qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH RFC 29/36] 9pfs: local: remove: don't follow symlink


From: Greg Kurz
Subject: [Qemu-devel] [PATCH RFC 29/36] 9pfs: local: remove: don't follow symlinks
Date: Mon, 30 Jan 2017 13:13:18 +0100
User-agent: StGit/0.17.1-20-gc0b1b-dirty

This fixes CVE-2016-9602 for the "passthrough" and "mapped" security models.

Signed-off-by: Greg Kurz <address@hidden>
---
 hw/9pfs/9p-local.c |   28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 364da435350b..573852a55a00 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -1432,8 +1432,17 @@ err_out:
 
 static int local_remove(FsContext *ctx, const char *path)
 {
-    int err;
-    char *buffer;
+    char *dirpath = local_dirname(path);
+    char *name = local_basename(path);
+    struct stat stbuf;
+    int flags = 0;
+    int err = -1;
+    int dirfd;
+
+    dirfd = local_opendir_nofollow(ctx, dirpath);
+    if (dirfd) {
+        goto out;
+    }
 
     if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
         err =  local_pre_remove_mapped_file(ctx, path);
@@ -1442,10 +1451,19 @@ static int local_remove(FsContext *ctx, const char 
*path)
         }
     }
 
-    buffer = rpath(ctx, path);
-    err = remove(buffer);
-    g_free(buffer);
+    if (fstatat(dirfd, path, &stbuf, AT_SYMLINK_NOFOLLOW) < 0) {
+        goto err_out;
+    }
+    if (S_ISDIR(stbuf.st_mode)) {
+        flags |= AT_REMOVEDIR;
+    }
+
+    err = unlinkat(dirfd, name, flags);
 err_out:
+    close_preserve_errno(dirfd);
+out:
+    g_free(name);
+    g_free(dirpath);
     return err;
 }
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]