Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 17554
b: refs/heads/master
c: 5be196e
h: refs/heads/master
v: v3
  • Loading branch information
Christoph Hellwig authored and Linus Torvalds committed Jan 10, 2006
1 parent 7298de2 commit 5a1f3eb
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 131 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a7e670d828e85ef9aacb7fa1cd221525c408110f
refs/heads/master: 5be196e5f925dab2309530fabce69c2e562b9791
125 changes: 48 additions & 77 deletions trunk/fs/nfsd/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@
#include <linux/fsnotify.h>
#include <linux/posix_acl.h>
#include <linux/posix_acl_xattr.h>
#ifdef CONFIG_NFSD_V4
#include <linux/xattr.h>
#ifdef CONFIG_NFSD_V4
#include <linux/nfs4.h>
#include <linux/nfs4_acl.h>
#include <linux/nfsd_idmap.h>
Expand Down Expand Up @@ -365,16 +365,37 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
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
set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
{
int len;
size_t buflen;
char *buf = NULL;
int error = 0;
struct inode *inode = dentry->d_inode;

buflen = posix_acl_xattr_size(pacl->a_count);
buf = kmalloc(buflen, GFP_KERNEL);
Expand All @@ -388,15 +409,7 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
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:
kfree(buf);
return error;
Expand Down Expand Up @@ -455,44 +468,19 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
static struct posix_acl *
_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;
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);
out:
kfree(buf);
return pacl;
out_err:
pacl = ERR_PTR(error);
goto out;
}

int
Expand Down Expand Up @@ -1884,39 +1872,25 @@ nfsd_get_posix_acl(struct svc_fh *fhp, int type)
ssize_t size;
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);
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);

getout:
kfree(value);
return acl;
}
Expand Down Expand Up @@ -1957,16 +1931,13 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
} else
size = 0;

if (!fhp->fh_locked)
fh_lock(fhp); /* unlocking is done automatically */
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 {
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
error = 0;
else {
error = inode->i_op->removexattr(fhp->fh_dentry, name);
error = vfs_removexattr(fhp->fh_dentry, name);
if (error == -ENODATA)
error = 0;
}
Expand Down
146 changes: 93 additions & 53 deletions trunk/fs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,96 @@
#include <linux/fsnotify.h>
#include <asm/uaccess.h>


int
vfs_setxattr(struct dentry *dentry, char *name, void *value,
size_t size, int flags)
{
struct inode *inode = dentry->d_inode;
int error;

mutex_lock(&inode->i_mutex);
error = security_inode_setxattr(dentry, name, value, size, flags);
if (error)
goto out;
error = -EOPNOTSUPP;
if (inode->i_op->setxattr) {
error = inode->i_op->setxattr(dentry, name, value, size, flags);
if (!error) {
fsnotify_xattr(dentry);
security_inode_post_setxattr(dentry, name, value,
size, flags);
}
} else if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof XATTR_SECURITY_PREFIX - 1)) {
const char *suffix = name + sizeof XATTR_SECURITY_PREFIX - 1;
error = security_inode_setsecurity(inode, suffix, value,
size, flags);
if (!error)
fsnotify_xattr(dentry);
}
out:
mutex_unlock(&inode->i_mutex);
return error;
}
EXPORT_SYMBOL_GPL(vfs_setxattr);

ssize_t
vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
{
struct inode *inode = dentry->d_inode;
int error;

error = security_inode_getxattr(dentry, name);
if (error)
return error;

if (inode->i_op->getxattr)
error = inode->i_op->getxattr(dentry, name, value, size);
else
error = -EOPNOTSUPP;

if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof XATTR_SECURITY_PREFIX - 1)) {
const char *suffix = name + sizeof XATTR_SECURITY_PREFIX - 1;
int ret = security_inode_getsecurity(inode, suffix, value,
size, error);
/*
* Only overwrite the return value if a security module
* is actually active.
*/
if (ret != -EOPNOTSUPP)
error = ret;
}

return error;
}
EXPORT_SYMBOL_GPL(vfs_getxattr);

int
vfs_removexattr(struct dentry *dentry, char *name)
{
struct inode *inode = dentry->d_inode;
int error;

if (!inode->i_op->removexattr)
return -EOPNOTSUPP;

error = security_inode_removexattr(dentry, name);
if (error)
return error;

mutex_lock(&inode->i_mutex);
error = inode->i_op->removexattr(dentry, name);
mutex_unlock(&inode->i_mutex);

if (!error)
fsnotify_xattr(dentry);
return error;
}
EXPORT_SYMBOL_GPL(vfs_removexattr);


/*
* Extended attribute SET operations
*/
Expand Down Expand Up @@ -51,29 +141,7 @@ setxattr(struct dentry *d, char __user *name, void __user *value,
}
}

mutex_lock(&d->d_inode->i_mutex);
error = security_inode_setxattr(d, kname, kvalue, size, flags);
if (error)
goto out;
error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
error = d->d_inode->i_op->setxattr(d, kname, kvalue,
size, flags);
if (!error) {
fsnotify_xattr(d);
security_inode_post_setxattr(d, kname, kvalue,
size, flags);
}
} else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
sizeof XATTR_SECURITY_PREFIX - 1)) {
const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
error = security_inode_setsecurity(d->d_inode, suffix, kvalue,
size, flags);
if (!error)
fsnotify_xattr(d);
}
out:
mutex_unlock(&d->d_inode->i_mutex);
error = vfs_setxattr(d, kname, kvalue, size, flags);
kfree(kvalue);
return error;
}
Expand Down Expand Up @@ -147,22 +215,7 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
return -ENOMEM;
}

error = security_inode_getxattr(d, kname);
if (error)
goto out;
error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->getxattr)
error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);

if (!strncmp(kname, XATTR_SECURITY_PREFIX,
sizeof XATTR_SECURITY_PREFIX - 1)) {
const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
int rv = security_inode_getsecurity(d->d_inode, suffix, kvalue,
size, error);
/* Security module active: overwrite error value */
if (rv != -EOPNOTSUPP)
error = rv;
}
error = vfs_getxattr(d, kname, kvalue, size);
if (error > 0) {
if (size && copy_to_user(value, kvalue, error))
error = -EFAULT;
Expand All @@ -171,7 +224,6 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
than XATTR_SIZE_MAX bytes. Not possible. */
error = -E2BIG;
}
out:
kfree(kvalue);
return error;
}
Expand Down Expand Up @@ -318,19 +370,7 @@ removexattr(struct dentry *d, char __user *name)
if (error < 0)
return error;

error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
error = security_inode_removexattr(d, kname);
if (error)
goto out;
mutex_lock(&d->d_inode->i_mutex);
error = d->d_inode->i_op->removexattr(d, kname);
mutex_unlock(&d->d_inode->i_mutex);
if (!error)
fsnotify_xattr(d);
}
out:
return error;
return vfs_removexattr(d, kname);
}

asmlinkage long
Expand Down
4 changes: 4 additions & 0 deletions trunk/include/linux/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ struct xattr_handler {
size_t size, int flags);
};

ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
int vfs_removexattr(struct dentry *, char *);

ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
int generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
Expand Down

0 comments on commit 5a1f3eb

Please sign in to comment.