qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] 9pfs: fix vulnerability in openat_dir() and local_unlinkat_common()
@ 2017-03-03 17:25 Greg Kurz
  2017-03-03 17:28 ` Daniel P. Berrange
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Greg Kurz @ 2017-03-03 17:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: Eric Blake, Daniel P. Berrange, Mark Cave-Ayland, Greg Kurz

We should pass O_NOFOLLOW otherwise openat() will follow symlinks and make
QEMU vulnerable.

O_PATH was used as an optimization: the fd returned by openat_dir() is only
passed to openat() actually, so we don't really need to reach the underlying
filesystem.

O_NOFOLLOW | O_PATH isn't an option: if name is a symlink, openat() will
return a fd, forcing us to do some other syscall to detect we have a
symlink. Also, O_PATH doesn't exist in glibc 2.13 and older.

The only sane thing to do is hence to drop O_PATH, and only pass O_NOFOLLOW.

While here, we also fix local_unlinkat_common() to use openat_dir() for
the same reasons (it was a leftover in the original patchset actually).

This fixes CVE-2016-9602.

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 hw/9pfs/9p-local.c |    2 +-
 hw/9pfs/9p-util.h  |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 5db7104334d6..e31309a29c58 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -959,7 +959,7 @@ static int local_unlinkat_common(FsContext *ctx, int dirfd, const char *name,
         if (flags == AT_REMOVEDIR) {
             int fd;
 
-            fd = openat(dirfd, name, O_RDONLY | O_DIRECTORY | O_PATH);
+            fd = openat_dir(dirfd, name);
             if (fd == -1) {
                 goto err_out;
             }
diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h
index 091f3ce88e15..4001d1fd8398 100644
--- a/hw/9pfs/9p-util.h
+++ b/hw/9pfs/9p-util.h
@@ -22,7 +22,7 @@ static inline void close_preserve_errno(int fd)
 
 static inline int openat_dir(int dirfd, const char *name)
 {
-    return openat(dirfd, name, O_DIRECTORY | O_RDONLY | O_PATH);
+    return openat(dirfd, name, O_DIRECTORY | O_RDONLY | O_NOFOLLOW);
 }
 
 static inline int openat_file(int dirfd, const char *name, int flags,

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-03-04 15:17 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-03-03 17:25 [Qemu-devel] [PATCH] 9pfs: fix vulnerability in openat_dir() and local_unlinkat_common() Greg Kurz
2017-03-03 17:28 ` Daniel P. Berrange
2017-03-03 17:54 ` Mark Cave-Ayland
2017-03-03 19:04   ` Greg Kurz
2017-03-03 18:14 ` Eric Blake
2017-03-03 19:08   ` Greg Kurz
2017-03-03 23:43   ` Eric Blake
2017-03-04 11:21     ` Greg Kurz
2017-03-04 13:55       ` Mark Cave-Ayland
2017-03-04 15:17       ` Eric Blake

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).