aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2006-01-09 23:51:55 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-10 11:01:29 -0500
commit5be196e5f925dab2309530fabce69c2e562b9791 (patch)
tree4249d808c38b6f13e899ac936585c1fbb48e5b3b /fs/nfsd
parenta7e670d828e85ef9aacb7fa1cd221525c408110f (diff)
[PATCH] add vfs_* helpers for xattr operations
Add vfs_getxattr, vfs_setxattr and vfs_removexattr helpers for common checks around invocation of the xattr methods. NFSD already was missing some of the checks and there will be more soon. Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: James Morris <jmorris@namei.org> (James, I haven't touched selinux yet because it's doing various odd things and I'm not sure how it would interact with the security attribute fallbacks you added. Could you investigate whether it could use vfs_getxattr or if not add a __vfs_getxattr helper to share the bits it is fine with?) For NFSv4: instead of just converting it add an nfsd_getxattr helper for the code shared by NFSv2/3 and NFSv4 ACLs. In fact that code isn't even NFS-specific, but I'll wait for more users to pop up first before moving it to common code. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Dave Kleikamp <shaggy@austin.ibm.com> Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Neil Brown <neilb@suse.de> Cc: Trond Myklebust <trond.myklebust@fys.uio.no> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/vfs.c125
1 files changed, 48 insertions, 77 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index bb36b4304491..eef0576a7785 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -48,8 +48,8 @@
48#include <linux/fsnotify.h> 48#include <linux/fsnotify.h>
49#include <linux/posix_acl.h> 49#include <linux/posix_acl.h>
50#include <linux/posix_acl_xattr.h> 50#include <linux/posix_acl_xattr.h>
51#ifdef CONFIG_NFSD_V4
52#include <linux/xattr.h> 51#include <linux/xattr.h>
52#ifdef CONFIG_NFSD_V4
53#include <linux/nfs4.h> 53#include <linux/nfs4.h>
54#include <linux/nfs4_acl.h> 54#include <linux/nfs4_acl.h>
55#include <linux/nfsd_idmap.h> 55#include <linux/nfsd_idmap.h>
@@ -365,8 +365,30 @@ out_nfserr:
365 goto out; 365 goto out;
366} 366}
367 367
368#if defined(CONFIG_NFSD_V4) 368#if defined(CONFIG_NFSD_V2_ACL) || \
369 defined(CONFIG_NFSD_V3_ACL) || \
370 defined(CONFIG_NFSD_V4)
371static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
372{
373 ssize_t buflen;
374 int error;
375
376 buflen = vfs_getxattr(dentry, key, NULL, 0);
377 if (buflen <= 0)
378 return buflen;
369 379
380 *buf = kmalloc(buflen, GFP_KERNEL);
381 if (!*buf)
382 return -ENOMEM;
383
384 error = vfs_getxattr(dentry, key, *buf, buflen);
385 if (error < 0)
386 return error;
387 return buflen;
388}
389#endif
390
391#if defined(CONFIG_NFSD_V4)
370static int 392static int
371set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key) 393set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
372{ 394{
@@ -374,7 +396,6 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
374 size_t buflen; 396 size_t buflen;
375 char *buf = NULL; 397 char *buf = NULL;
376 int error = 0; 398 int error = 0;
377 struct inode *inode = dentry->d_inode;
378 399
379 buflen = posix_acl_xattr_size(pacl->a_count); 400 buflen = posix_acl_xattr_size(pacl->a_count);
380 buf = kmalloc(buflen, GFP_KERNEL); 401 buf = kmalloc(buflen, GFP_KERNEL);
@@ -388,15 +409,7 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
388 goto out; 409 goto out;
389 } 410 }
390 411
391 error = -EOPNOTSUPP; 412 error = vfs_setxattr(dentry, key, buf, len, 0);
392 if (inode->i_op && inode->i_op->setxattr) {
393 mutex_lock(&inode->i_mutex);
394 security_inode_setxattr(dentry, key, buf, len, 0);
395 error = inode->i_op->setxattr(dentry, key, buf, len, 0);
396 if (!error)
397 security_inode_post_setxattr(dentry, key, buf, len, 0);
398 mutex_unlock(&inode->i_mutex);
399 }
400out: 413out:
401 kfree(buf); 414 kfree(buf);
402 return error; 415 return error;
@@ -455,44 +468,19 @@ out_nfserr:
455static struct posix_acl * 468static struct posix_acl *
456_get_posix_acl(struct dentry *dentry, char *key) 469_get_posix_acl(struct dentry *dentry, char *key)
457{ 470{
458 struct inode *inode = dentry->d_inode; 471 void *buf = NULL;
459 char *buf = NULL;
460 int buflen, error = 0;
461 struct posix_acl *pacl = NULL; 472 struct posix_acl *pacl = NULL;
473 int buflen;
462 474
463 error = -EOPNOTSUPP; 475 buflen = nfsd_getxattr(dentry, key, &buf);
464 if (inode->i_op == NULL) 476 if (!buflen)
465 goto out_err; 477 buflen = -ENODATA;
466 if (inode->i_op->getxattr == NULL) 478 if (buflen <= 0)
467 goto out_err; 479 return ERR_PTR(buflen);
468
469 error = security_inode_getxattr(dentry, key);
470 if (error)
471 goto out_err;
472
473 buflen = inode->i_op->getxattr(dentry, key, NULL, 0);
474 if (buflen <= 0) {
475 error = buflen < 0 ? buflen : -ENODATA;
476 goto out_err;
477 }
478
479 buf = kmalloc(buflen, GFP_KERNEL);
480 if (buf == NULL) {
481 error = -ENOMEM;
482 goto out_err;
483 }
484
485 error = inode->i_op->getxattr(dentry, key, buf, buflen);
486 if (error < 0)
487 goto out_err;
488 480
489 pacl = posix_acl_from_xattr(buf, buflen); 481 pacl = posix_acl_from_xattr(buf, buflen);
490 out:
491 kfree(buf); 482 kfree(buf);
492 return pacl; 483 return pacl;
493 out_err:
494 pacl = ERR_PTR(error);
495 goto out;
496} 484}
497 485
498int 486int
@@ -1884,39 +1872,25 @@ nfsd_get_posix_acl(struct svc_fh *fhp, int type)
1884 ssize_t size; 1872 ssize_t size;
1885 struct posix_acl *acl; 1873 struct posix_acl *acl;
1886 1874
1887 if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr) 1875 if (!IS_POSIXACL(inode))
1876 return ERR_PTR(-EOPNOTSUPP);
1877
1878 switch (type) {
1879 case ACL_TYPE_ACCESS:
1880 name = POSIX_ACL_XATTR_ACCESS;
1881 break;
1882 case ACL_TYPE_DEFAULT:
1883 name = POSIX_ACL_XATTR_DEFAULT;
1884 break;
1885 default:
1888 return ERR_PTR(-EOPNOTSUPP); 1886 return ERR_PTR(-EOPNOTSUPP);
1889 switch(type) {
1890 case ACL_TYPE_ACCESS:
1891 name = POSIX_ACL_XATTR_ACCESS;
1892 break;
1893 case ACL_TYPE_DEFAULT:
1894 name = POSIX_ACL_XATTR_DEFAULT;
1895 break;
1896 default:
1897 return ERR_PTR(-EOPNOTSUPP);
1898 } 1887 }
1899 1888
1900 size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0); 1889 size = nfsd_getxattr(fhp->fh_dentry, name, &value);
1890 if (size < 0)
1891 return ERR_PTR(size);
1901 1892
1902 if (size < 0) {
1903 acl = ERR_PTR(size);
1904 goto getout;
1905 } else if (size > 0) {
1906 value = kmalloc(size, GFP_KERNEL);
1907 if (!value) {
1908 acl = ERR_PTR(-ENOMEM);
1909 goto getout;
1910 }
1911 size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size);
1912 if (size < 0) {
1913 acl = ERR_PTR(size);
1914 goto getout;
1915 }
1916 }
1917 acl = posix_acl_from_xattr(value, size); 1893 acl = posix_acl_from_xattr(value, size);
1918
1919getout:
1920 kfree(value); 1894 kfree(value);
1921 return acl; 1895 return acl;
1922} 1896}
@@ -1957,16 +1931,13 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
1957 } else 1931 } else
1958 size = 0; 1932 size = 0;
1959 1933
1960 if (!fhp->fh_locked)
1961 fh_lock(fhp); /* unlocking is done automatically */
1962 if (size) 1934 if (size)
1963 error = inode->i_op->setxattr(fhp->fh_dentry, name, 1935 error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
1964 value, size, 0);
1965 else { 1936 else {
1966 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT) 1937 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
1967 error = 0; 1938 error = 0;
1968 else { 1939 else {
1969 error = inode->i_op->removexattr(fhp->fh_dentry, name); 1940 error = vfs_removexattr(fhp->fh_dentry, name);
1970 if (error == -ENODATA) 1941 if (error == -ENODATA)
1971 error = 0; 1942 error = 0;
1972 } 1943 }