qemu-devel
[Top][All Lists]
Advanced

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

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


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

This fixes CVE-2016-9602 for the "passthrough" security model.

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

diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 9dfa3e306245..bbc08184564f 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -1100,29 +1100,25 @@ static int local_symlink_passthrough(FsContext *fs_ctx, 
const char *oldpath,
                                      V9fsPath *dir_path, const char *name,
                                      FsCred *credp)
 {
-    int err = -1;
-    int serrno = 0;
-    char *newpath;
-    V9fsString fullname;
-    char *buffer = NULL;
+    int dirfd, err;
 
-    v9fs_string_init(&fullname);
-    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
-    newpath = fullname.data;
+    dirfd = local_opendir_nofollow(fs_ctx, dir_path->data);
+    if (dirfd == -1) {
+        return -1;
+    }
 
-    buffer = rpath(fs_ctx, newpath);
-    err = symlink(oldpath, buffer);
+    err = symlinkat(oldpath, dirfd, name);
     if (err) {
         goto out;
     }
-    err = lchown(buffer, credp->fc_uid, credp->fc_gid);
+    err = fchownat(dirfd, name, credp->fc_uid, credp->fc_gid,
+                   AT_SYMLINK_NOFOLLOW);
     if (err == -1) {
         /*
          * If we fail to change ownership and if we are
          * using security model none. Ignore the error
          */
         if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
-            serrno = errno;
             goto err_end;
         } else {
             err = 0;
@@ -1131,11 +1127,9 @@ static int local_symlink_passthrough(FsContext *fs_ctx, 
const char *oldpath,
     goto out;
 
 err_end:
-    remove(buffer);
-    errno = serrno;
+    unlinkat_preserve_errno(dirfd, name, 0);
 out:
-    g_free(buffer);
-    v9fs_string_free(&fullname);
+    close_preserve_errno(dirfd);
     return err;
 }
 




reply via email to

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