[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH RFC 16/36] 9pfs: introduce openat_nofollow() helper
From: |
Greg Kurz |
Subject: |
[Qemu-devel] [PATCH RFC 16/36] 9pfs: introduce openat_nofollow() helper |
Date: |
Mon, 30 Jan 2017 13:11:39 +0100 |
User-agent: |
StGit/0.17.1-20-gc0b1b-dirty |
When using the passthrough security mode, symbolic links created by the
guest are actual symbolic links on the host file system.
Since the resolution of symbolic links during path walk is supposed to
occur on the client side. The server should never have to follow them.
The current code hence relies on O_NOFOLLOW and "l*()" variants of system
calls. Unfortunately, this only applies to the rightmost path component.
A guest could maliciously replace any component in a trusted path with a
symbolic link. This could allow any guest to escape a virtfs shared folder.
This patch introduces a variant of the openat() syscall that successively
opens each path element with O_NOFOLLOW. It will be used by subsequent
patches to implement symlink-safe path walk for any access to the backend.
Suggested-by: Jann Horn <address@hidden>
Signed-off-by: Greg Kurz <address@hidden>
---
hw/9pfs/9p-util.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++
hw/9pfs/9p-util.h | 25 ++++++++++++++++++
hw/9pfs/Makefile.objs | 2 +
3 files changed, 95 insertions(+), 1 deletion(-)
create mode 100644 hw/9pfs/9p-util.c
create mode 100644 hw/9pfs/9p-util.h
diff --git a/hw/9pfs/9p-util.c b/hw/9pfs/9p-util.c
new file mode 100644
index 000000000000..48292d948401
--- /dev/null
+++ b/hw/9pfs/9p-util.c
@@ -0,0 +1,69 @@
+/*
+ * 9p 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.
+ */
+
+#include "qemu/osdep.h"
+#include "9p-util.h"
+
+int openat_nofollow(int dirfd, const char *path, int flags, mode_t mode)
+{
+ const char *tail = path;
+ const char *c;
+ int fd;
+
+ fd = dup(dirfd);
+ if (fd == -1) {
+ return -1;
+ }
+
+ while (*tail) {
+ int next_fd;
+ char *head;
+
+ while (*tail == '/') {
+ tail++;
+ }
+
+ if (!*tail) {
+ break;
+ }
+
+ head = g_strdup(tail);
+ c = strchr(tail, '/');
+ if (c) {
+ head[c - tail] = 0;
+ next_fd = openat(fd, head, O_DIRECTORY | O_RDONLY | O_NOFOLLOW);
+ } else {
+ /* We don't want bad things to happen like opening a file that
+ * sits outside the virtfs export, or hanging on a named pipe,
+ * or changing the controlling process of a terminal.
+ */
+ flags |= O_NOFOLLOW | O_NONBLOCK | O_NOCTTY;
+ next_fd = openat(fd, head, flags, mode);
+ }
+ g_free(head);
+ if (next_fd == -1) {
+ close_preserve_errno(fd);
+ return -1;
+ }
+ close(fd);
+ fd = next_fd;
+
+ if (!c) {
+ break;
+ }
+ tail = c + 1;
+ }
+ /* O_NONBLOCK was only needed to open the file. Let's drop it. */
+ assert(!fcntl(fd, F_SETFL, flags));
+
+ return fd;
+}
diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h
new file mode 100644
index 000000000000..e19673d85222
--- /dev/null
+++ b/hw/9pfs/9p-util.h
@@ -0,0 +1,25 @@
+/*
+ * 9p 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_UTIL_H
+#define QEMU_9P_UTIL_H
+
+static inline void close_preserve_errno(int fd)
+{
+ int serrno = errno;
+ close(fd);
+ errno = serrno;
+}
+
+int openat_nofollow(int dirfd, const char *path, int flags, mode_t mode);
+
+#endif
diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs
index da0ae0cfdbae..32197e6671dd 100644
--- a/hw/9pfs/Makefile.objs
+++ b/hw/9pfs/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-y = 9p.o
+common-obj-y = 9p.o 9p-util.o
common-obj-y += 9p-local.o 9p-xattr.o
common-obj-y += 9p-xattr-user.o 9p-posix-acl.o
common-obj-y += coth.o cofs.o codir.o cofile.o
- [Qemu-devel] [PATCH RFC 08/36] 9pfs: local: improve error handling in link op, (continued)
- [Qemu-devel] [PATCH RFC 08/36] 9pfs: local: improve error handling in link op, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 09/36] 9pfs: local: post link operation for mapped-file security, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 07/36] 9pfs: local: split mkdir operation per security model, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 10/36] v9fs: local: improve error handling in rename op, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 11/36] 9pfs: local: post rename operation for mapped-file security, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 12/36] 9pfs: local: pre remove operation for mapped-file security, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 06/36] 9pfs: local: split symlink operation per security model, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 13/36] 9pfs: local: pre unlikat operation for mapped-file security, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 14/36] 9pfs: remove side-effects in local_init(), Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 15/36] 9pfs: remove side-effects in local_open() and local_opendir(), Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 16/36] 9pfs: introduce openat_nofollow() helper,
Greg Kurz <=
- [Qemu-devel] [PATCH RFC 17/36] 9pfs: local: keep a file descriptor on the shared folder, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 18/36] 9pfs: local: open/opendir: don't follow symlinks, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 19/36] 9pfs: local: utimensat: don't follow symlinks, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 20/36] 9pfs: local: readlink: don't follow symlinks, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 21/36] 9pfs: local: truncate: don't follow symlinks, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 22/36] 9pfs: local: statfs: don't follow symlinks, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 23/36] 9pfs: local: mknod/mkdir/open2: don't follow symlinks, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 24/36] 9pfs: local: chmod: don't follow symlinks, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 25/36] 9pfs: local: symlink: don't follow symlinks, Greg Kurz, 2017/01/30
- [Qemu-devel] [PATCH RFC 26/36] 9pfs: local: chown: don't follow symlinks, Greg Kurz, 2017/01/30