return -EPERM;
}
- return permission(inode, mask, NULL);
+ return inode_permission(inode, mask);
}
-int
-vfs_setxattr(struct dentry *dentry, char *name, void *value,
- size_t size, int flags)
+/**
+ * __vfs_setxattr_noperm - perform setxattr operation without performing
+ * permission checks.
+ *
+ * @dentry - object to perform setxattr on
+ * @name - xattr name to set
+ * @value - value to set @name to
+ * @size - size of @value
+ * @flags - flags to pass into filesystem operations
+ *
+ * returns the result of the internal setxattr or setsecurity operations.
+ *
+ * This function requires the caller to lock the inode's i_mutex before it
+ * is executed. It also assumes that the caller will make the appropriate
+ * permission checks.
+ */
+int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
+ const void *value, size_t size, int flags)
{
struct inode *inode = dentry->d_inode;
- int error;
-
- error = xattr_permission(inode, name, MAY_WRITE);
- if (error)
- return error;
+ int error = -EOPNOTSUPP;
- 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) {
if (!error)
fsnotify_xattr(dentry);
}
+
+ return error;
+}
+
+
+int
+vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
+ size_t size, int flags)
+{
+ struct inode *inode = dentry->d_inode;
+ int error;
+
+ error = xattr_permission(inode, name, MAY_WRITE);
+ if (error)
+ return error;
+
+ mutex_lock(&inode->i_mutex);
+ error = security_inode_setxattr(dentry, name, value, size, flags);
+ if (error)
+ goto out;
+
+ error = __vfs_setxattr_noperm(dentry, name, value, size, flags);
+
out:
mutex_unlock(&inode->i_mutex);
return error;
EXPORT_SYMBOL_GPL(xattr_getsecurity);
ssize_t
-vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
+vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
{
struct inode *inode = dentry->d_inode;
int error;
if (error)
return error;
error = -EOPNOTSUPP;
- if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
+ if (d->d_inode->i_op->listxattr) {
error = d->d_inode->i_op->listxattr(d, list, size);
} else {
error = security_inode_listsecurity(d->d_inode, list, size);
EXPORT_SYMBOL_GPL(vfs_listxattr);
int
-vfs_removexattr(struct dentry *dentry, char *name)
+vfs_removexattr(struct dentry *dentry, const char *name)
{
struct inode *inode = dentry->d_inode;
int error;
* Extended attribute SET operations
*/
static long
-setxattr(struct dentry *d, char __user *name, void __user *value,
+setxattr(struct dentry *d, const char __user *name, const void __user *value,
size_t size, int flags)
{
int error;
if (size) {
if (size > XATTR_SIZE_MAX)
return -E2BIG;
- kvalue = kmalloc(size, GFP_KERNEL);
- if (!kvalue)
- return -ENOMEM;
- if (copy_from_user(kvalue, value, size)) {
- kfree(kvalue);
- return -EFAULT;
- }
+ kvalue = memdup_user(value, size);
+ if (IS_ERR(kvalue))
+ return PTR_ERR(kvalue);
}
error = vfs_setxattr(d, kname, kvalue, size, flags);
return error;
}
-asmlinkage long
-sys_setxattr(char __user *path, char __user *name, void __user *value,
- size_t size, int flags)
+SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
+ const char __user *, name, const void __user *, value,
+ size_t, size, int, flags)
{
- struct nameidata nd;
+ struct path path;
int error;
- error = user_path_walk(path, &nd);
+ error = user_path(pathname, &path);
if (error)
return error;
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(path.mnt);
if (!error) {
- error = setxattr(nd.path.dentry, name, value, size, flags);
- mnt_drop_write(nd.path.mnt);
+ error = setxattr(path.dentry, name, value, size, flags);
+ mnt_drop_write(path.mnt);
}
- path_put(&nd.path);
+ path_put(&path);
return error;
}
-asmlinkage long
-sys_lsetxattr(char __user *path, char __user *name, void __user *value,
- size_t size, int flags)
+SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
+ const char __user *, name, const void __user *, value,
+ size_t, size, int, flags)
{
- struct nameidata nd;
+ struct path path;
int error;
- error = user_path_walk_link(path, &nd);
+ error = user_lpath(pathname, &path);
if (error)
return error;
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(path.mnt);
if (!error) {
- error = setxattr(nd.path.dentry, name, value, size, flags);
- mnt_drop_write(nd.path.mnt);
+ error = setxattr(path.dentry, name, value, size, flags);
+ mnt_drop_write(path.mnt);
}
- path_put(&nd.path);
+ path_put(&path);
return error;
}
-asmlinkage long
-sys_fsetxattr(int fd, char __user *name, void __user *value,
- size_t size, int flags)
+SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
+ const void __user *,value, size_t, size, int, flags)
{
struct file *f;
struct dentry *dentry;
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- error = mnt_want_write(f->f_path.mnt);
+ error = mnt_want_write_file(f);
if (!error) {
error = setxattr(dentry, name, value, size, flags);
mnt_drop_write(f->f_path.mnt);
* Extended attribute GET operations
*/
static ssize_t
-getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
+getxattr(struct dentry *d, const char __user *name, void __user *value,
+ size_t size)
{
ssize_t error;
void *kvalue = NULL;
return error;
}
-asmlinkage ssize_t
-sys_getxattr(char __user *path, char __user *name, void __user *value,
- size_t size)
+SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
+ const char __user *, name, void __user *, value, size_t, size)
{
- struct nameidata nd;
+ struct path path;
ssize_t error;
- error = user_path_walk(path, &nd);
+ error = user_path(pathname, &path);
if (error)
return error;
- error = getxattr(nd.path.dentry, name, value, size);
- path_put(&nd.path);
+ error = getxattr(path.dentry, name, value, size);
+ path_put(&path);
return error;
}
-asmlinkage ssize_t
-sys_lgetxattr(char __user *path, char __user *name, void __user *value,
- size_t size)
+SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname,
+ const char __user *, name, void __user *, value, size_t, size)
{
- struct nameidata nd;
+ struct path path;
ssize_t error;
- error = user_path_walk_link(path, &nd);
+ error = user_lpath(pathname, &path);
if (error)
return error;
- error = getxattr(nd.path.dentry, name, value, size);
- path_put(&nd.path);
+ error = getxattr(path.dentry, name, value, size);
+ path_put(&path);
return error;
}
-asmlinkage ssize_t
-sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
+SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
+ void __user *, value, size_t, size)
{
struct file *f;
ssize_t error = -EBADF;
return error;
}
-asmlinkage ssize_t
-sys_listxattr(char __user *path, char __user *list, size_t size)
+SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
+ size_t, size)
{
- struct nameidata nd;
+ struct path path;
ssize_t error;
- error = user_path_walk(path, &nd);
+ error = user_path(pathname, &path);
if (error)
return error;
- error = listxattr(nd.path.dentry, list, size);
- path_put(&nd.path);
+ error = listxattr(path.dentry, list, size);
+ path_put(&path);
return error;
}
-asmlinkage ssize_t
-sys_llistxattr(char __user *path, char __user *list, size_t size)
+SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
+ size_t, size)
{
- struct nameidata nd;
+ struct path path;
ssize_t error;
- error = user_path_walk_link(path, &nd);
+ error = user_lpath(pathname, &path);
if (error)
return error;
- error = listxattr(nd.path.dentry, list, size);
- path_put(&nd.path);
+ error = listxattr(path.dentry, list, size);
+ path_put(&path);
return error;
}
-asmlinkage ssize_t
-sys_flistxattr(int fd, char __user *list, size_t size)
+SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
{
struct file *f;
ssize_t error = -EBADF;
* Extended attribute REMOVE operations
*/
static long
-removexattr(struct dentry *d, char __user *name)
+removexattr(struct dentry *d, const char __user *name)
{
int error;
char kname[XATTR_NAME_MAX + 1];
return vfs_removexattr(d, kname);
}
-asmlinkage long
-sys_removexattr(char __user *path, char __user *name)
+SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
+ const char __user *, name)
{
- struct nameidata nd;
+ struct path path;
int error;
- error = user_path_walk(path, &nd);
+ error = user_path(pathname, &path);
if (error)
return error;
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(path.mnt);
if (!error) {
- error = removexattr(nd.path.dentry, name);
- mnt_drop_write(nd.path.mnt);
+ error = removexattr(path.dentry, name);
+ mnt_drop_write(path.mnt);
}
- path_put(&nd.path);
+ path_put(&path);
return error;
}
-asmlinkage long
-sys_lremovexattr(char __user *path, char __user *name)
+SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
+ const char __user *, name)
{
- struct nameidata nd;
+ struct path path;
int error;
- error = user_path_walk_link(path, &nd);
+ error = user_lpath(pathname, &path);
if (error)
return error;
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(path.mnt);
if (!error) {
- error = removexattr(nd.path.dentry, name);
- mnt_drop_write(nd.path.mnt);
+ error = removexattr(path.dentry, name);
+ mnt_drop_write(path.mnt);
}
- path_put(&nd.path);
+ path_put(&path);
return error;
}
-asmlinkage long
-sys_fremovexattr(int fd, char __user *name)
+SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
{
struct file *f;
struct dentry *dentry;
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- error = mnt_want_write(f->f_path.mnt);
+ error = mnt_want_write_file(f);
if (!error) {
error = removexattr(dentry, name);
mnt_drop_write(f->f_path.mnt);
generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
{
struct xattr_handler *handler;
- struct inode *inode = dentry->d_inode;
- handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
+ handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
if (!handler)
return -EOPNOTSUPP;
- return handler->get(inode, name, buffer, size);
+ return handler->get(dentry, name, buffer, size, handler->flags);
}
/*
ssize_t
generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
{
- struct inode *inode = dentry->d_inode;
- struct xattr_handler *handler, **handlers = inode->i_sb->s_xattr;
+ struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
unsigned int size = 0;
if (!buffer) {
- for_each_xattr_handler(handlers, handler)
- size += handler->list(inode, NULL, 0, NULL, 0);
+ for_each_xattr_handler(handlers, handler) {
+ size += handler->list(dentry, NULL, 0, NULL, 0,
+ handler->flags);
+ }
} else {
char *buf = buffer;
for_each_xattr_handler(handlers, handler) {
- size = handler->list(inode, buf, buffer_size, NULL, 0);
+ size = handler->list(dentry, buf, buffer_size,
+ NULL, 0, handler->flags);
if (size > buffer_size)
return -ERANGE;
buf += size;
generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
{
struct xattr_handler *handler;
- struct inode *inode = dentry->d_inode;
if (size == 0)
value = ""; /* empty EA, do not remove */
- handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
+ handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
if (!handler)
return -EOPNOTSUPP;
- return handler->set(inode, name, value, size, flags);
+ return handler->set(dentry, name, value, size, 0, handler->flags);
}
/*
generic_removexattr(struct dentry *dentry, const char *name)
{
struct xattr_handler *handler;
- struct inode *inode = dentry->d_inode;
- handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
+ handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
if (!handler)
return -EOPNOTSUPP;
- return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
+ return handler->set(dentry, name, NULL, 0,
+ XATTR_REPLACE, handler->flags);
}
EXPORT_SYMBOL(generic_getxattr);