xref: /qemu/hw/9pfs/9p-posix-acl.c (revision f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65)
170fc55ebSAneesh Kumar K.V /*
2d57b7800SWei Liu  * 9p system.posix* xattr callback
370fc55ebSAneesh Kumar K.V  *
470fc55ebSAneesh Kumar K.V  * Copyright IBM, Corp. 2010
570fc55ebSAneesh Kumar K.V  *
670fc55ebSAneesh Kumar K.V  * Authors:
770fc55ebSAneesh Kumar K.V  * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
870fc55ebSAneesh Kumar K.V  *
970fc55ebSAneesh Kumar K.V  * This work is licensed under the terms of the GNU GPL, version 2.  See
1070fc55ebSAneesh Kumar K.V  * the COPYING file in the top-level directory.
1170fc55ebSAneesh Kumar K.V  *
1270fc55ebSAneesh Kumar K.V  */
1370fc55ebSAneesh Kumar K.V 
146f569084SChristian Schoenebeck /*
156f569084SChristian Schoenebeck  * Not so fast! You might want to read the 9p developer docs first:
166f569084SChristian Schoenebeck  * https://wiki.qemu.org/Documentation/9p
176f569084SChristian Schoenebeck  */
186f569084SChristian Schoenebeck 
19fbc04127SPeter Maydell #include "qemu/osdep.h"
201de7afc9SPaolo Bonzini #include "qemu/xattr.h"
21ebe74f8bSWei Liu #include "9p.h"
22353ac78dSAneesh Kumar K.V #include "fsdev/file-op-9p.h"
23267ae092SWei Liu #include "9p-xattr.h"
2470fc55ebSAneesh Kumar K.V 
2570fc55ebSAneesh Kumar K.V #define MAP_ACL_ACCESS "user.virtfs.system.posix_acl_access"
2670fc55ebSAneesh Kumar K.V #define MAP_ACL_DEFAULT "user.virtfs.system.posix_acl_default"
2770fc55ebSAneesh Kumar K.V #define ACL_ACCESS "system.posix_acl_access"
2870fc55ebSAneesh Kumar K.V #define ACL_DEFAULT "system.posix_acl_default"
2970fc55ebSAneesh Kumar K.V 
mp_pacl_getxattr(FsContext * ctx,const char * path,const char * name,void * value,size_t size)3070fc55ebSAneesh Kumar K.V static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
3170fc55ebSAneesh Kumar K.V                                 const char *name, void *value, size_t size)
3270fc55ebSAneesh Kumar K.V {
3356ad3e54SGreg Kurz     return local_getxattr_nofollow(ctx, path, MAP_ACL_ACCESS, value, size);
3470fc55ebSAneesh Kumar K.V }
3570fc55ebSAneesh Kumar K.V 
mp_pacl_listxattr(FsContext * ctx,const char * path,char * name,void * value,size_t osize)3670fc55ebSAneesh Kumar K.V static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
3770fc55ebSAneesh Kumar K.V                                  char *name, void *value, size_t osize)
3870fc55ebSAneesh Kumar K.V {
3970fc55ebSAneesh Kumar K.V     ssize_t len = sizeof(ACL_ACCESS);
4070fc55ebSAneesh Kumar K.V 
4170fc55ebSAneesh Kumar K.V     if (!value) {
4270fc55ebSAneesh Kumar K.V         return len;
4370fc55ebSAneesh Kumar K.V     }
4470fc55ebSAneesh Kumar K.V 
4570fc55ebSAneesh Kumar K.V     if (osize < len) {
4670fc55ebSAneesh Kumar K.V         errno = ERANGE;
4770fc55ebSAneesh Kumar K.V         return -1;
4870fc55ebSAneesh Kumar K.V     }
4970fc55ebSAneesh Kumar K.V 
509238c209SJim Meyering     /* len includes the trailing NUL */
519238c209SJim Meyering     memcpy(value, ACL_ACCESS, len);
5270fc55ebSAneesh Kumar K.V     return 0;
5370fc55ebSAneesh Kumar K.V }
5470fc55ebSAneesh Kumar K.V 
mp_pacl_setxattr(FsContext * ctx,const char * path,const char * name,void * value,size_t size,int flags)5570fc55ebSAneesh Kumar K.V static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
5670fc55ebSAneesh Kumar K.V                             void *value, size_t size, int flags)
5770fc55ebSAneesh Kumar K.V {
583e36aba7SGreg Kurz     return local_setxattr_nofollow(ctx, path, MAP_ACL_ACCESS, value, size,
593e36aba7SGreg Kurz                                    flags);
6070fc55ebSAneesh Kumar K.V }
6170fc55ebSAneesh Kumar K.V 
mp_pacl_removexattr(FsContext * ctx,const char * path,const char * name)6270fc55ebSAneesh Kumar K.V static int mp_pacl_removexattr(FsContext *ctx,
6370fc55ebSAneesh Kumar K.V                                const char *path, const char *name)
6470fc55ebSAneesh Kumar K.V {
6570fc55ebSAneesh Kumar K.V     int ret;
664fa4ce71SChen Gang 
6772f0d0bfSGreg Kurz     ret = local_removexattr_nofollow(ctx, path, MAP_ACL_ACCESS);
68*9ea31646SChristian Schoenebeck     /*
69*9ea31646SChristian Schoenebeck      * macOS returns ENOATTR (!=ENODATA on macOS), whereas Linux returns
70*9ea31646SChristian Schoenebeck      * ENODATA (==ENOATTR on Linux), so checking for ENOATTR is fine
71*9ea31646SChristian Schoenebeck      */
72*9ea31646SChristian Schoenebeck     if (ret == -1 && errno == ENOATTR) {
7370fc55ebSAneesh Kumar K.V         /*
74a0994761SAneesh Kumar K.V          * We don't get ENODATA error when trying to remove a
7570fc55ebSAneesh Kumar K.V          * posix acl that is not present. So don't throw the error
7670fc55ebSAneesh Kumar K.V          * even in case of mapped security model
7770fc55ebSAneesh Kumar K.V          */
7870fc55ebSAneesh Kumar K.V         errno = 0;
7970fc55ebSAneesh Kumar K.V         ret = 0;
8070fc55ebSAneesh Kumar K.V     }
8170fc55ebSAneesh Kumar K.V     return ret;
8270fc55ebSAneesh Kumar K.V }
8370fc55ebSAneesh Kumar K.V 
mp_dacl_getxattr(FsContext * ctx,const char * path,const char * name,void * value,size_t size)8470fc55ebSAneesh Kumar K.V static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
8570fc55ebSAneesh Kumar K.V                                 const char *name, void *value, size_t size)
8670fc55ebSAneesh Kumar K.V {
8756ad3e54SGreg Kurz     return local_getxattr_nofollow(ctx, path, MAP_ACL_DEFAULT, value, size);
8870fc55ebSAneesh Kumar K.V }
8970fc55ebSAneesh Kumar K.V 
mp_dacl_listxattr(FsContext * ctx,const char * path,char * name,void * value,size_t osize)9070fc55ebSAneesh Kumar K.V static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
9170fc55ebSAneesh Kumar K.V                                  char *name, void *value, size_t osize)
9270fc55ebSAneesh Kumar K.V {
9370fc55ebSAneesh Kumar K.V     ssize_t len = sizeof(ACL_DEFAULT);
9470fc55ebSAneesh Kumar K.V 
9570fc55ebSAneesh Kumar K.V     if (!value) {
9670fc55ebSAneesh Kumar K.V         return len;
9770fc55ebSAneesh Kumar K.V     }
9870fc55ebSAneesh Kumar K.V 
9970fc55ebSAneesh Kumar K.V     if (osize < len) {
10070fc55ebSAneesh Kumar K.V         errno = ERANGE;
10170fc55ebSAneesh Kumar K.V         return -1;
10270fc55ebSAneesh Kumar K.V     }
10370fc55ebSAneesh Kumar K.V 
1049238c209SJim Meyering     /* len includes the trailing NUL */
1059005c3b3SShannon Zhao     memcpy(value, ACL_DEFAULT, len);
10670fc55ebSAneesh Kumar K.V     return 0;
10770fc55ebSAneesh Kumar K.V }
10870fc55ebSAneesh Kumar K.V 
mp_dacl_setxattr(FsContext * ctx,const char * path,const char * name,void * value,size_t size,int flags)10970fc55ebSAneesh Kumar K.V static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
11070fc55ebSAneesh Kumar K.V                             void *value, size_t size, int flags)
11170fc55ebSAneesh Kumar K.V {
1123e36aba7SGreg Kurz     return local_setxattr_nofollow(ctx, path, MAP_ACL_DEFAULT, value, size,
1133e36aba7SGreg Kurz                                    flags);
11470fc55ebSAneesh Kumar K.V }
11570fc55ebSAneesh Kumar K.V 
mp_dacl_removexattr(FsContext * ctx,const char * path,const char * name)11670fc55ebSAneesh Kumar K.V static int mp_dacl_removexattr(FsContext *ctx,
11770fc55ebSAneesh Kumar K.V                                const char *path, const char *name)
11870fc55ebSAneesh Kumar K.V {
119a0994761SAneesh Kumar K.V     int ret;
1204fa4ce71SChen Gang 
12172f0d0bfSGreg Kurz     ret = local_removexattr_nofollow(ctx, path, MAP_ACL_DEFAULT);
122*9ea31646SChristian Schoenebeck     /*
123*9ea31646SChristian Schoenebeck      * macOS returns ENOATTR (!=ENODATA on macOS), whereas Linux returns
124*9ea31646SChristian Schoenebeck      * ENODATA (==ENOATTR on Linux), so checking for ENOATTR is fine
125*9ea31646SChristian Schoenebeck      */
126*9ea31646SChristian Schoenebeck     if (ret == -1 && errno == ENOATTR) {
127a0994761SAneesh Kumar K.V         /*
128a0994761SAneesh Kumar K.V          * We don't get ENODATA error when trying to remove a
129a0994761SAneesh Kumar K.V          * posix acl that is not present. So don't throw the error
130a0994761SAneesh Kumar K.V          * even in case of mapped security model
131a0994761SAneesh Kumar K.V          */
132a0994761SAneesh Kumar K.V         errno = 0;
133a0994761SAneesh Kumar K.V         ret = 0;
134a0994761SAneesh Kumar K.V     }
135a0994761SAneesh Kumar K.V     return ret;
13670fc55ebSAneesh Kumar K.V }
13770fc55ebSAneesh Kumar K.V 
13870fc55ebSAneesh Kumar K.V 
13970fc55ebSAneesh Kumar K.V XattrOperations mapped_pacl_xattr = {
14070fc55ebSAneesh Kumar K.V     .name = "system.posix_acl_access",
14170fc55ebSAneesh Kumar K.V     .getxattr = mp_pacl_getxattr,
14270fc55ebSAneesh Kumar K.V     .setxattr = mp_pacl_setxattr,
14370fc55ebSAneesh Kumar K.V     .listxattr = mp_pacl_listxattr,
14470fc55ebSAneesh Kumar K.V     .removexattr = mp_pacl_removexattr,
14570fc55ebSAneesh Kumar K.V };
14670fc55ebSAneesh Kumar K.V 
14770fc55ebSAneesh Kumar K.V XattrOperations mapped_dacl_xattr = {
14870fc55ebSAneesh Kumar K.V     .name = "system.posix_acl_default",
14970fc55ebSAneesh Kumar K.V     .getxattr = mp_dacl_getxattr,
15070fc55ebSAneesh Kumar K.V     .setxattr = mp_dacl_setxattr,
15170fc55ebSAneesh Kumar K.V     .listxattr = mp_dacl_listxattr,
15270fc55ebSAneesh Kumar K.V     .removexattr = mp_dacl_removexattr,
15370fc55ebSAneesh Kumar K.V };
15470fc55ebSAneesh Kumar K.V 
15570fc55ebSAneesh Kumar K.V XattrOperations passthrough_acl_xattr = {
15670fc55ebSAneesh Kumar K.V     .name = "system.posix_acl_",
15770fc55ebSAneesh Kumar K.V     .getxattr = pt_getxattr,
15870fc55ebSAneesh Kumar K.V     .setxattr = pt_setxattr,
15970fc55ebSAneesh Kumar K.V     .listxattr = pt_listxattr,
16070fc55ebSAneesh Kumar K.V     .removexattr = pt_removexattr,
16170fc55ebSAneesh Kumar K.V };
16270fc55ebSAneesh Kumar K.V 
16370fc55ebSAneesh Kumar K.V XattrOperations none_acl_xattr = {
16470fc55ebSAneesh Kumar K.V     .name = "system.posix_acl_",
16570fc55ebSAneesh Kumar K.V     .getxattr = notsup_getxattr,
16670fc55ebSAneesh Kumar K.V     .setxattr = notsup_setxattr,
16770fc55ebSAneesh Kumar K.V     .listxattr = notsup_listxattr,
16870fc55ebSAneesh Kumar K.V     .removexattr = notsup_removexattr,
16970fc55ebSAneesh Kumar K.V };
170