Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nfs3acl.c
Go to the documentation of this file.
1 #include <linux/fs.h>
2 #include <linux/gfp.h>
3 #include <linux/nfs.h>
4 #include <linux/nfs3.h>
5 #include <linux/nfs_fs.h>
7 #include <linux/nfsacl.h>
8 
9 #include "internal.h"
10 
11 #define NFSDBG_FACILITY NFSDBG_PROC
12 
13 ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size)
14 {
15  struct inode *inode = dentry->d_inode;
16  struct posix_acl *acl;
17  int pos=0, len=0;
18 
19 # define output(s) do { \
20  if (pos + sizeof(s) <= size) { \
21  memcpy(buffer + pos, s, sizeof(s)); \
22  pos += sizeof(s); \
23  } \
24  len += sizeof(s); \
25  } while(0)
26 
27  acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS);
28  if (IS_ERR(acl))
29  return PTR_ERR(acl);
30  if (acl) {
31  output("system.posix_acl_access");
32  posix_acl_release(acl);
33  }
34 
35  if (S_ISDIR(inode->i_mode)) {
36  acl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT);
37  if (IS_ERR(acl))
38  return PTR_ERR(acl);
39  if (acl) {
40  output("system.posix_acl_default");
41  posix_acl_release(acl);
42  }
43  }
44 
45 # undef output
46 
47  if (!buffer || len <= size)
48  return len;
49  return -ERANGE;
50 }
51 
52 ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
53  void *buffer, size_t size)
54 {
55  struct inode *inode = dentry->d_inode;
56  struct posix_acl *acl;
57  int type, error = 0;
58 
59  if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
60  type = ACL_TYPE_ACCESS;
61  else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
62  type = ACL_TYPE_DEFAULT;
63  else
64  return -EOPNOTSUPP;
65 
66  acl = nfs3_proc_getacl(inode, type);
67  if (IS_ERR(acl))
68  return PTR_ERR(acl);
69  else if (acl) {
70  if (type == ACL_TYPE_ACCESS && acl->a_count == 0)
71  error = -ENODATA;
72  else
73  error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
74  posix_acl_release(acl);
75  } else
76  error = -ENODATA;
77 
78  return error;
79 }
80 
81 int nfs3_setxattr(struct dentry *dentry, const char *name,
82  const void *value, size_t size, int flags)
83 {
84  struct inode *inode = dentry->d_inode;
85  struct posix_acl *acl;
86  int type, error;
87 
88  if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
89  type = ACL_TYPE_ACCESS;
90  else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
91  type = ACL_TYPE_DEFAULT;
92  else
93  return -EOPNOTSUPP;
94 
95  acl = posix_acl_from_xattr(&init_user_ns, value, size);
96  if (IS_ERR(acl))
97  return PTR_ERR(acl);
98  error = nfs3_proc_setacl(inode, type, acl);
99  posix_acl_release(acl);
100 
101  return error;
102 }
103 
104 int nfs3_removexattr(struct dentry *dentry, const char *name)
105 {
106  struct inode *inode = dentry->d_inode;
107  int type;
108 
109  if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
110  type = ACL_TYPE_ACCESS;
111  else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
112  type = ACL_TYPE_DEFAULT;
113  else
114  return -EOPNOTSUPP;
115 
116  return nfs3_proc_setacl(inode, type, NULL);
117 }
118 
119 static void __nfs3_forget_cached_acls(struct nfs_inode *nfsi)
120 {
121  if (!IS_ERR(nfsi->acl_access)) {
122  posix_acl_release(nfsi->acl_access);
123  nfsi->acl_access = ERR_PTR(-EAGAIN);
124  }
125  if (!IS_ERR(nfsi->acl_default)) {
126  posix_acl_release(nfsi->acl_default);
127  nfsi->acl_default = ERR_PTR(-EAGAIN);
128  }
129 }
130 
132 {
133  dprintk("NFS: nfs3_forget_cached_acls(%s/%ld)\n", inode->i_sb->s_id,
134  inode->i_ino);
135  spin_lock(&inode->i_lock);
136  __nfs3_forget_cached_acls(NFS_I(inode));
137  spin_unlock(&inode->i_lock);
138 }
139 
140 static struct posix_acl *nfs3_get_cached_acl(struct inode *inode, int type)
141 {
142  struct nfs_inode *nfsi = NFS_I(inode);
143  struct posix_acl *acl = ERR_PTR(-EINVAL);
144 
145  spin_lock(&inode->i_lock);
146  switch(type) {
147  case ACL_TYPE_ACCESS:
148  acl = nfsi->acl_access;
149  break;
150 
151  case ACL_TYPE_DEFAULT:
152  acl = nfsi->acl_default;
153  break;
154 
155  default:
156  goto out;
157  }
158  if (IS_ERR(acl))
159  acl = ERR_PTR(-EAGAIN);
160  else
161  acl = posix_acl_dup(acl);
162 out:
163  spin_unlock(&inode->i_lock);
164  dprintk("NFS: nfs3_get_cached_acl(%s/%ld, %d) = %p\n", inode->i_sb->s_id,
165  inode->i_ino, type, acl);
166  return acl;
167 }
168 
169 static void nfs3_cache_acls(struct inode *inode, struct posix_acl *acl,
170  struct posix_acl *dfacl)
171 {
172  struct nfs_inode *nfsi = NFS_I(inode);
173 
174  dprintk("nfs3_cache_acls(%s/%ld, %p, %p)\n", inode->i_sb->s_id,
175  inode->i_ino, acl, dfacl);
176  spin_lock(&inode->i_lock);
177  __nfs3_forget_cached_acls(NFS_I(inode));
178  if (!IS_ERR(acl))
179  nfsi->acl_access = posix_acl_dup(acl);
180  if (!IS_ERR(dfacl))
181  nfsi->acl_default = posix_acl_dup(dfacl);
182  spin_unlock(&inode->i_lock);
183 }
184 
185 struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
186 {
187  struct nfs_server *server = NFS_SERVER(inode);
188  struct page *pages[NFSACL_MAXPAGES] = { };
189  struct nfs3_getaclargs args = {
190  .fh = NFS_FH(inode),
191  /* The xdr layer may allocate pages here. */
192  .pages = pages,
193  };
194  struct nfs3_getaclres res = {
195  NULL,
196  };
197  struct rpc_message msg = {
198  .rpc_argp = &args,
199  .rpc_resp = &res,
200  };
201  struct posix_acl *acl;
202  int status, count;
203 
204  if (!nfs_server_capable(inode, NFS_CAP_ACLS))
205  return ERR_PTR(-EOPNOTSUPP);
206 
207  status = nfs_revalidate_inode(server, inode);
208  if (status < 0)
209  return ERR_PTR(status);
210  acl = nfs3_get_cached_acl(inode, type);
211  if (acl != ERR_PTR(-EAGAIN))
212  return acl;
213  acl = NULL;
214 
215  /*
216  * Only get the access acl when explicitly requested: We don't
217  * need it for access decisions, and only some applications use
218  * it. Applications which request the access acl first are not
219  * penalized from this optimization.
220  */
221  if (type == ACL_TYPE_ACCESS)
222  args.mask |= NFS_ACLCNT|NFS_ACL;
223  if (S_ISDIR(inode->i_mode))
224  args.mask |= NFS_DFACLCNT|NFS_DFACL;
225  if (args.mask == 0)
226  return NULL;
227 
228  dprintk("NFS call getacl\n");
229  msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_GETACL];
230  res.fattr = nfs_alloc_fattr();
231  if (res.fattr == NULL)
232  return ERR_PTR(-ENOMEM);
233 
234  status = rpc_call_sync(server->client_acl, &msg, 0);
235  dprintk("NFS reply getacl: %d\n", status);
236 
237  /* pages may have been allocated at the xdr layer. */
238  for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
239  __free_page(args.pages[count]);
240 
241  switch (status) {
242  case 0:
243  status = nfs_refresh_inode(inode, res.fattr);
244  break;
245  case -EPFNOSUPPORT:
246  case -EPROTONOSUPPORT:
247  dprintk("NFS_V3_ACL extension not supported; disabling\n");
248  server->caps &= ~NFS_CAP_ACLS;
249  case -ENOTSUPP:
250  status = -EOPNOTSUPP;
251  default:
252  goto getout;
253  }
254  if ((args.mask & res.mask) != args.mask) {
255  status = -EIO;
256  goto getout;
257  }
258 
259  if (res.acl_access != NULL) {
260  if (posix_acl_equiv_mode(res.acl_access, NULL) == 0) {
261  posix_acl_release(res.acl_access);
262  res.acl_access = NULL;
263  }
264  }
265  nfs3_cache_acls(inode,
266  (res.mask & NFS_ACL) ? res.acl_access : ERR_PTR(-EINVAL),
267  (res.mask & NFS_DFACL) ? res.acl_default : ERR_PTR(-EINVAL));
268 
269  switch(type) {
270  case ACL_TYPE_ACCESS:
271  acl = res.acl_access;
272  res.acl_access = NULL;
273  break;
274 
275  case ACL_TYPE_DEFAULT:
276  acl = res.acl_default;
277  res.acl_default = NULL;
278  }
279 
280 getout:
281  posix_acl_release(res.acl_access);
282  posix_acl_release(res.acl_default);
283  nfs_free_fattr(res.fattr);
284 
285  if (status != 0) {
286  posix_acl_release(acl);
287  acl = ERR_PTR(status);
288  }
289  return acl;
290 }
291 
292 static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
293  struct posix_acl *dfacl)
294 {
295  struct nfs_server *server = NFS_SERVER(inode);
296  struct nfs_fattr *fattr;
297  struct page *pages[NFSACL_MAXPAGES];
298  struct nfs3_setaclargs args = {
299  .inode = inode,
300  .mask = NFS_ACL,
301  .acl_access = acl,
302  .pages = pages,
303  };
304  struct rpc_message msg = {
305  .rpc_argp = &args,
306  .rpc_resp = &fattr,
307  };
308  int status;
309 
310  status = -EOPNOTSUPP;
311  if (!nfs_server_capable(inode, NFS_CAP_ACLS))
312  goto out;
313 
314  /* We are doing this here because XDR marshalling does not
315  * return any results, it BUGs. */
316  status = -ENOSPC;
317  if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES)
318  goto out;
319  if (dfacl != NULL && dfacl->a_count > NFS_ACL_MAX_ENTRIES)
320  goto out;
321  if (S_ISDIR(inode->i_mode)) {
322  args.mask |= NFS_DFACL;
323  args.acl_default = dfacl;
324  args.len = nfsacl_size(acl, dfacl);
325  } else
326  args.len = nfsacl_size(acl, NULL);
327 
328  if (args.len > NFS_ACL_INLINE_BUFSIZE) {
329  unsigned int npages = 1 + ((args.len - 1) >> PAGE_SHIFT);
330 
331  status = -ENOMEM;
332  do {
333  args.pages[args.npages] = alloc_page(GFP_KERNEL);
334  if (args.pages[args.npages] == NULL)
335  goto out_freepages;
336  args.npages++;
337  } while (args.npages < npages);
338  }
339 
340  dprintk("NFS call setacl\n");
341  status = -ENOMEM;
342  fattr = nfs_alloc_fattr();
343  if (fattr == NULL)
344  goto out_freepages;
345 
346  msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL];
347  msg.rpc_resp = fattr;
348  status = rpc_call_sync(server->client_acl, &msg, 0);
349  nfs_access_zap_cache(inode);
350  nfs_zap_acl_cache(inode);
351  dprintk("NFS reply setacl: %d\n", status);
352 
353  switch (status) {
354  case 0:
355  status = nfs_refresh_inode(inode, fattr);
356  nfs3_cache_acls(inode, acl, dfacl);
357  break;
358  case -EPFNOSUPPORT:
359  case -EPROTONOSUPPORT:
360  dprintk("NFS_V3_ACL SETACL RPC not supported"
361  "(will not retry)\n");
362  server->caps &= ~NFS_CAP_ACLS;
363  case -ENOTSUPP:
364  status = -EOPNOTSUPP;
365  }
366  nfs_free_fattr(fattr);
367 out_freepages:
368  while (args.npages != 0) {
369  args.npages--;
370  __free_page(args.pages[args.npages]);
371  }
372 out:
373  return status;
374 }
375 
376 int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl)
377 {
378  struct posix_acl *alloc = NULL, *dfacl = NULL;
379  int status;
380 
381  if (S_ISDIR(inode->i_mode)) {
382  switch(type) {
383  case ACL_TYPE_ACCESS:
384  alloc = dfacl = nfs3_proc_getacl(inode,
386  if (IS_ERR(alloc))
387  goto fail;
388  break;
389 
390  case ACL_TYPE_DEFAULT:
391  dfacl = acl;
392  alloc = acl = nfs3_proc_getacl(inode,
394  if (IS_ERR(alloc))
395  goto fail;
396  break;
397 
398  default:
399  return -EINVAL;
400  }
401  } else if (type != ACL_TYPE_ACCESS)
402  return -EINVAL;
403 
404  if (acl == NULL) {
405  alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
406  if (IS_ERR(alloc))
407  goto fail;
408  }
409  status = nfs3_proc_setacls(inode, acl, dfacl);
410  posix_acl_release(alloc);
411  return status;
412 
413 fail:
414  return PTR_ERR(alloc);
415 }
416 
417 int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
418  umode_t mode)
419 {
420  struct posix_acl *dfacl, *acl;
421  int error = 0;
422 
423  dfacl = nfs3_proc_getacl(dir, ACL_TYPE_DEFAULT);
424  if (IS_ERR(dfacl)) {
425  error = PTR_ERR(dfacl);
426  return (error == -EOPNOTSUPP) ? 0 : error;
427  }
428  if (!dfacl)
429  return 0;
430  acl = posix_acl_dup(dfacl);
431  error = posix_acl_create(&acl, GFP_KERNEL, &mode);
432  if (error < 0)
433  goto out_release_dfacl;
434  error = nfs3_proc_setacls(inode, acl, S_ISDIR(inode->i_mode) ?
435  dfacl : NULL);
436  posix_acl_release(acl);
437 out_release_dfacl:
438  posix_acl_release(dfacl);
439  return error;
440 }