xref: /qemu/hw/9pfs/9p-posix-acl.c (revision a976a99a)
1 /*
2  * 9p system.posix* xattr callback
3  *
4  * Copyright IBM, Corp. 2010
5  *
6  * Authors:
7  * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.  See
10  * the COPYING file in the top-level directory.
11  *
12  */
13 
14 /*
15  * Not so fast! You might want to read the 9p developer docs first:
16  * https://wiki.qemu.org/Documentation/9p
17  */
18 
19 #include "qemu/osdep.h"
20 #include "qemu/xattr.h"
21 #include "9p.h"
22 #include "fsdev/file-op-9p.h"
23 #include "9p-xattr.h"
24 
25 #define MAP_ACL_ACCESS "user.virtfs.system.posix_acl_access"
26 #define MAP_ACL_DEFAULT "user.virtfs.system.posix_acl_default"
27 #define ACL_ACCESS "system.posix_acl_access"
28 #define ACL_DEFAULT "system.posix_acl_default"
29 
30 static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
31                                 const char *name, void *value, size_t size)
32 {
33     return local_getxattr_nofollow(ctx, path, MAP_ACL_ACCESS, value, size);
34 }
35 
36 static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
37                                  char *name, void *value, size_t osize)
38 {
39     ssize_t len = sizeof(ACL_ACCESS);
40 
41     if (!value) {
42         return len;
43     }
44 
45     if (osize < len) {
46         errno = ERANGE;
47         return -1;
48     }
49 
50     /* len includes the trailing NUL */
51     memcpy(value, ACL_ACCESS, len);
52     return 0;
53 }
54 
55 static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
56                             void *value, size_t size, int flags)
57 {
58     return local_setxattr_nofollow(ctx, path, MAP_ACL_ACCESS, value, size,
59                                    flags);
60 }
61 
62 static int mp_pacl_removexattr(FsContext *ctx,
63                                const char *path, const char *name)
64 {
65     int ret;
66 
67     ret = local_removexattr_nofollow(ctx, path, MAP_ACL_ACCESS);
68     /*
69      * macOS returns ENOATTR (!=ENODATA on macOS), whereas Linux returns
70      * ENODATA (==ENOATTR on Linux), so checking for ENOATTR is fine
71      */
72     if (ret == -1 && errno == ENOATTR) {
73         /*
74          * We don't get ENODATA error when trying to remove a
75          * posix acl that is not present. So don't throw the error
76          * even in case of mapped security model
77          */
78         errno = 0;
79         ret = 0;
80     }
81     return ret;
82 }
83 
84 static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
85                                 const char *name, void *value, size_t size)
86 {
87     return local_getxattr_nofollow(ctx, path, MAP_ACL_DEFAULT, value, size);
88 }
89 
90 static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
91                                  char *name, void *value, size_t osize)
92 {
93     ssize_t len = sizeof(ACL_DEFAULT);
94 
95     if (!value) {
96         return len;
97     }
98 
99     if (osize < len) {
100         errno = ERANGE;
101         return -1;
102     }
103 
104     /* len includes the trailing NUL */
105     memcpy(value, ACL_DEFAULT, len);
106     return 0;
107 }
108 
109 static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
110                             void *value, size_t size, int flags)
111 {
112     return local_setxattr_nofollow(ctx, path, MAP_ACL_DEFAULT, value, size,
113                                    flags);
114 }
115 
116 static int mp_dacl_removexattr(FsContext *ctx,
117                                const char *path, const char *name)
118 {
119     int ret;
120 
121     ret = local_removexattr_nofollow(ctx, path, MAP_ACL_DEFAULT);
122     /*
123      * macOS returns ENOATTR (!=ENODATA on macOS), whereas Linux returns
124      * ENODATA (==ENOATTR on Linux), so checking for ENOATTR is fine
125      */
126     if (ret == -1 && errno == ENOATTR) {
127         /*
128          * We don't get ENODATA error when trying to remove a
129          * posix acl that is not present. So don't throw the error
130          * even in case of mapped security model
131          */
132         errno = 0;
133         ret = 0;
134     }
135     return ret;
136 }
137 
138 
139 XattrOperations mapped_pacl_xattr = {
140     .name = "system.posix_acl_access",
141     .getxattr = mp_pacl_getxattr,
142     .setxattr = mp_pacl_setxattr,
143     .listxattr = mp_pacl_listxattr,
144     .removexattr = mp_pacl_removexattr,
145 };
146 
147 XattrOperations mapped_dacl_xattr = {
148     .name = "system.posix_acl_default",
149     .getxattr = mp_dacl_getxattr,
150     .setxattr = mp_dacl_setxattr,
151     .listxattr = mp_dacl_listxattr,
152     .removexattr = mp_dacl_removexattr,
153 };
154 
155 XattrOperations passthrough_acl_xattr = {
156     .name = "system.posix_acl_",
157     .getxattr = pt_getxattr,
158     .setxattr = pt_setxattr,
159     .listxattr = pt_listxattr,
160     .removexattr = pt_removexattr,
161 };
162 
163 XattrOperations none_acl_xattr = {
164     .name = "system.posix_acl_",
165     .getxattr = notsup_getxattr,
166     .setxattr = notsup_setxattr,
167     .listxattr = notsup_listxattr,
168     .removexattr = notsup_removexattr,
169 };
170