|
@@ -48,8 +48,8 @@
|
|
|
#include <linux/fsnotify.h>
|
|
#include <linux/fsnotify.h>
|
|
|
#include <linux/posix_acl.h>
|
|
#include <linux/posix_acl.h>
|
|
|
#include <linux/posix_acl_xattr.h>
|
|
#include <linux/posix_acl_xattr.h>
|
|
|
-#ifdef CONFIG_NFSD_V4
|
|
|
|
|
#include <linux/xattr.h>
|
|
#include <linux/xattr.h>
|
|
|
|
|
+#ifdef CONFIG_NFSD_V4
|
|
|
#include <linux/nfs4.h>
|
|
#include <linux/nfs4.h>
|
|
|
#include <linux/nfs4_acl.h>
|
|
#include <linux/nfs4_acl.h>
|
|
|
#include <linux/nfsd_idmap.h>
|
|
#include <linux/nfsd_idmap.h>
|
|
@@ -365,8 +365,30 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
|
|
|
goto out;
|
|
goto out;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-#if defined(CONFIG_NFSD_V4)
|
|
|
|
|
|
|
+#if defined(CONFIG_NFSD_V2_ACL) || \
|
|
|
|
|
+ defined(CONFIG_NFSD_V3_ACL) || \
|
|
|
|
|
+ defined(CONFIG_NFSD_V4)
|
|
|
|
|
+static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
|
|
|
|
|
+{
|
|
|
|
|
+ ssize_t buflen;
|
|
|
|
|
+ int error;
|
|
|
|
|
+
|
|
|
|
|
+ buflen = vfs_getxattr(dentry, key, NULL, 0);
|
|
|
|
|
+ if (buflen <= 0)
|
|
|
|
|
+ return buflen;
|
|
|
|
|
|
|
|
|
|
+ *buf = kmalloc(buflen, GFP_KERNEL);
|
|
|
|
|
+ if (!*buf)
|
|
|
|
|
+ return -ENOMEM;
|
|
|
|
|
+
|
|
|
|
|
+ error = vfs_getxattr(dentry, key, *buf, buflen);
|
|
|
|
|
+ if (error < 0)
|
|
|
|
|
+ return error;
|
|
|
|
|
+ return buflen;
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#if defined(CONFIG_NFSD_V4)
|
|
|
static int
|
|
static int
|
|
|
set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
|
|
set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
|
|
|
{
|
|
{
|
|
@@ -374,7 +396,6 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
|
|
|
size_t buflen;
|
|
size_t buflen;
|
|
|
char *buf = NULL;
|
|
char *buf = NULL;
|
|
|
int error = 0;
|
|
int error = 0;
|
|
|
- struct inode *inode = dentry->d_inode;
|
|
|
|
|
|
|
|
|
|
buflen = posix_acl_xattr_size(pacl->a_count);
|
|
buflen = posix_acl_xattr_size(pacl->a_count);
|
|
|
buf = kmalloc(buflen, GFP_KERNEL);
|
|
buf = kmalloc(buflen, GFP_KERNEL);
|
|
@@ -388,15 +409,7 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
|
|
|
goto out;
|
|
goto out;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- error = -EOPNOTSUPP;
|
|
|
|
|
- if (inode->i_op && inode->i_op->setxattr) {
|
|
|
|
|
- mutex_lock(&inode->i_mutex);
|
|
|
|
|
- security_inode_setxattr(dentry, key, buf, len, 0);
|
|
|
|
|
- error = inode->i_op->setxattr(dentry, key, buf, len, 0);
|
|
|
|
|
- if (!error)
|
|
|
|
|
- security_inode_post_setxattr(dentry, key, buf, len, 0);
|
|
|
|
|
- mutex_unlock(&inode->i_mutex);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ error = vfs_setxattr(dentry, key, buf, len, 0);
|
|
|
out:
|
|
out:
|
|
|
kfree(buf);
|
|
kfree(buf);
|
|
|
return error;
|
|
return error;
|
|
@@ -455,44 +468,19 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
|
|
static struct posix_acl *
|
|
static struct posix_acl *
|
|
|
_get_posix_acl(struct dentry *dentry, char *key)
|
|
_get_posix_acl(struct dentry *dentry, char *key)
|
|
|
{
|
|
{
|
|
|
- struct inode *inode = dentry->d_inode;
|
|
|
|
|
- char *buf = NULL;
|
|
|
|
|
- int buflen, error = 0;
|
|
|
|
|
|
|
+ void *buf = NULL;
|
|
|
struct posix_acl *pacl = NULL;
|
|
struct posix_acl *pacl = NULL;
|
|
|
|
|
+ int buflen;
|
|
|
|
|
|
|
|
- error = -EOPNOTSUPP;
|
|
|
|
|
- if (inode->i_op == NULL)
|
|
|
|
|
- goto out_err;
|
|
|
|
|
- if (inode->i_op->getxattr == NULL)
|
|
|
|
|
- goto out_err;
|
|
|
|
|
-
|
|
|
|
|
- error = security_inode_getxattr(dentry, key);
|
|
|
|
|
- if (error)
|
|
|
|
|
- goto out_err;
|
|
|
|
|
-
|
|
|
|
|
- buflen = inode->i_op->getxattr(dentry, key, NULL, 0);
|
|
|
|
|
- if (buflen <= 0) {
|
|
|
|
|
- error = buflen < 0 ? buflen : -ENODATA;
|
|
|
|
|
- goto out_err;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- buf = kmalloc(buflen, GFP_KERNEL);
|
|
|
|
|
- if (buf == NULL) {
|
|
|
|
|
- error = -ENOMEM;
|
|
|
|
|
- goto out_err;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- error = inode->i_op->getxattr(dentry, key, buf, buflen);
|
|
|
|
|
- if (error < 0)
|
|
|
|
|
- goto out_err;
|
|
|
|
|
|
|
+ buflen = nfsd_getxattr(dentry, key, &buf);
|
|
|
|
|
+ if (!buflen)
|
|
|
|
|
+ buflen = -ENODATA;
|
|
|
|
|
+ if (buflen <= 0)
|
|
|
|
|
+ return ERR_PTR(buflen);
|
|
|
|
|
|
|
|
pacl = posix_acl_from_xattr(buf, buflen);
|
|
pacl = posix_acl_from_xattr(buf, buflen);
|
|
|
- out:
|
|
|
|
|
kfree(buf);
|
|
kfree(buf);
|
|
|
return pacl;
|
|
return pacl;
|
|
|
- out_err:
|
|
|
|
|
- pacl = ERR_PTR(error);
|
|
|
|
|
- goto out;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int
|
|
int
|
|
@@ -1884,39 +1872,25 @@ nfsd_get_posix_acl(struct svc_fh *fhp, int type)
|
|
|
ssize_t size;
|
|
ssize_t size;
|
|
|
struct posix_acl *acl;
|
|
struct posix_acl *acl;
|
|
|
|
|
|
|
|
- if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr)
|
|
|
|
|
|
|
+ if (!IS_POSIXACL(inode))
|
|
|
|
|
+ return ERR_PTR(-EOPNOTSUPP);
|
|
|
|
|
+
|
|
|
|
|
+ switch (type) {
|
|
|
|
|
+ case ACL_TYPE_ACCESS:
|
|
|
|
|
+ name = POSIX_ACL_XATTR_ACCESS;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case ACL_TYPE_DEFAULT:
|
|
|
|
|
+ name = POSIX_ACL_XATTR_DEFAULT;
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
return ERR_PTR(-EOPNOTSUPP);
|
|
return ERR_PTR(-EOPNOTSUPP);
|
|
|
- switch(type) {
|
|
|
|
|
- case ACL_TYPE_ACCESS:
|
|
|
|
|
- name = POSIX_ACL_XATTR_ACCESS;
|
|
|
|
|
- break;
|
|
|
|
|
- case ACL_TYPE_DEFAULT:
|
|
|
|
|
- name = POSIX_ACL_XATTR_DEFAULT;
|
|
|
|
|
- break;
|
|
|
|
|
- default:
|
|
|
|
|
- return ERR_PTR(-EOPNOTSUPP);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0);
|
|
|
|
|
|
|
+ size = nfsd_getxattr(fhp->fh_dentry, name, &value);
|
|
|
|
|
+ if (size < 0)
|
|
|
|
|
+ return ERR_PTR(size);
|
|
|
|
|
|
|
|
- if (size < 0) {
|
|
|
|
|
- acl = ERR_PTR(size);
|
|
|
|
|
- goto getout;
|
|
|
|
|
- } else if (size > 0) {
|
|
|
|
|
- value = kmalloc(size, GFP_KERNEL);
|
|
|
|
|
- if (!value) {
|
|
|
|
|
- acl = ERR_PTR(-ENOMEM);
|
|
|
|
|
- goto getout;
|
|
|
|
|
- }
|
|
|
|
|
- size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size);
|
|
|
|
|
- if (size < 0) {
|
|
|
|
|
- acl = ERR_PTR(size);
|
|
|
|
|
- goto getout;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
acl = posix_acl_from_xattr(value, size);
|
|
acl = posix_acl_from_xattr(value, size);
|
|
|
-
|
|
|
|
|
-getout:
|
|
|
|
|
kfree(value);
|
|
kfree(value);
|
|
|
return acl;
|
|
return acl;
|
|
|
}
|
|
}
|
|
@@ -1957,16 +1931,13 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
|
|
|
} else
|
|
} else
|
|
|
size = 0;
|
|
size = 0;
|
|
|
|
|
|
|
|
- if (!fhp->fh_locked)
|
|
|
|
|
- fh_lock(fhp); /* unlocking is done automatically */
|
|
|
|
|
if (size)
|
|
if (size)
|
|
|
- error = inode->i_op->setxattr(fhp->fh_dentry, name,
|
|
|
|
|
- value, size, 0);
|
|
|
|
|
|
|
+ error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
|
|
|
else {
|
|
else {
|
|
|
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
|
|
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
|
|
|
error = 0;
|
|
error = 0;
|
|
|
else {
|
|
else {
|
|
|
- error = inode->i_op->removexattr(fhp->fh_dentry, name);
|
|
|
|
|
|
|
+ error = vfs_removexattr(fhp->fh_dentry, name);
|
|
|
if (error == -ENODATA)
|
|
if (error == -ENODATA)
|
|
|
error = 0;
|
|
error = 0;
|
|
|
}
|
|
}
|