1 // SPDX-License-Identifier: LGPL-2.1 2 /* 3 * Copyright IBM Corporation, 2010 4 * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 5 */ 6 7 #include <linux/module.h> 8 #include <linux/fs.h> 9 #include <net/9p/9p.h> 10 #include <net/9p/client.h> 11 #include <linux/slab.h> 12 #include <linux/sched.h> 13 #include <linux/posix_acl_xattr.h> 14 #include "xattr.h" 15 #include "acl.h" 16 #include "v9fs.h" 17 #include "v9fs_vfs.h" 18 #include "fid.h" 19 20 static struct posix_acl *v9fs_fid_get_acl(struct p9_fid *fid, const char *name) 21 { 22 ssize_t size; 23 void *value = NULL; 24 struct posix_acl *acl = NULL; 25 26 size = v9fs_fid_xattr_get(fid, name, NULL, 0); 27 if (size < 0) 28 return ERR_PTR(size); 29 if (size == 0) 30 return ERR_PTR(-ENODATA); 31 32 value = kzalloc(size, GFP_NOFS); 33 if (!value) 34 return ERR_PTR(-ENOMEM); 35 36 size = v9fs_fid_xattr_get(fid, name, value, size); 37 if (size < 0) 38 acl = ERR_PTR(size); 39 else if (size == 0) 40 acl = ERR_PTR(-ENODATA); 41 else 42 acl = posix_acl_from_xattr(&init_user_ns, value, size); 43 kfree(value); 44 return acl; 45 } 46 47 static struct posix_acl *v9fs_acl_get(struct dentry *dentry, const char *name) 48 { 49 struct p9_fid *fid; 50 struct posix_acl *acl = NULL; 51 52 fid = v9fs_fid_lookup(dentry); 53 if (IS_ERR(fid)) 54 return ERR_CAST(fid); 55 56 acl = v9fs_fid_get_acl(fid, name); 57 p9_fid_put(fid); 58 return acl; 59 } 60 61 static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, const char *name) 62 { 63 int retval; 64 struct posix_acl *acl = NULL; 65 66 acl = v9fs_fid_get_acl(fid, name); 67 if (!IS_ERR(acl)) 68 return acl; 69 70 retval = PTR_ERR(acl); 71 if (retval == -ENODATA || retval == -ENOSYS || retval == -EOPNOTSUPP) 72 return NULL; 73 74 /* map everything else to -EIO */ 75 return ERR_PTR(-EIO); 76 } 77 78 int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) 79 { 80 int retval = 0; 81 struct posix_acl *pacl, *dacl; 82 struct v9fs_session_info *v9ses; 83 84 v9ses = v9fs_inode2v9ses(inode); 85 if (((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) || 86 ((v9ses->flags & V9FS_ACL_MASK) != V9FS_POSIX_ACL)) { 87 set_cached_acl(inode, ACL_TYPE_DEFAULT, NULL); 88 set_cached_acl(inode, ACL_TYPE_ACCESS, NULL); 89 return 0; 90 } 91 /* get the default/access acl values and cache them */ 92 dacl = __v9fs_get_acl(fid, XATTR_NAME_POSIX_ACL_DEFAULT); 93 pacl = __v9fs_get_acl(fid, XATTR_NAME_POSIX_ACL_ACCESS); 94 95 if (!IS_ERR(dacl) && !IS_ERR(pacl)) { 96 set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl); 97 set_cached_acl(inode, ACL_TYPE_ACCESS, pacl); 98 } else 99 retval = -EIO; 100 101 if (!IS_ERR(dacl)) 102 posix_acl_release(dacl); 103 104 if (!IS_ERR(pacl)) 105 posix_acl_release(pacl); 106 107 return retval; 108 } 109 110 static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type) 111 { 112 struct posix_acl *acl; 113 /* 114 * 9p Always cache the acl value when 115 * instantiating the inode (v9fs_inode_from_fid) 116 */ 117 acl = get_cached_acl(inode, type); 118 BUG_ON(is_uncached_acl(acl)); 119 return acl; 120 } 121 122 struct posix_acl *v9fs_iop_get_inode_acl(struct inode *inode, int type, bool rcu) 123 { 124 struct v9fs_session_info *v9ses; 125 126 if (rcu) 127 return ERR_PTR(-ECHILD); 128 129 v9ses = v9fs_inode2v9ses(inode); 130 if (((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) || 131 ((v9ses->flags & V9FS_ACL_MASK) != V9FS_POSIX_ACL)) { 132 /* 133 * On access = client and acl = on mode get the acl 134 * values from the server 135 */ 136 return NULL; 137 } 138 return v9fs_get_cached_acl(inode, type); 139 140 } 141 142 struct posix_acl *v9fs_iop_get_acl(struct user_namespace *mnt_userns, 143 struct dentry *dentry, int type) 144 { 145 struct v9fs_session_info *v9ses; 146 147 v9ses = v9fs_dentry2v9ses(dentry); 148 /* We allow set/get/list of acl when access=client is not specified. */ 149 if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) 150 return v9fs_acl_get(dentry, posix_acl_xattr_name(type)); 151 return v9fs_get_cached_acl(d_inode(dentry), type); 152 } 153 154 static int v9fs_set_acl(struct p9_fid *fid, int type, struct posix_acl *acl) 155 { 156 int retval; 157 char *name; 158 size_t size; 159 void *buffer; 160 161 if (!acl) 162 return 0; 163 164 /* Set a setxattr request to server */ 165 size = posix_acl_xattr_size(acl->a_count); 166 buffer = kmalloc(size, GFP_KERNEL); 167 if (!buffer) 168 return -ENOMEM; 169 retval = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); 170 if (retval < 0) 171 goto err_free_out; 172 switch (type) { 173 case ACL_TYPE_ACCESS: 174 name = XATTR_NAME_POSIX_ACL_ACCESS; 175 break; 176 case ACL_TYPE_DEFAULT: 177 name = XATTR_NAME_POSIX_ACL_DEFAULT; 178 break; 179 default: 180 BUG(); 181 } 182 retval = v9fs_fid_xattr_set(fid, name, buffer, size, 0); 183 err_free_out: 184 kfree(buffer); 185 return retval; 186 } 187 188 int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid) 189 { 190 int retval = 0; 191 struct posix_acl *acl; 192 193 if (S_ISLNK(inode->i_mode)) 194 return -EOPNOTSUPP; 195 acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS); 196 if (acl) { 197 retval = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); 198 if (retval) 199 return retval; 200 set_cached_acl(inode, ACL_TYPE_ACCESS, acl); 201 retval = v9fs_set_acl(fid, ACL_TYPE_ACCESS, acl); 202 posix_acl_release(acl); 203 } 204 return retval; 205 } 206 207 int v9fs_set_create_acl(struct inode *inode, struct p9_fid *fid, 208 struct posix_acl *dacl, struct posix_acl *acl) 209 { 210 set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl); 211 set_cached_acl(inode, ACL_TYPE_ACCESS, acl); 212 v9fs_set_acl(fid, ACL_TYPE_DEFAULT, dacl); 213 v9fs_set_acl(fid, ACL_TYPE_ACCESS, acl); 214 return 0; 215 } 216 217 void v9fs_put_acl(struct posix_acl *dacl, 218 struct posix_acl *acl) 219 { 220 posix_acl_release(dacl); 221 posix_acl_release(acl); 222 } 223 224 int v9fs_acl_mode(struct inode *dir, umode_t *modep, 225 struct posix_acl **dpacl, struct posix_acl **pacl) 226 { 227 int retval = 0; 228 umode_t mode = *modep; 229 struct posix_acl *acl = NULL; 230 231 if (!S_ISLNK(mode)) { 232 acl = v9fs_get_cached_acl(dir, ACL_TYPE_DEFAULT); 233 if (IS_ERR(acl)) 234 return PTR_ERR(acl); 235 if (!acl) 236 mode &= ~current_umask(); 237 } 238 if (acl) { 239 if (S_ISDIR(mode)) 240 *dpacl = posix_acl_dup(acl); 241 retval = __posix_acl_create(&acl, GFP_NOFS, &mode); 242 if (retval < 0) 243 return retval; 244 if (retval > 0) 245 *pacl = acl; 246 else 247 posix_acl_release(acl); 248 } 249 *modep = mode; 250 return 0; 251 } 252 253 static int v9fs_xattr_get_acl(const struct xattr_handler *handler, 254 struct dentry *dentry, struct inode *inode, 255 const char *name, void *buffer, size_t size) 256 { 257 struct v9fs_session_info *v9ses; 258 struct posix_acl *acl; 259 int error; 260 261 v9ses = v9fs_dentry2v9ses(dentry); 262 /* 263 * We allow set/get/list of acl when access=client is not specified 264 */ 265 if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) 266 return v9fs_xattr_get(dentry, handler->name, buffer, size); 267 268 acl = v9fs_get_cached_acl(inode, handler->flags); 269 if (IS_ERR(acl)) 270 return PTR_ERR(acl); 271 if (acl == NULL) 272 return -ENODATA; 273 error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); 274 posix_acl_release(acl); 275 276 return error; 277 } 278 279 static int v9fs_xattr_set_acl(const struct xattr_handler *handler, 280 struct user_namespace *mnt_userns, 281 struct dentry *dentry, struct inode *inode, 282 const char *name, const void *value, 283 size_t size, int flags) 284 { 285 int retval; 286 struct posix_acl *acl; 287 struct v9fs_session_info *v9ses; 288 289 v9ses = v9fs_dentry2v9ses(dentry); 290 /* 291 * set the attribute on the remote. Without even looking at the 292 * xattr value. We leave it to the server to validate 293 */ 294 if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) 295 return v9fs_xattr_set(dentry, handler->name, value, size, 296 flags); 297 298 if (S_ISLNK(inode->i_mode)) 299 return -EOPNOTSUPP; 300 if (!inode_owner_or_capable(&init_user_ns, inode)) 301 return -EPERM; 302 if (value) { 303 /* update the cached acl value */ 304 acl = posix_acl_from_xattr(&init_user_ns, value, size); 305 if (IS_ERR(acl)) 306 return PTR_ERR(acl); 307 else if (acl) { 308 retval = posix_acl_valid(inode->i_sb->s_user_ns, acl); 309 if (retval) 310 goto err_out; 311 } 312 } else 313 acl = NULL; 314 315 switch (handler->flags) { 316 case ACL_TYPE_ACCESS: 317 if (acl) { 318 struct iattr iattr = { 0 }; 319 struct posix_acl *old_acl = acl; 320 321 retval = posix_acl_update_mode(&init_user_ns, inode, 322 &iattr.ia_mode, &acl); 323 if (retval) 324 goto err_out; 325 if (!acl) { 326 /* 327 * ACL can be represented 328 * by the mode bits. So don't 329 * update ACL. 330 */ 331 posix_acl_release(old_acl); 332 value = NULL; 333 size = 0; 334 } 335 iattr.ia_valid = ATTR_MODE; 336 /* FIXME should we update ctime ? 337 * What is the following setxattr update the 338 * mode ? 339 */ 340 v9fs_vfs_setattr_dotl(&init_user_ns, dentry, &iattr); 341 } 342 break; 343 case ACL_TYPE_DEFAULT: 344 if (!S_ISDIR(inode->i_mode)) { 345 retval = acl ? -EINVAL : 0; 346 goto err_out; 347 } 348 break; 349 default: 350 BUG(); 351 } 352 retval = v9fs_xattr_set(dentry, handler->name, value, size, flags); 353 if (!retval) 354 set_cached_acl(inode, handler->flags, acl); 355 err_out: 356 posix_acl_release(acl); 357 return retval; 358 } 359 360 const struct xattr_handler v9fs_xattr_acl_access_handler = { 361 .name = XATTR_NAME_POSIX_ACL_ACCESS, 362 .flags = ACL_TYPE_ACCESS, 363 .get = v9fs_xattr_get_acl, 364 .set = v9fs_xattr_set_acl, 365 }; 366 367 const struct xattr_handler v9fs_xattr_acl_default_handler = { 368 .name = XATTR_NAME_POSIX_ACL_DEFAULT, 369 .flags = ACL_TYPE_DEFAULT, 370 .get = v9fs_xattr_get_acl, 371 .set = v9fs_xattr_set_acl, 372 }; 373