X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=fs%2Fxattr.c;h=1c3d0af59ddf84c7fb51c3f5da52803d2d095e9a;hb=80fc015bdfe1f5b870c1e1ee02d78e709523fee7;hp=1858552a6a1a0c6af76afb92316507c7d2d352eb;hpb=42492594043d621a7910ff5877c3eb9202870b45;p=safe%2Fjmp%2Flinux-2.6 diff --git a/fs/xattr.c b/fs/xattr.c index 1858552..1c3d0af 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -32,8 +33,6 @@ xattr_permission(struct inode *inode, const char *name, int mask) * filesystem or on an immutable / append-only inode. */ if (mask & MAY_WRITE) { - if (IS_RDONLY(inode)) - return -EROFS; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) return -EPERM; } @@ -64,11 +63,11 @@ xattr_permission(struct inode *inode, const char *name, int mask) return -EPERM; } - return permission(inode, mask, NULL); + return inode_permission(inode, mask); } int -vfs_setxattr(struct dentry *dentry, char *name, void *value, +vfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { struct inode *inode = dentry->d_inode; @@ -132,7 +131,7 @@ out_noalloc: 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; @@ -145,11 +144,6 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size) 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, XATTR_SECURITY_PREFIX_LEN)) { const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; @@ -158,9 +152,15 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size) * Only overwrite the return value if a security module * is actually active. */ - if (ret != -EOPNOTSUPP) - error = ret; + if (ret == -EOPNOTSUPP) + goto nolsm; + return ret; } +nolsm: + if (inode->i_op->getxattr) + error = inode->i_op->getxattr(dentry, name, value, size); + else + error = -EOPNOTSUPP; return error; } @@ -175,7 +175,7 @@ vfs_listxattr(struct dentry *d, char *list, size_t size) 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); @@ -187,7 +187,7 @@ vfs_listxattr(struct dentry *d, char *list, size_t 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; @@ -218,7 +218,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr); * 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; @@ -237,13 +237,9 @@ setxattr(struct dentry *d, char __user *name, void __user *value, 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); @@ -251,39 +247,46 @@ setxattr(struct dentry *d, char __user *name, void __user *value, 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 = setxattr(nd.dentry, name, value, size, flags); - path_release(&nd); + error = mnt_want_write(path.mnt); + if (!error) { + error = setxattr(path.dentry, name, value, size, flags); + mnt_drop_write(path.mnt); + } + 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 = setxattr(nd.dentry, name, value, size, flags); - path_release(&nd); + error = mnt_want_write(path.mnt); + if (!error) { + error = setxattr(path.dentry, name, value, size, flags); + mnt_drop_write(path.mnt); + } + 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; @@ -294,7 +297,11 @@ sys_fsetxattr(int fd, char __user *name, void __user *value, return error; dentry = f->f_path.dentry; audit_inode(NULL, dentry); - error = setxattr(dentry, name, value, size, flags); + error = mnt_want_write_file(f); + if (!error) { + error = setxattr(dentry, name, value, size, flags); + mnt_drop_write(f->f_path.mnt); + } fput(f); return error; } @@ -303,7 +310,8 @@ sys_fsetxattr(int fd, char __user *name, void __user *value, * 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; @@ -336,38 +344,36 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) 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.dentry, name, value, size); - path_release(&nd); + 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.dentry, name, value, size); - path_release(&nd); + 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; @@ -411,36 +417,35 @@ listxattr(struct dentry *d, char __user *list, size_t size) 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.dentry, list, size); - path_release(&nd); + 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.dentry, list, size); - path_release(&nd); + 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; @@ -458,7 +463,7 @@ sys_flistxattr(int fd, char __user *list, size_t size) * 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]; @@ -472,36 +477,43 @@ removexattr(struct dentry *d, char __user *name) 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 = removexattr(nd.dentry, name); - path_release(&nd); + error = mnt_want_write(path.mnt); + if (!error) { + error = removexattr(path.dentry, name); + mnt_drop_write(path.mnt); + } + 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 = removexattr(nd.dentry, name); - path_release(&nd); + error = mnt_want_write(path.mnt); + if (!error) { + error = removexattr(path.dentry, name); + mnt_drop_write(path.mnt); + } + 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; @@ -512,7 +524,11 @@ sys_fremovexattr(int fd, char __user *name) return error; dentry = f->f_path.dentry; audit_inode(NULL, dentry); - error = removexattr(dentry, name); + error = mnt_want_write_file(f); + if (!error) { + error = removexattr(dentry, name); + mnt_drop_write(f->f_path.mnt); + } fput(f); return error; }