[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 06/29] 9pfs: local: open/opendir: don't follow symli
From: |
Greg Kurz |
Subject: |
[Qemu-devel] [PATCH 06/29] 9pfs: local: open/opendir: don't follow symlinks |
Date: |
Mon, 20 Feb 2017 15:40:07 +0100 |
User-agent: |
StGit/0.17.1-20-gc0b1b-dirty |
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>
---
hw/9pfs/9p-local.c | 31 +++++++++++++++++++++----------
hw/9pfs/9p-local.h | 20 ++++++++++++++++++++
2 files changed, 41 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 8aee7f2516ed..26ea72c66306 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,18 @@ struct local_data {
int mountfd;
};
+int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags,
+ mode_t mode)
+{
+ struct local_data *data = fs_ctx->private;
+ return 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 +372,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 +385,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
- Re: [Qemu-devel] [PATCH 01/29] 9pfs: local: move xattr security ops to 9p-xattr.c, (continued)
- [Qemu-devel] [PATCH 02/29] 9pfs: remove side-effects in local_init(), Greg Kurz, 2017/02/20
- [Qemu-devel] [PATCH 03/29] 9pfs: remove side-effects in local_open() and local_opendir(), Greg Kurz, 2017/02/20
- [Qemu-devel] [PATCH 04/29] 9pfs: introduce openat_nofollow() helper, Greg Kurz, 2017/02/20
- [Qemu-devel] [PATCH 05/29] 9pfs: local: keep a file descriptor on the shared folder, Greg Kurz, 2017/02/20
- [Qemu-devel] [PATCH 06/29] 9pfs: local: open/opendir: don't follow symlinks,
Greg Kurz <=
- [Qemu-devel] [PATCH 07/29] 9pfs: local: introduce symlink-attack safe xattr helpers, Greg Kurz, 2017/02/20
- [Qemu-devel] [PATCH 08/29] 9pfs: local: lgetxattr: don't follow symlinks, Greg Kurz, 2017/02/20