summaryrefslogtreecommitdiffstats
path: root/patches/qemu-7.1.0/0100-9pfs-allow-real-symlinks-for-security_model-mapped-f.patch
blob: 6299ba1f61b5a33956a803140afba5197853b66c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
From: Michael Olbrich <m.olbrich@pengutronix.de>
Date: Tue, 25 Oct 2016 12:39:03 +0200
Subject: [PATCH] 9pfs: allow real symlinks for security_model=mapped-file

And create real symlinks if possible. This makes it possible to use the
same filesystem with security_model=mapped-file and security_model=none.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
---
 hw/9pfs/9p-local.c | 44 +++++++++++++++++++++++++++++---------------
 1 file changed, 29 insertions(+), 15 deletions(-)

diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index d42ce6d8b822..559573008eec 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -462,8 +462,7 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
 {
     ssize_t tsize = -1;
 
-    if ((fs_ctx->export_flags & V9FS_SM_MAPPED) ||
-        (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
+    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         int fd;
 
         fd = local_open_nofollow(fs_ctx, fs_path->data, O_RDONLY, 0);
@@ -475,6 +474,7 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
         } while (tsize == -1 && errno == EINTR);
         close_preserve_errno(fd);
     } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
+               (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) ||
                (fs_ctx->export_flags & V9FS_SM_NONE)) {
         char *dirpath = g_path_get_dirname(fs_path->data);
         char *name = g_path_get_basename(fs_path->data);
@@ -486,6 +486,17 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
         }
 
         tsize = readlinkat(dirfd, name, buf, bufsz);
+
+        if (tsize == -1 && (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
+            int fd = openat_file(dirfd, name, O_RDONLY, 0);
+            if (fd == -1) {
+                goto out;
+            }
+            do {
+                tsize = read(fd, (void *)buf, bufsz);
+            } while (tsize == -1 && errno == EINTR);
+            close_preserve_errno(fd);
+        }
         close_preserve_errno(dirfd);
     out:
         g_free(name);
@@ -901,20 +912,23 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
         int fd;
         ssize_t oldpath_size, write_size;
 
-        fd = openat_file(dirfd, name, O_CREAT | O_EXCL | O_RDWR,
-                         fs_ctx->fmode);
-        if (fd == -1) {
-            goto out;
-        }
-        /* Write the oldpath (target) to the file. */
-        oldpath_size = strlen(oldpath);
-        do {
-            write_size = write(fd, (void *)oldpath, oldpath_size);
-        } while (write_size == -1 && errno == EINTR);
-        close_preserve_errno(fd);
+        if (fs_ctx->export_flags & V9FS_SM_MAPPED ||
+            (symlinkat(oldpath, dirfd, name) != 0)) {
+            fd = openat_file(dirfd, name, O_CREAT | O_EXCL | O_RDWR,
+                             fs_ctx->fmode);
+            if (fd == -1) {
+                goto out;
+            }
+            /* Write the oldpath (target) to the file. */
+            oldpath_size = strlen(oldpath);
+            do {
+                write_size = write(fd, (void *)oldpath, oldpath_size);
+            } while (write_size == -1 && errno == EINTR);
+            close_preserve_errno(fd);
 
-        if (write_size != oldpath_size) {
-            goto err_end;
+            if (write_size != oldpath_size) {
+                goto err_end;
+            }
         }
         /* Set cleint credentials in symlink's xattr */
         credp->fc_mode = credp->fc_mode | S_IFLNK;