|
@@ -468,158 +468,7 @@ out:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-#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;
|
|
|
- ssize_t ret;
|
|
|
-
|
|
|
- buflen = vfs_getxattr(dentry, key, NULL, 0);
|
|
|
- if (buflen <= 0)
|
|
|
- return buflen;
|
|
|
-
|
|
|
- *buf = kmalloc(buflen, GFP_KERNEL);
|
|
|
- if (!*buf)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- ret = vfs_getxattr(dentry, key, *buf, buflen);
|
|
|
- if (ret < 0)
|
|
|
- kfree(*buf);
|
|
|
- return ret;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
#if defined(CONFIG_NFSD_V4)
|
|
|
-static int
|
|
|
-set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
|
|
|
-{
|
|
|
- int len;
|
|
|
- size_t buflen;
|
|
|
- char *buf = NULL;
|
|
|
- int error = 0;
|
|
|
-
|
|
|
- buflen = posix_acl_xattr_size(pacl->a_count);
|
|
|
- buf = kmalloc(buflen, GFP_KERNEL);
|
|
|
- error = -ENOMEM;
|
|
|
- if (buf == NULL)
|
|
|
- goto out;
|
|
|
-
|
|
|
- len = posix_acl_to_xattr(&init_user_ns, pacl, buf, buflen);
|
|
|
- if (len < 0) {
|
|
|
- error = len;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- error = vfs_setxattr(dentry, key, buf, len, 0);
|
|
|
-out:
|
|
|
- kfree(buf);
|
|
|
- return error;
|
|
|
-}
|
|
|
-
|
|
|
-__be32
|
|
|
-nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
|
|
- struct nfs4_acl *acl)
|
|
|
-{
|
|
|
- __be32 error;
|
|
|
- int host_error;
|
|
|
- struct dentry *dentry;
|
|
|
- struct inode *inode;
|
|
|
- struct posix_acl *pacl = NULL, *dpacl = NULL;
|
|
|
- unsigned int flags = 0;
|
|
|
-
|
|
|
- /* Get inode */
|
|
|
- error = fh_verify(rqstp, fhp, 0, NFSD_MAY_SATTR);
|
|
|
- if (error)
|
|
|
- return error;
|
|
|
-
|
|
|
- dentry = fhp->fh_dentry;
|
|
|
- inode = dentry->d_inode;
|
|
|
- if (S_ISDIR(inode->i_mode))
|
|
|
- flags = NFS4_ACL_DIR;
|
|
|
-
|
|
|
- host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
|
|
|
- if (host_error == -EINVAL) {
|
|
|
- return nfserr_attrnotsupp;
|
|
|
- } else if (host_error < 0)
|
|
|
- goto out_nfserr;
|
|
|
-
|
|
|
- host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
|
|
|
- if (host_error < 0)
|
|
|
- goto out_release;
|
|
|
-
|
|
|
- if (S_ISDIR(inode->i_mode))
|
|
|
- host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
|
|
|
-
|
|
|
-out_release:
|
|
|
- posix_acl_release(pacl);
|
|
|
- posix_acl_release(dpacl);
|
|
|
-out_nfserr:
|
|
|
- if (host_error == -EOPNOTSUPP)
|
|
|
- return nfserr_attrnotsupp;
|
|
|
- else
|
|
|
- return nfserrno(host_error);
|
|
|
-}
|
|
|
-
|
|
|
-static struct posix_acl *
|
|
|
-_get_posix_acl(struct dentry *dentry, char *key)
|
|
|
-{
|
|
|
- void *buf = NULL;
|
|
|
- struct posix_acl *pacl = NULL;
|
|
|
- int buflen;
|
|
|
-
|
|
|
- buflen = nfsd_getxattr(dentry, key, &buf);
|
|
|
- if (!buflen)
|
|
|
- buflen = -ENODATA;
|
|
|
- if (buflen <= 0)
|
|
|
- return ERR_PTR(buflen);
|
|
|
-
|
|
|
- pacl = posix_acl_from_xattr(&init_user_ns, buf, buflen);
|
|
|
- kfree(buf);
|
|
|
- return pacl;
|
|
|
-}
|
|
|
-
|
|
|
-int
|
|
|
-nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
|
|
|
-{
|
|
|
- struct inode *inode = dentry->d_inode;
|
|
|
- int error = 0;
|
|
|
- struct posix_acl *pacl = NULL, *dpacl = NULL;
|
|
|
- unsigned int flags = 0;
|
|
|
-
|
|
|
- pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
|
|
|
- if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
|
|
|
- pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
|
|
|
- if (IS_ERR(pacl)) {
|
|
|
- error = PTR_ERR(pacl);
|
|
|
- pacl = NULL;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- if (S_ISDIR(inode->i_mode)) {
|
|
|
- dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
|
|
|
- if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
|
|
|
- dpacl = NULL;
|
|
|
- else if (IS_ERR(dpacl)) {
|
|
|
- error = PTR_ERR(dpacl);
|
|
|
- dpacl = NULL;
|
|
|
- goto out;
|
|
|
- }
|
|
|
- flags = NFS4_ACL_DIR;
|
|
|
- }
|
|
|
-
|
|
|
- *acl = nfs4_acl_posix_to_nfsv4(pacl, dpacl, flags);
|
|
|
- if (IS_ERR(*acl)) {
|
|
|
- error = PTR_ERR(*acl);
|
|
|
- *acl = NULL;
|
|
|
- }
|
|
|
- out:
|
|
|
- posix_acl_release(pacl);
|
|
|
- posix_acl_release(dpacl);
|
|
|
- return error;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* NFS junction information is stored in an extended attribute.
|
|
|
*/
|
|
@@ -2284,93 +2133,3 @@ out_nomem:
|
|
|
nfsd_racache_shutdown();
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
-
|
|
|
-#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
|
|
|
-struct posix_acl *
|
|
|
-nfsd_get_posix_acl(struct svc_fh *fhp, int type)
|
|
|
-{
|
|
|
- struct inode *inode = fhp->fh_dentry->d_inode;
|
|
|
- char *name;
|
|
|
- void *value = NULL;
|
|
|
- ssize_t size;
|
|
|
- struct posix_acl *acl;
|
|
|
-
|
|
|
- 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);
|
|
|
- }
|
|
|
-
|
|
|
- size = nfsd_getxattr(fhp->fh_dentry, name, &value);
|
|
|
- if (size < 0)
|
|
|
- return ERR_PTR(size);
|
|
|
-
|
|
|
- acl = posix_acl_from_xattr(&init_user_ns, value, size);
|
|
|
- kfree(value);
|
|
|
- return acl;
|
|
|
-}
|
|
|
-
|
|
|
-int
|
|
|
-nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
|
|
|
-{
|
|
|
- struct inode *inode = fhp->fh_dentry->d_inode;
|
|
|
- char *name;
|
|
|
- void *value = NULL;
|
|
|
- size_t size;
|
|
|
- int error;
|
|
|
-
|
|
|
- if (!IS_POSIXACL(inode) ||
|
|
|
- !inode->i_op->setxattr || !inode->i_op->removexattr)
|
|
|
- return -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 -EOPNOTSUPP;
|
|
|
- }
|
|
|
-
|
|
|
- if (acl && acl->a_count) {
|
|
|
- size = posix_acl_xattr_size(acl->a_count);
|
|
|
- value = kmalloc(size, GFP_KERNEL);
|
|
|
- if (!value)
|
|
|
- return -ENOMEM;
|
|
|
- error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
|
|
|
- if (error < 0)
|
|
|
- goto getout;
|
|
|
- size = error;
|
|
|
- } else
|
|
|
- size = 0;
|
|
|
-
|
|
|
- error = fh_want_write(fhp);
|
|
|
- if (error)
|
|
|
- goto getout;
|
|
|
- if (size)
|
|
|
- error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
|
|
|
- else {
|
|
|
- if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
|
|
|
- error = 0;
|
|
|
- else {
|
|
|
- error = vfs_removexattr(fhp->fh_dentry, name);
|
|
|
- if (error == -ENODATA)
|
|
|
- error = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- fh_drop_write(fhp);
|
|
|
-
|
|
|
-getout:
|
|
|
- kfree(value);
|
|
|
- return error;
|
|
|
-}
|
|
|
-#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
|