[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 09/31] 9pfs: local: open/opendir: don't follow symlin
From: |
Greg Kurz |
Subject: |
[Qemu-devel] [PULL 09/31] 9pfs: local: open/opendir: don't follow symlinks |
Date: |
Mon, 27 Feb 2017 23:59:59 +0100 |
The local_open() and local_opendir() callbacks are vulnerable to symlink
attacks because they call:
(1) open(O_NOFOLLOW) which follows symbolic links in all path elements but
the rightmost one
(2) opendir() which follows symbolic links in all path elements
This patch converts both callbacks to use new helpers based on
openat_nofollow() to only open files and directories if they are
below the virtfs shared folder
This partly fixes CVE-2016-9602.
Signed-off-by: Greg Kurz <address@hidden>
Reviewed-by: Stefan Hajnoczi <address@hidden>
---
hw/9pfs/9p-local.c | 37 +++++++++++++++++++++++++++----------
hw/9pfs/9p-local.h | 20 ++++++++++++++++++++
2 files changed, 47 insertions(+), 10 deletions(-)
create mode 100644 hw/9pfs/9p-local.h
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index b58d0bc65439..af5f430e6c8e 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -13,6 +13,7 @@
#include "qemu/osdep.h"
#include "9p.h"
+#include "9p-local.h"
#include "9p-xattr.h"
#include "9p-util.h"
#include "fsdev/qemu-fsdev.h" /* local_ops */
@@ -48,6 +49,24 @@ typedef struct {
int mountfd;
} LocalData;
+int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags,
+ mode_t mode)
+{
+ LocalData *data = fs_ctx->private;
+
+ /* All paths are relative to the path data->mountfd points to */
+ while (*path == '/') {
+ path++;
+ }
+
+ return relative_openat_nofollow(data->mountfd, path, flags, mode);
+}
+
+int local_opendir_nofollow(FsContext *fs_ctx, const char *path)
+{
+ return local_open_nofollow(fs_ctx, path, O_DIRECTORY | O_RDONLY, 0);
+}
+
#define VIRTFS_META_DIR ".virtfs_metadata"
static char *local_mapped_attr_path(FsContext *ctx, const char *path)
@@ -359,13 +378,9 @@ static int local_closedir(FsContext *ctx, V9fsFidOpenState
*fs)
static int local_open(FsContext *ctx, V9fsPath *fs_path,
int flags, V9fsFidOpenState *fs)
{
- char *buffer;
- char *path = fs_path->data;
int fd;
- buffer = rpath(ctx, path);
- fd = open(buffer, flags | O_NOFOLLOW);
- g_free(buffer);
+ fd = local_open_nofollow(ctx, fs_path->data, flags, 0);
if (fd == -1) {
return -1;
}
@@ -376,13 +391,15 @@ static int local_open(FsContext *ctx, V9fsPath *fs_path,
static int local_opendir(FsContext *ctx,
V9fsPath *fs_path, V9fsFidOpenState *fs)
{
- char *buffer;
- char *path = fs_path->data;
+ int dirfd;
DIR *stream;
- buffer = rpath(ctx, path);
- stream = opendir(buffer);
- g_free(buffer);
+ dirfd = local_opendir_nofollow(ctx, fs_path->data);
+ if (dirfd == -1) {
+ return -1;
+ }
+
+ stream = fdopendir(dirfd);
if (!stream) {
return -1;
}
diff --git a/hw/9pfs/9p-local.h b/hw/9pfs/9p-local.h
new file mode 100644
index 000000000000..32c72749d9df
--- /dev/null
+++ b/hw/9pfs/9p-local.h
@@ -0,0 +1,20 @@
+/*
+ * 9p local backend utilities
+ *
+ * Copyright IBM, Corp. 2017
+ *
+ * Authors:
+ * Greg Kurz <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_9P_LOCAL_H
+#define QEMU_9P_LOCAL_H
+
+int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags,
+ mode_t mode);
+int local_opendir_nofollow(FsContext *fs_ctx, const char *path);
+
+#endif
--
2.7.4
- [Qemu-devel] [PULL 16/31] 9pfs: local: utimensat: don't follow symlinks, (continued)
- [Qemu-devel] [PULL 16/31] 9pfs: local: utimensat: don't follow symlinks, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 04/31] 9pfs: local: move xattr security ops to 9p-xattr.c, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 14/31] 9pfs: local: unlinkat: don't follow symlinks, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 17/31] 9pfs: local: statfs: don't follow symlinks, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 19/31] 9pfs: local: readlink: don't follow symlinks, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 20/31] 9pfs: local: lstat: don't follow symlinks, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 23/31] 9pfs: local: improve error handling in link op, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 26/31] 9pfs: local: chown: don't follow symlinks, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 18/31] 9pfs: local: truncate: don't follow symlinks, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 22/31] 9pfs: local: rename: use renameat, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 09/31] 9pfs: local: open/opendir: don't follow symlinks,
Greg Kurz <=
- [Qemu-devel] [PULL 30/31] 9pfs: local: open2: don't follow symlinks, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 29/31] 9pfs: local: mkdir: don't follow symlinks, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 31/31] 9pfs: local: drop unused code, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 28/31] 9pfs: local: mknod: don't follow symlinks, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 24/31] 9pfs: local: link: don't follow symlinks, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 27/31] 9pfs: local: symlink: don't follow symlinks, Greg Kurz, 2017/02/27
- [Qemu-devel] [PULL 25/31] 9pfs: local: chmod: don't follow symlinks, Greg Kurz, 2017/02/27
- Re: [Qemu-devel] [PULL 00/31] 9p patches 2017-02-27 for 2.9 soft freeze, no-reply, 2017/02/27
- Re: [Qemu-devel] [PULL 00/31] 9p patches 2017-02-27 for 2.9 soft freeze, no-reply, 2017/02/27