qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH RFC 05/36] 9pfs: local: split open2 operation per se


From: Greg Kurz
Subject: [Qemu-devel] [PATCH RFC 05/36] 9pfs: local: split open2 operation per security model
Date: Mon, 30 Jan 2017 13:10:14 +0100
User-agent: StGit/0.17.1-20-gc0b1b-dirty

Having all security models implemented in one monolithic function is
cumbersome. Especially when the need arises to fix something in the
shared code, as it forces to change all the paths at the same time.

This doesn't fix any bug, it is just preparatory cleanup.

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

diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 0d6869123094..4deb19ce8775 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -785,8 +785,9 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
     return err;
 }
 
-static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
-                       int flags, FsCred *credp, V9fsFidOpenState *fs)
+static int local_open2_mapped(FsContext *fs_ctx, V9fsPath *dir_path,
+                              const char *name, int flags, FsCred *credp,
+                              V9fsFidOpenState *fs)
 {
     char *path;
     int fd = -1;
@@ -804,48 +805,65 @@ static int local_open2(FsContext *fs_ctx, V9fsPath 
*dir_path, const char *name,
     v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
     path = fullname.data;
 
-    /* Determine the security model */
-    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
-        buffer = rpath(fs_ctx, path);
-        fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
-        if (fd == -1) {
-            err = fd;
-            goto out;
-        }
-        credp->fc_mode = credp->fc_mode|S_IFREG;
-        /* Set cleint credentials in xattr */
-        err = local_set_xattr(buffer, credp);
-        if (err == -1) {
-            serrno = errno;
-            goto err_end;
-        }
-    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
-        buffer = rpath(fs_ctx, path);
-        fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
-        if (fd == -1) {
-            err = fd;
-            goto out;
-        }
-        credp->fc_mode = credp->fc_mode|S_IFREG;
-        /* Set client credentials in .virtfs_metadata directory files */
-        err = local_set_mapped_file_attr(fs_ctx, path, credp);
-        if (err == -1) {
-            serrno = errno;
-            goto err_end;
-        }
-    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
-               (fs_ctx->export_flags & V9FS_SM_NONE)) {
-        buffer = rpath(fs_ctx, path);
-        fd = open(buffer, flags, credp->fc_mode);
-        if (fd == -1) {
-            err = fd;
-            goto out;
-        }
-        err = local_post_create_passthrough(fs_ctx, path, credp);
-        if (err == -1) {
-            serrno = errno;
-            goto err_end;
-        }
+    buffer = rpath(fs_ctx, path);
+    fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
+    if (fd == -1) {
+        err = fd;
+        goto out;
+    }
+    credp->fc_mode = credp->fc_mode | S_IFREG;
+    /* Set cleint credentials in xattr */
+    err = local_set_xattr(buffer, credp);
+    if (err == -1) {
+        serrno = errno;
+        goto err_end;
+    }
+    err = fd;
+    fs->fd = fd;
+    goto out;
+
+err_end:
+    close(fd);
+    remove(buffer);
+    errno = serrno;
+out:
+    g_free(buffer);
+    v9fs_string_free(&fullname);
+    return err;
+}
+
+static int local_open2_mapped_file(FsContext *fs_ctx, V9fsPath *dir_path,
+                                   const char *name, int flags, FsCred *credp,
+                                   V9fsFidOpenState *fs)
+{
+    char *path;
+    int fd = -1;
+    int err = -1;
+    int serrno = 0;
+    V9fsString fullname;
+    char *buffer = NULL;
+
+    /*
+     * Mark all the open to not follow symlinks
+     */
+    flags |= O_NOFOLLOW;
+
+    v9fs_string_init(&fullname);
+    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+    path = fullname.data;
+
+    buffer = rpath(fs_ctx, path);
+    fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
+    if (fd == -1) {
+        err = fd;
+        goto out;
+    }
+    credp->fc_mode = credp->fc_mode | S_IFREG;
+    /* Set client credentials in .virtfs_metadata directory files */
+    err = local_set_mapped_file_attr(fs_ctx, path, credp);
+    if (err == -1) {
+        serrno = errno;
+        goto err_end;
     }
     err = fd;
     fs->fd = fd;
@@ -861,6 +879,67 @@ out:
     return err;
 }
 
+static int local_open2_passthrough(FsContext *fs_ctx, V9fsPath *dir_path,
+                                   const char *name, int flags, FsCred *credp,
+                                   V9fsFidOpenState *fs)
+{
+    char *path;
+    int fd = -1;
+    int err = -1;
+    int serrno = 0;
+    V9fsString fullname;
+    char *buffer = NULL;
+
+    /*
+     * Mark all the open to not follow symlinks
+     */
+    flags |= O_NOFOLLOW;
+
+    v9fs_string_init(&fullname);
+    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+    path = fullname.data;
+
+    buffer = rpath(fs_ctx, path);
+    fd = open(buffer, flags, credp->fc_mode);
+    if (fd == -1) {
+        err = fd;
+        goto out;
+    }
+    err = local_post_create_passthrough(fs_ctx, path, credp);
+    if (err == -1) {
+        serrno = errno;
+        goto err_end;
+    }
+    err = fd;
+    fs->fd = fd;
+    goto out;
+
+err_end:
+    close(fd);
+    remove(buffer);
+    errno = serrno;
+out:
+    g_free(buffer);
+    v9fs_string_free(&fullname);
+    return err;
+}
+
+static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
+                       int flags, FsCred *credp, V9fsFidOpenState *fs)
+{
+    /* Determine the security model */
+    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
+        return local_open2_mapped(fs_ctx, dir_path, name, flags, credp, fs);
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        return local_open2_mapped_file(fs_ctx, dir_path, name, flags, credp,
+                                       fs);
+    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
+               (fs_ctx->export_flags & V9FS_SM_NONE)) {
+        return local_open2_passthrough(fs_ctx, dir_path, name, flags, credp,
+                                       fs);
+    }
+    g_assert_not_reached();
+}
 
 static int local_symlink(FsContext *fs_ctx, const char *oldpath,
                          V9fsPath *dir_path, const char *name, FsCred *credp)




reply via email to

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