Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 2 : : #include <linux/fs.h> 3 : : #include <linux/gfp.h> 4 : : #include <linux/nfs.h> 5 : : #include <linux/nfs3.h> 6 : : #include <linux/nfs_fs.h> 7 : : #include <linux/posix_acl_xattr.h> 8 : : #include <linux/nfsacl.h> 9 : : 10 : : #include "internal.h" 11 : : #include "nfs3_fs.h" 12 : : 13 : : #define NFSDBG_FACILITY NFSDBG_PROC 14 : : 15 : : /* 16 : : * nfs3_prepare_get_acl, nfs3_complete_get_acl, nfs3_abort_get_acl: Helpers for 17 : : * caching get_acl results in a race-free way. See fs/posix_acl.c:get_acl() 18 : : * for explanations. 19 : : */ 20 : 0 : static void nfs3_prepare_get_acl(struct posix_acl **p) 21 : : { 22 : 0 : struct posix_acl *sentinel = uncached_acl_sentinel(current); 23 : : 24 : 0 : if (cmpxchg(p, ACL_NOT_CACHED, sentinel) != ACL_NOT_CACHED) { 25 : : /* Not the first reader or sentinel already in place. */ 26 : : } 27 : 0 : } 28 : : 29 : 0 : static void nfs3_complete_get_acl(struct posix_acl **p, struct posix_acl *acl) 30 : : { 31 : 0 : struct posix_acl *sentinel = uncached_acl_sentinel(current); 32 : : 33 : : /* Only cache the ACL if our sentinel is still in place. */ 34 : : posix_acl_dup(acl); 35 : 0 : if (cmpxchg(p, sentinel, acl) != sentinel) 36 : 0 : posix_acl_release(acl); 37 : 0 : } 38 : : 39 : 0 : static void nfs3_abort_get_acl(struct posix_acl **p) 40 : : { 41 : 0 : struct posix_acl *sentinel = uncached_acl_sentinel(current); 42 : : 43 : : /* Remove our sentinel upon failure. */ 44 : 0 : cmpxchg(p, sentinel, ACL_NOT_CACHED); 45 : 0 : } 46 : : 47 : 0 : struct posix_acl *nfs3_get_acl(struct inode *inode, int type) 48 : : { 49 : : struct nfs_server *server = NFS_SERVER(inode); 50 : 0 : struct page *pages[NFSACL_MAXPAGES] = { }; 51 : 0 : struct nfs3_getaclargs args = { 52 : : .fh = NFS_FH(inode), 53 : : /* The xdr layer may allocate pages here. */ 54 : : .pages = pages, 55 : : }; 56 : 0 : struct nfs3_getaclres res = { 57 : : NULL, 58 : : }; 59 : 0 : struct rpc_message msg = { 60 : : .rpc_argp = &args, 61 : : .rpc_resp = &res, 62 : : }; 63 : : int status, count; 64 : : 65 : 0 : if (!nfs_server_capable(inode, NFS_CAP_ACLS)) 66 : : return ERR_PTR(-EOPNOTSUPP); 67 : : 68 : 0 : status = nfs_revalidate_inode(server, inode); 69 : 0 : if (status < 0) 70 : 0 : return ERR_PTR(status); 71 : : 72 : : /* 73 : : * Only get the access acl when explicitly requested: We don't 74 : : * need it for access decisions, and only some applications use 75 : : * it. Applications which request the access acl first are not 76 : : * penalized from this optimization. 77 : : */ 78 : 0 : if (type == ACL_TYPE_ACCESS) 79 : 0 : args.mask |= NFS_ACLCNT|NFS_ACL; 80 : 0 : if (S_ISDIR(inode->i_mode)) 81 : 0 : args.mask |= NFS_DFACLCNT|NFS_DFACL; 82 : 0 : if (args.mask == 0) 83 : : return NULL; 84 : : 85 : : dprintk("NFS call getacl\n"); 86 : 0 : msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_GETACL]; 87 : 0 : res.fattr = nfs_alloc_fattr(); 88 : 0 : if (res.fattr == NULL) 89 : : return ERR_PTR(-ENOMEM); 90 : : 91 : 0 : if (args.mask & NFS_ACL) 92 : 0 : nfs3_prepare_get_acl(&inode->i_acl); 93 : 0 : if (args.mask & NFS_DFACL) 94 : 0 : nfs3_prepare_get_acl(&inode->i_default_acl); 95 : : 96 : 0 : status = rpc_call_sync(server->client_acl, &msg, 0); 97 : : dprintk("NFS reply getacl: %d\n", status); 98 : : 99 : : /* pages may have been allocated at the xdr layer. */ 100 : 0 : for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++) 101 : 0 : __free_page(args.pages[count]); 102 : : 103 : 0 : switch (status) { 104 : : case 0: 105 : 0 : status = nfs_refresh_inode(inode, res.fattr); 106 : : break; 107 : : case -EPFNOSUPPORT: 108 : : case -EPROTONOSUPPORT: 109 : : dprintk("NFS_V3_ACL extension not supported; disabling\n"); 110 : 0 : server->caps &= ~NFS_CAP_ACLS; 111 : : /* fall through */ 112 : : case -ENOTSUPP: 113 : : status = -EOPNOTSUPP; 114 : : default: 115 : : goto getout; 116 : : } 117 : 0 : if ((args.mask & res.mask) != args.mask) { 118 : : status = -EIO; 119 : : goto getout; 120 : : } 121 : : 122 : 0 : if (res.acl_access != NULL) { 123 : 0 : if ((posix_acl_equiv_mode(res.acl_access, NULL) == 0) || 124 : 0 : res.acl_access->a_count == 0) { 125 : 0 : posix_acl_release(res.acl_access); 126 : 0 : res.acl_access = NULL; 127 : : } 128 : : } 129 : : 130 : 0 : if (res.mask & NFS_ACL) 131 : 0 : nfs3_complete_get_acl(&inode->i_acl, res.acl_access); 132 : : else 133 : 0 : forget_cached_acl(inode, ACL_TYPE_ACCESS); 134 : : 135 : 0 : if (res.mask & NFS_DFACL) 136 : 0 : nfs3_complete_get_acl(&inode->i_default_acl, res.acl_default); 137 : : else 138 : 0 : forget_cached_acl(inode, ACL_TYPE_DEFAULT); 139 : : 140 : 0 : nfs_free_fattr(res.fattr); 141 : 0 : if (type == ACL_TYPE_ACCESS) { 142 : 0 : posix_acl_release(res.acl_default); 143 : 0 : return res.acl_access; 144 : : } else { 145 : 0 : posix_acl_release(res.acl_access); 146 : 0 : return res.acl_default; 147 : : } 148 : : 149 : : getout: 150 : 0 : nfs3_abort_get_acl(&inode->i_acl); 151 : 0 : nfs3_abort_get_acl(&inode->i_default_acl); 152 : 0 : posix_acl_release(res.acl_access); 153 : 0 : posix_acl_release(res.acl_default); 154 : 0 : nfs_free_fattr(res.fattr); 155 : 0 : return ERR_PTR(status); 156 : : } 157 : : 158 : 0 : static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, 159 : : struct posix_acl *dfacl) 160 : : { 161 : : struct nfs_server *server = NFS_SERVER(inode); 162 : : struct nfs_fattr *fattr; 163 : : struct page *pages[NFSACL_MAXPAGES]; 164 : 0 : struct nfs3_setaclargs args = { 165 : : .inode = inode, 166 : : .mask = NFS_ACL, 167 : : .acl_access = acl, 168 : : .pages = pages, 169 : : }; 170 : 0 : struct rpc_message msg = { 171 : : .rpc_argp = &args, 172 : : .rpc_resp = &fattr, 173 : : }; 174 : : int status = 0; 175 : : 176 : 0 : if (acl == NULL && (!S_ISDIR(inode->i_mode) || dfacl == NULL)) 177 : : goto out; 178 : : 179 : : status = -EOPNOTSUPP; 180 : 0 : if (!nfs_server_capable(inode, NFS_CAP_ACLS)) 181 : : goto out; 182 : : 183 : : /* We are doing this here because XDR marshalling does not 184 : : * return any results, it BUGs. */ 185 : : status = -ENOSPC; 186 : 0 : if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES) 187 : : goto out; 188 : 0 : if (dfacl != NULL && dfacl->a_count > NFS_ACL_MAX_ENTRIES) 189 : : goto out; 190 : 0 : if (S_ISDIR(inode->i_mode)) { 191 : 0 : args.mask |= NFS_DFACL; 192 : 0 : args.acl_default = dfacl; 193 : 0 : args.len = nfsacl_size(acl, dfacl); 194 : : } else 195 : 0 : args.len = nfsacl_size(acl, NULL); 196 : : 197 : 0 : if (args.len > NFS_ACL_INLINE_BUFSIZE) { 198 : 0 : unsigned int npages = 1 + ((args.len - 1) >> PAGE_SHIFT); 199 : : 200 : : status = -ENOMEM; 201 : : do { 202 : 0 : args.pages[args.npages] = alloc_page(GFP_KERNEL); 203 : 0 : if (args.pages[args.npages] == NULL) 204 : : goto out_freepages; 205 : 0 : args.npages++; 206 : 0 : } while (args.npages < npages); 207 : : } 208 : : 209 : : dprintk("NFS call setacl\n"); 210 : : status = -ENOMEM; 211 : 0 : fattr = nfs_alloc_fattr(); 212 : 0 : if (fattr == NULL) 213 : : goto out_freepages; 214 : : 215 : 0 : msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL]; 216 : 0 : msg.rpc_resp = fattr; 217 : 0 : status = rpc_call_sync(server->client_acl, &msg, 0); 218 : 0 : nfs_access_zap_cache(inode); 219 : 0 : nfs_zap_acl_cache(inode); 220 : : dprintk("NFS reply setacl: %d\n", status); 221 : : 222 : 0 : switch (status) { 223 : : case 0: 224 : 0 : status = nfs_refresh_inode(inode, fattr); 225 : 0 : break; 226 : : case -EPFNOSUPPORT: 227 : : case -EPROTONOSUPPORT: 228 : : dprintk("NFS_V3_ACL SETACL RPC not supported" 229 : : "(will not retry)\n"); 230 : 0 : server->caps &= ~NFS_CAP_ACLS; 231 : : /* fall through */ 232 : : case -ENOTSUPP: 233 : : status = -EOPNOTSUPP; 234 : : } 235 : 0 : nfs_free_fattr(fattr); 236 : : out_freepages: 237 : 0 : while (args.npages != 0) { 238 : 0 : args.npages--; 239 : 0 : __free_page(args.pages[args.npages]); 240 : : } 241 : : out: 242 : 0 : return status; 243 : : } 244 : : 245 : 0 : int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, 246 : : struct posix_acl *dfacl) 247 : : { 248 : : int ret; 249 : 0 : ret = __nfs3_proc_setacls(inode, acl, dfacl); 250 : 0 : return (ret == -EOPNOTSUPP) ? 0 : ret; 251 : : 252 : : } 253 : : 254 : 0 : int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type) 255 : : { 256 : : struct posix_acl *orig = acl, *dfacl = NULL, *alloc; 257 : : int status; 258 : : 259 : 0 : if (S_ISDIR(inode->i_mode)) { 260 : 0 : switch(type) { 261 : : case ACL_TYPE_ACCESS: 262 : 0 : alloc = get_acl(inode, ACL_TYPE_DEFAULT); 263 : 0 : if (IS_ERR(alloc)) 264 : : goto fail; 265 : : dfacl = alloc; 266 : : break; 267 : : 268 : : case ACL_TYPE_DEFAULT: 269 : 0 : alloc = get_acl(inode, ACL_TYPE_ACCESS); 270 : 0 : if (IS_ERR(alloc)) 271 : : goto fail; 272 : : dfacl = acl; 273 : : acl = alloc; 274 : : break; 275 : : } 276 : : } 277 : : 278 : 0 : if (acl == NULL) { 279 : 0 : alloc = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); 280 : 0 : if (IS_ERR(alloc)) 281 : : goto fail; 282 : : acl = alloc; 283 : : } 284 : 0 : status = __nfs3_proc_setacls(inode, acl, dfacl); 285 : : out: 286 : 0 : if (acl != orig) 287 : 0 : posix_acl_release(acl); 288 : 0 : if (dfacl != orig) 289 : 0 : posix_acl_release(dfacl); 290 : 0 : return status; 291 : : 292 : : fail: 293 : : status = PTR_ERR(alloc); 294 : 0 : goto out; 295 : : } 296 : : 297 : : const struct xattr_handler *nfs3_xattr_handlers[] = { 298 : : &posix_acl_access_xattr_handler, 299 : : &posix_acl_default_xattr_handler, 300 : : NULL, 301 : : }; 302 : : 303 : : static int 304 : 0 : nfs3_list_one_acl(struct inode *inode, int type, const char *name, void *data, 305 : : size_t size, ssize_t *result) 306 : : { 307 : : struct posix_acl *acl; 308 : 0 : char *p = data + *result; 309 : : 310 : 0 : acl = get_acl(inode, type); 311 : 0 : if (IS_ERR_OR_NULL(acl)) 312 : : return 0; 313 : : 314 : 0 : posix_acl_release(acl); 315 : : 316 : 0 : *result += strlen(name); 317 : 0 : *result += 1; 318 : 0 : if (!size) 319 : : return 0; 320 : 0 : if (*result > size) 321 : : return -ERANGE; 322 : : 323 : 0 : strcpy(p, name); 324 : 0 : return 0; 325 : : } 326 : : 327 : : ssize_t 328 : 0 : nfs3_listxattr(struct dentry *dentry, char *data, size_t size) 329 : : { 330 : : struct inode *inode = d_inode(dentry); 331 : 0 : ssize_t result = 0; 332 : : int error; 333 : : 334 : 0 : error = nfs3_list_one_acl(inode, ACL_TYPE_ACCESS, 335 : : XATTR_NAME_POSIX_ACL_ACCESS, data, size, &result); 336 : 0 : if (error) 337 : : return error; 338 : : 339 : 0 : error = nfs3_list_one_acl(inode, ACL_TYPE_DEFAULT, 340 : : XATTR_NAME_POSIX_ACL_DEFAULT, data, size, &result); 341 : 0 : if (error) 342 : : return error; 343 : 0 : return result; 344 : : }