forked from luck/tmp_suning_uos_patched
[PATCH] sanitize __user_walk_fd() et.al.
* do not pass nameidata; struct path is all the callers want. * switch to new helpers: user_path_at(dfd, pathname, flags, &path) user_path(pathname, &path) user_lpath(pathname, &path) user_path_dir(pathname, &path) (fail if not a directory) The last 3 are trivial macro wrappers for the first one. * remove nameidata in callers. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
256984a838
commit
2d8f30380a
|
@ -253,15 +253,15 @@ do_osf_statfs(struct dentry * dentry, struct osf_statfs __user *buffer,
|
|||
}
|
||||
|
||||
asmlinkage int
|
||||
osf_statfs(char __user *path, struct osf_statfs __user *buffer, unsigned long bufsiz)
|
||||
osf_statfs(char __user *pathname, struct osf_statfs __user *buffer, unsigned long bufsiz)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int retval;
|
||||
|
||||
retval = user_path_walk(path, &nd);
|
||||
retval = user_path(pathname, &path);
|
||||
if (!retval) {
|
||||
retval = do_osf_statfs(nd.path.dentry, buffer, bufsiz);
|
||||
path_put(&nd.path);
|
||||
retval = do_osf_statfs(path.dentry, buffer, bufsiz);
|
||||
path_put(&path);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -210,19 +210,19 @@ static int vfs_statfs_hpux(struct dentry *dentry, struct hpux_statfs *buf)
|
|||
}
|
||||
|
||||
/* hpux statfs */
|
||||
asmlinkage long hpux_statfs(const char __user *path,
|
||||
asmlinkage long hpux_statfs(const char __user *pathname,
|
||||
struct hpux_statfs __user *buf)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
error = user_path_walk(path, &nd);
|
||||
error = user_path(pathname, &path);
|
||||
if (!error) {
|
||||
struct hpux_statfs tmp;
|
||||
error = vfs_statfs_hpux(nd.path.dentry, &tmp);
|
||||
error = vfs_statfs_hpux(path.dentry, &tmp);
|
||||
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
|
||||
error = -EFAULT;
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ static int coda_ioctl_permission(struct inode *inode, int mask)
|
|||
static int coda_pioctl(struct inode * inode, struct file * filp,
|
||||
unsigned int cmd, unsigned long user_data)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int error;
|
||||
struct PioctlData data;
|
||||
struct inode *target_inode = NULL;
|
||||
|
@ -64,21 +64,21 @@ static int coda_pioctl(struct inode * inode, struct file * filp,
|
|||
* Look up the pathname. Note that the pathname is in
|
||||
* user memory, and namei takes care of this
|
||||
*/
|
||||
if ( data.follow ) {
|
||||
error = user_path_walk(data.path, &nd);
|
||||
if (data.follow) {
|
||||
error = user_path(data.path, &path);
|
||||
} else {
|
||||
error = user_path_walk_link(data.path, &nd);
|
||||
error = user_lpath(data.path, &path);
|
||||
}
|
||||
|
||||
if ( error ) {
|
||||
return error;
|
||||
} else {
|
||||
target_inode = nd.path.dentry->d_inode;
|
||||
target_inode = path.dentry->d_inode;
|
||||
}
|
||||
|
||||
/* return if it is not a Coda inode */
|
||||
if ( target_inode->i_sb != inode->i_sb ) {
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ static int coda_pioctl(struct inode * inode, struct file * filp,
|
|||
|
||||
error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data);
|
||||
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
20
fs/compat.c
20
fs/compat.c
|
@ -234,18 +234,18 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
|
|||
* The following statfs calls are copies of code from fs/open.c and
|
||||
* should be checked against those from time to time
|
||||
*/
|
||||
asmlinkage long compat_sys_statfs(const char __user *path, struct compat_statfs __user *buf)
|
||||
asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
error = user_path_walk(path, &nd);
|
||||
error = user_path(pathname, &path);
|
||||
if (!error) {
|
||||
struct kstatfs tmp;
|
||||
error = vfs_statfs(nd.path.dentry, &tmp);
|
||||
error = vfs_statfs(path.dentry, &tmp);
|
||||
if (!error)
|
||||
error = put_compat_statfs(buf, &tmp);
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
@ -299,21 +299,21 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat
|
|||
return 0;
|
||||
}
|
||||
|
||||
asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, struct compat_statfs64 __user *buf)
|
||||
asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t sz, struct compat_statfs64 __user *buf)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
if (sz != sizeof(*buf))
|
||||
return -EINVAL;
|
||||
|
||||
error = user_path_walk(path, &nd);
|
||||
error = user_path(pathname, &path);
|
||||
if (!error) {
|
||||
struct kstatfs tmp;
|
||||
error = vfs_statfs(nd.path.dentry, &tmp);
|
||||
error = vfs_statfs(path.dentry, &tmp);
|
||||
if (!error)
|
||||
error = put_compat_statfs64(buf, &tmp);
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -354,20 +354,20 @@ static void inotify_dev_event_dequeue(struct inotify_device *dev)
|
|||
}
|
||||
|
||||
/*
|
||||
* find_inode - resolve a user-given path to a specific inode and return a nd
|
||||
* find_inode - resolve a user-given path to a specific inode
|
||||
*/
|
||||
static int find_inode(const char __user *dirname, struct nameidata *nd,
|
||||
static int find_inode(const char __user *dirname, struct path *path,
|
||||
unsigned flags)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = __user_walk(dirname, flags, nd);
|
||||
error = user_path_at(AT_FDCWD, dirname, flags, path);
|
||||
if (error)
|
||||
return error;
|
||||
/* you can only watch an inode if you have read permissions on it */
|
||||
error = inode_permission(nd->path.dentry->d_inode, MAY_READ);
|
||||
error = inode_permission(path->dentry->d_inode, MAY_READ);
|
||||
if (error)
|
||||
path_put(&nd->path);
|
||||
path_put(path);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -650,11 +650,11 @@ asmlinkage long sys_inotify_init(void)
|
|||
return sys_inotify_init1(0);
|
||||
}
|
||||
|
||||
asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
|
||||
asmlinkage long sys_inotify_add_watch(int fd, const char __user *pathname, u32 mask)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct inotify_device *dev;
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
struct file *filp;
|
||||
int ret, fput_needed;
|
||||
unsigned flags = 0;
|
||||
|
@ -674,12 +674,12 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
|
|||
if (mask & IN_ONLYDIR)
|
||||
flags |= LOOKUP_DIRECTORY;
|
||||
|
||||
ret = find_inode(path, &nd, flags);
|
||||
ret = find_inode(pathname, &path, flags);
|
||||
if (unlikely(ret))
|
||||
goto fput_and_out;
|
||||
|
||||
/* inode held in place by reference to nd; dev by fget on fd */
|
||||
inode = nd.path.dentry->d_inode;
|
||||
/* inode held in place by reference to path; dev by fget on fd */
|
||||
inode = path.dentry->d_inode;
|
||||
dev = filp->private_data;
|
||||
|
||||
mutex_lock(&dev->up_mutex);
|
||||
|
@ -688,7 +688,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
|
|||
ret = create_watch(dev, inode, mask);
|
||||
mutex_unlock(&dev->up_mutex);
|
||||
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
fput_and_out:
|
||||
fput_light(filp, fput_needed);
|
||||
return ret;
|
||||
|
|
36
fs/namei.c
36
fs/namei.c
|
@ -1334,24 +1334,24 @@ struct dentry *lookup_one_noperm(const char *name, struct dentry *base)
|
|||
return __lookup_hash(&this, base, NULL);
|
||||
}
|
||||
|
||||
int __user_walk_fd(int dfd, const char __user *name, unsigned flags,
|
||||
struct nameidata *nd)
|
||||
int user_path_at(int dfd, const char __user *name, unsigned flags,
|
||||
struct path *path)
|
||||
{
|
||||
struct nameidata nd;
|
||||
char *tmp = getname(name);
|
||||
int err = PTR_ERR(tmp);
|
||||
|
||||
if (!IS_ERR(tmp)) {
|
||||
err = do_path_lookup(dfd, tmp, flags, nd);
|
||||
|
||||
BUG_ON(flags & LOOKUP_PARENT);
|
||||
|
||||
err = do_path_lookup(dfd, tmp, flags, &nd);
|
||||
putname(tmp);
|
||||
if (!err)
|
||||
*path = nd.path;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int __user_walk(const char __user *name, unsigned flags, struct nameidata *nd)
|
||||
{
|
||||
return __user_walk_fd(AT_FDCWD, name, flags, nd);
|
||||
}
|
||||
|
||||
/*
|
||||
* It's inline, so penalty for filesystems that don't use sticky bit is
|
||||
* minimal.
|
||||
|
@ -2446,7 +2446,8 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
|
|||
int flags)
|
||||
{
|
||||
struct dentry *new_dentry;
|
||||
struct nameidata nd, old_nd;
|
||||
struct nameidata nd;
|
||||
struct path old_path;
|
||||
int error;
|
||||
char * to;
|
||||
|
||||
|
@ -2457,16 +2458,16 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
|
|||
if (IS_ERR(to))
|
||||
return PTR_ERR(to);
|
||||
|
||||
error = __user_walk_fd(olddfd, oldname,
|
||||
flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0,
|
||||
&old_nd);
|
||||
error = user_path_at(olddfd, oldname,
|
||||
flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0,
|
||||
&old_path);
|
||||
if (error)
|
||||
goto exit;
|
||||
error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
|
||||
if (error)
|
||||
goto out;
|
||||
error = -EXDEV;
|
||||
if (old_nd.path.mnt != nd.path.mnt)
|
||||
if (old_path.mnt != nd.path.mnt)
|
||||
goto out_release;
|
||||
new_dentry = lookup_create(&nd, 0);
|
||||
error = PTR_ERR(new_dentry);
|
||||
|
@ -2475,7 +2476,7 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
|
|||
error = mnt_want_write(nd.path.mnt);
|
||||
if (error)
|
||||
goto out_dput;
|
||||
error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry);
|
||||
error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
out_dput:
|
||||
dput(new_dentry);
|
||||
|
@ -2484,7 +2485,7 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
|
|||
out_release:
|
||||
path_put(&nd.path);
|
||||
out:
|
||||
path_put(&old_nd.path);
|
||||
path_put(&old_path);
|
||||
exit:
|
||||
putname(to);
|
||||
|
||||
|
@ -2877,8 +2878,7 @@ const struct inode_operations page_symlink_inode_operations = {
|
|||
.put_link = page_put_link,
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL(__user_walk);
|
||||
EXPORT_SYMBOL(__user_walk_fd);
|
||||
EXPORT_SYMBOL(user_path_at);
|
||||
EXPORT_SYMBOL(follow_down);
|
||||
EXPORT_SYMBOL(follow_up);
|
||||
EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
|
||||
|
|
|
@ -1130,27 +1130,27 @@ static int do_umount(struct vfsmount *mnt, int flags)
|
|||
|
||||
asmlinkage long sys_umount(char __user * name, int flags)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int retval;
|
||||
|
||||
retval = __user_walk(name, LOOKUP_FOLLOW, &nd);
|
||||
retval = user_path(name, &path);
|
||||
if (retval)
|
||||
goto out;
|
||||
retval = -EINVAL;
|
||||
if (nd.path.dentry != nd.path.mnt->mnt_root)
|
||||
if (path.dentry != path.mnt->mnt_root)
|
||||
goto dput_and_out;
|
||||
if (!check_mnt(nd.path.mnt))
|
||||
if (!check_mnt(path.mnt))
|
||||
goto dput_and_out;
|
||||
|
||||
retval = -EPERM;
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
goto dput_and_out;
|
||||
|
||||
retval = do_umount(nd.path.mnt, flags);
|
||||
retval = do_umount(path.mnt, flags);
|
||||
dput_and_out:
|
||||
/* we mustn't call path_put() as that would clear mnt_expiry_mark */
|
||||
dput(nd.path.dentry);
|
||||
mntput_no_expire(nd.path.mnt);
|
||||
dput(path.dentry);
|
||||
mntput_no_expire(path.mnt);
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
@ -2179,28 +2179,26 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
|
|||
const char __user * put_old)
|
||||
{
|
||||
struct vfsmount *tmp;
|
||||
struct nameidata new_nd, old_nd;
|
||||
struct path parent_path, root_parent, root;
|
||||
struct path new, old, parent_path, root_parent, root;
|
||||
int error;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
|
||||
&new_nd);
|
||||
error = user_path_dir(new_root, &new);
|
||||
if (error)
|
||||
goto out0;
|
||||
error = -EINVAL;
|
||||
if (!check_mnt(new_nd.path.mnt))
|
||||
if (!check_mnt(new.mnt))
|
||||
goto out1;
|
||||
|
||||
error = __user_walk(put_old, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &old_nd);
|
||||
error = user_path_dir(put_old, &old);
|
||||
if (error)
|
||||
goto out1;
|
||||
|
||||
error = security_sb_pivotroot(&old_nd.path, &new_nd.path);
|
||||
error = security_sb_pivotroot(&old, &new);
|
||||
if (error) {
|
||||
path_put(&old_nd.path);
|
||||
path_put(&old);
|
||||
goto out1;
|
||||
}
|
||||
|
||||
|
@ -2209,69 +2207,69 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
|
|||
path_get(¤t->fs->root);
|
||||
read_unlock(¤t->fs->lock);
|
||||
down_write(&namespace_sem);
|
||||
mutex_lock(&old_nd.path.dentry->d_inode->i_mutex);
|
||||
mutex_lock(&old.dentry->d_inode->i_mutex);
|
||||
error = -EINVAL;
|
||||
if (IS_MNT_SHARED(old_nd.path.mnt) ||
|
||||
IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) ||
|
||||
if (IS_MNT_SHARED(old.mnt) ||
|
||||
IS_MNT_SHARED(new.mnt->mnt_parent) ||
|
||||
IS_MNT_SHARED(root.mnt->mnt_parent))
|
||||
goto out2;
|
||||
if (!check_mnt(root.mnt))
|
||||
goto out2;
|
||||
error = -ENOENT;
|
||||
if (IS_DEADDIR(new_nd.path.dentry->d_inode))
|
||||
if (IS_DEADDIR(new.dentry->d_inode))
|
||||
goto out2;
|
||||
if (d_unhashed(new_nd.path.dentry) && !IS_ROOT(new_nd.path.dentry))
|
||||
if (d_unhashed(new.dentry) && !IS_ROOT(new.dentry))
|
||||
goto out2;
|
||||
if (d_unhashed(old_nd.path.dentry) && !IS_ROOT(old_nd.path.dentry))
|
||||
if (d_unhashed(old.dentry) && !IS_ROOT(old.dentry))
|
||||
goto out2;
|
||||
error = -EBUSY;
|
||||
if (new_nd.path.mnt == root.mnt ||
|
||||
old_nd.path.mnt == root.mnt)
|
||||
if (new.mnt == root.mnt ||
|
||||
old.mnt == root.mnt)
|
||||
goto out2; /* loop, on the same file system */
|
||||
error = -EINVAL;
|
||||
if (root.mnt->mnt_root != root.dentry)
|
||||
goto out2; /* not a mountpoint */
|
||||
if (root.mnt->mnt_parent == root.mnt)
|
||||
goto out2; /* not attached */
|
||||
if (new_nd.path.mnt->mnt_root != new_nd.path.dentry)
|
||||
if (new.mnt->mnt_root != new.dentry)
|
||||
goto out2; /* not a mountpoint */
|
||||
if (new_nd.path.mnt->mnt_parent == new_nd.path.mnt)
|
||||
if (new.mnt->mnt_parent == new.mnt)
|
||||
goto out2; /* not attached */
|
||||
/* make sure we can reach put_old from new_root */
|
||||
tmp = old_nd.path.mnt;
|
||||
tmp = old.mnt;
|
||||
spin_lock(&vfsmount_lock);
|
||||
if (tmp != new_nd.path.mnt) {
|
||||
if (tmp != new.mnt) {
|
||||
for (;;) {
|
||||
if (tmp->mnt_parent == tmp)
|
||||
goto out3; /* already mounted on put_old */
|
||||
if (tmp->mnt_parent == new_nd.path.mnt)
|
||||
if (tmp->mnt_parent == new.mnt)
|
||||
break;
|
||||
tmp = tmp->mnt_parent;
|
||||
}
|
||||
if (!is_subdir(tmp->mnt_mountpoint, new_nd.path.dentry))
|
||||
if (!is_subdir(tmp->mnt_mountpoint, new.dentry))
|
||||
goto out3;
|
||||
} else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry))
|
||||
} else if (!is_subdir(old.dentry, new.dentry))
|
||||
goto out3;
|
||||
detach_mnt(new_nd.path.mnt, &parent_path);
|
||||
detach_mnt(new.mnt, &parent_path);
|
||||
detach_mnt(root.mnt, &root_parent);
|
||||
/* mount old root on put_old */
|
||||
attach_mnt(root.mnt, &old_nd.path);
|
||||
attach_mnt(root.mnt, &old);
|
||||
/* mount new_root on / */
|
||||
attach_mnt(new_nd.path.mnt, &root_parent);
|
||||
attach_mnt(new.mnt, &root_parent);
|
||||
touch_mnt_namespace(current->nsproxy->mnt_ns);
|
||||
spin_unlock(&vfsmount_lock);
|
||||
chroot_fs_refs(&root, &new_nd.path);
|
||||
security_sb_post_pivotroot(&root, &new_nd.path);
|
||||
chroot_fs_refs(&root, &new);
|
||||
security_sb_post_pivotroot(&root, &new);
|
||||
error = 0;
|
||||
path_put(&root_parent);
|
||||
path_put(&parent_path);
|
||||
out2:
|
||||
mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex);
|
||||
mutex_unlock(&old.dentry->d_inode->i_mutex);
|
||||
up_write(&namespace_sem);
|
||||
path_put(&root);
|
||||
path_put(&old_nd.path);
|
||||
path_put(&old);
|
||||
out1:
|
||||
path_put(&new_nd.path);
|
||||
path_put(&new);
|
||||
out0:
|
||||
return error;
|
||||
out3:
|
||||
|
|
124
fs/open.c
124
fs/open.c
|
@ -122,37 +122,37 @@ static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
asmlinkage long sys_statfs(const char __user * path, struct statfs __user * buf)
|
||||
asmlinkage long sys_statfs(const char __user *pathname, struct statfs __user * buf)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
error = user_path_walk(path, &nd);
|
||||
error = user_path(pathname, &path);
|
||||
if (!error) {
|
||||
struct statfs tmp;
|
||||
error = vfs_statfs_native(nd.path.dentry, &tmp);
|
||||
error = vfs_statfs_native(path.dentry, &tmp);
|
||||
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
|
||||
error = -EFAULT;
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
asmlinkage long sys_statfs64(const char __user *path, size_t sz, struct statfs64 __user *buf)
|
||||
asmlinkage long sys_statfs64(const char __user *pathname, size_t sz, struct statfs64 __user *buf)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
long error;
|
||||
|
||||
if (sz != sizeof(*buf))
|
||||
return -EINVAL;
|
||||
error = user_path_walk(path, &nd);
|
||||
error = user_path(pathname, &path);
|
||||
if (!error) {
|
||||
struct statfs64 tmp;
|
||||
error = vfs_statfs64(nd.path.dentry, &tmp);
|
||||
error = vfs_statfs64(path.dentry, &tmp);
|
||||
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
|
||||
error = -EFAULT;
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
@ -223,20 +223,20 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
|
|||
return err;
|
||||
}
|
||||
|
||||
static long do_sys_truncate(const char __user * path, loff_t length)
|
||||
static long do_sys_truncate(const char __user *pathname, loff_t length)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct inode * inode;
|
||||
struct path path;
|
||||
struct inode *inode;
|
||||
int error;
|
||||
|
||||
error = -EINVAL;
|
||||
if (length < 0) /* sorry, but loff_t says... */
|
||||
goto out;
|
||||
|
||||
error = user_path_walk(path, &nd);
|
||||
error = user_path(pathname, &path);
|
||||
if (error)
|
||||
goto out;
|
||||
inode = nd.path.dentry->d_inode;
|
||||
inode = path.dentry->d_inode;
|
||||
|
||||
/* For directories it's -EISDIR, for other non-regulars - -EINVAL */
|
||||
error = -EISDIR;
|
||||
|
@ -247,7 +247,7 @@ static long do_sys_truncate(const char __user * path, loff_t length)
|
|||
if (!S_ISREG(inode->i_mode))
|
||||
goto dput_and_out;
|
||||
|
||||
error = mnt_want_write(nd.path.mnt);
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (error)
|
||||
goto dput_and_out;
|
||||
|
||||
|
@ -274,15 +274,15 @@ static long do_sys_truncate(const char __user * path, loff_t length)
|
|||
error = locks_verify_truncate(inode, NULL, length);
|
||||
if (!error) {
|
||||
DQUOT_INIT(inode);
|
||||
error = do_truncate(nd.path.dentry, length, 0, NULL);
|
||||
error = do_truncate(path.dentry, length, 0, NULL);
|
||||
}
|
||||
|
||||
put_write_and_out:
|
||||
put_write_access(inode);
|
||||
mnt_drop_write_and_out:
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
mnt_drop_write(path.mnt);
|
||||
dput_and_out:
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
@ -425,7 +425,7 @@ asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len)
|
|||
*/
|
||||
asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
struct inode *inode;
|
||||
int old_fsuid, old_fsgid;
|
||||
kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */
|
||||
|
@ -449,7 +449,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
|
|||
* FIXME: There is a race here against sys_capset. The
|
||||
* capabilities can change yet we will restore the old
|
||||
* value below. We should hold task_capabilities_lock,
|
||||
* but we cannot because user_path_walk can sleep.
|
||||
* but we cannot because user_path_at can sleep.
|
||||
*/
|
||||
#endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */
|
||||
if (current->uid)
|
||||
|
@ -458,11 +458,11 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
|
|||
old_cap = cap_set_effective(current->cap_permitted);
|
||||
}
|
||||
|
||||
res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
|
||||
res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
|
||||
if (res)
|
||||
goto out;
|
||||
|
||||
inode = nd.path.dentry->d_inode;
|
||||
inode = path.dentry->d_inode;
|
||||
|
||||
if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) {
|
||||
/*
|
||||
|
@ -470,7 +470,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
|
|||
* with the "noexec" flag.
|
||||
*/
|
||||
res = -EACCES;
|
||||
if (nd.path.mnt->mnt_flags & MNT_NOEXEC)
|
||||
if (path.mnt->mnt_flags & MNT_NOEXEC)
|
||||
goto out_path_release;
|
||||
}
|
||||
|
||||
|
@ -488,11 +488,11 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
|
|||
* inherently racy and know that the fs may change
|
||||
* state before we even see this result.
|
||||
*/
|
||||
if (__mnt_is_readonly(nd.path.mnt))
|
||||
if (__mnt_is_readonly(path.mnt))
|
||||
res = -EROFS;
|
||||
|
||||
out_path_release:
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
out:
|
||||
current->fsuid = old_fsuid;
|
||||
current->fsgid = old_fsgid;
|
||||
|
@ -510,21 +510,21 @@ asmlinkage long sys_access(const char __user *filename, int mode)
|
|||
|
||||
asmlinkage long sys_chdir(const char __user * filename)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
|
||||
error = user_path_dir(filename, &path);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
error = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
|
||||
error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
|
||||
if (error)
|
||||
goto dput_and_out;
|
||||
|
||||
set_fs_pwd(current->fs, &nd.path);
|
||||
set_fs_pwd(current->fs, &path);
|
||||
|
||||
dput_and_out:
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
@ -557,14 +557,14 @@ asmlinkage long sys_fchdir(unsigned int fd)
|
|||
|
||||
asmlinkage long sys_chroot(const char __user * filename)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd);
|
||||
error = user_path_dir(filename, &path);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
error = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
|
||||
error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
|
||||
if (error)
|
||||
goto dput_and_out;
|
||||
|
||||
|
@ -572,10 +572,10 @@ asmlinkage long sys_chroot(const char __user * filename)
|
|||
if (!capable(CAP_SYS_CHROOT))
|
||||
goto dput_and_out;
|
||||
|
||||
set_fs_root(current->fs, &nd.path);
|
||||
set_fs_root(current->fs, &path);
|
||||
error = 0;
|
||||
dput_and_out:
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
@ -617,17 +617,17 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
|
|||
asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
|
||||
mode_t mode)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct inode * inode;
|
||||
struct path path;
|
||||
struct inode *inode;
|
||||
int error;
|
||||
struct iattr newattrs;
|
||||
|
||||
error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
|
||||
error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
|
||||
if (error)
|
||||
goto out;
|
||||
inode = nd.path.dentry->d_inode;
|
||||
inode = path.dentry->d_inode;
|
||||
|
||||
error = mnt_want_write(nd.path.mnt);
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (error)
|
||||
goto dput_and_out;
|
||||
mutex_lock(&inode->i_mutex);
|
||||
|
@ -635,11 +635,11 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
|
|||
mode = inode->i_mode;
|
||||
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
|
||||
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
|
||||
error = notify_change(nd.path.dentry, &newattrs);
|
||||
error = notify_change(path.dentry, &newattrs);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
mnt_drop_write(path.mnt);
|
||||
dput_and_out:
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
@ -676,19 +676,19 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
|
|||
|
||||
asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
error = user_path_walk(filename, &nd);
|
||||
error = user_path(filename, &path);
|
||||
if (error)
|
||||
goto out;
|
||||
error = mnt_want_write(nd.path.mnt);
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (error)
|
||||
goto out_release;
|
||||
error = chown_common(nd.path.dentry, user, group);
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
error = chown_common(path.dentry, user, group);
|
||||
mnt_drop_write(path.mnt);
|
||||
out_release:
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
@ -696,7 +696,7 @@ asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
|
|||
asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
|
||||
gid_t group, int flag)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int error = -EINVAL;
|
||||
int follow;
|
||||
|
||||
|
@ -704,35 +704,35 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
|
|||
goto out;
|
||||
|
||||
follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
|
||||
error = __user_walk_fd(dfd, filename, follow, &nd);
|
||||
error = user_path_at(dfd, filename, follow, &path);
|
||||
if (error)
|
||||
goto out;
|
||||
error = mnt_want_write(nd.path.mnt);
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (error)
|
||||
goto out_release;
|
||||
error = chown_common(nd.path.dentry, user, group);
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
error = chown_common(path.dentry, user, group);
|
||||
mnt_drop_write(path.mnt);
|
||||
out_release:
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
error = user_path_walk_link(filename, &nd);
|
||||
error = user_lpath(filename, &path);
|
||||
if (error)
|
||||
goto out;
|
||||
error = mnt_want_write(nd.path.mnt);
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (error)
|
||||
goto out_release;
|
||||
error = chown_common(nd.path.dentry, user, group);
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
error = chown_common(path.dentry, user, group);
|
||||
mnt_drop_write(path.mnt);
|
||||
out_release:
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
|
32
fs/stat.c
32
fs/stat.c
|
@ -57,13 +57,13 @@ EXPORT_SYMBOL(vfs_getattr);
|
|||
|
||||
int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
|
||||
error = user_path_at(dfd, name, LOOKUP_FOLLOW, &path);
|
||||
if (!error) {
|
||||
error = vfs_getattr(nd.path.mnt, nd.path.dentry, stat);
|
||||
path_put(&nd.path);
|
||||
error = vfs_getattr(path.mnt, path.dentry, stat);
|
||||
path_put(&path);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
@ -77,13 +77,13 @@ EXPORT_SYMBOL(vfs_stat);
|
|||
|
||||
int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
error = __user_walk_fd(dfd, name, 0, &nd);
|
||||
error = user_path_at(dfd, name, 0, &path);
|
||||
if (!error) {
|
||||
error = vfs_getattr(nd.path.mnt, nd.path.dentry, stat);
|
||||
path_put(&nd.path);
|
||||
error = vfs_getattr(path.mnt, path.dentry, stat);
|
||||
path_put(&path);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
@ -291,29 +291,29 @@ asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf)
|
|||
return error;
|
||||
}
|
||||
|
||||
asmlinkage long sys_readlinkat(int dfd, const char __user *path,
|
||||
asmlinkage long sys_readlinkat(int dfd, const char __user *pathname,
|
||||
char __user *buf, int bufsiz)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
if (bufsiz <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
error = __user_walk_fd(dfd, path, 0, &nd);
|
||||
error = user_path_at(dfd, pathname, 0, &path);
|
||||
if (!error) {
|
||||
struct inode *inode = nd.path.dentry->d_inode;
|
||||
struct inode *inode = path.dentry->d_inode;
|
||||
|
||||
error = -EINVAL;
|
||||
if (inode->i_op && inode->i_op->readlink) {
|
||||
error = security_inode_readlink(nd.path.dentry);
|
||||
error = security_inode_readlink(path.dentry);
|
||||
if (!error) {
|
||||
touch_atime(nd.path.mnt, nd.path.dentry);
|
||||
error = inode->i_op->readlink(nd.path.dentry,
|
||||
touch_atime(path.mnt, path.dentry);
|
||||
error = inode->i_op->readlink(path.dentry,
|
||||
buf, bufsiz);
|
||||
}
|
||||
}
|
||||
path_put(&nd.path);
|
||||
path_put(&path);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -152,18 +152,18 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
|
|||
error = utimes_common(&file->f_path, times);
|
||||
fput(file);
|
||||
} else {
|
||||
struct nameidata nd;
|
||||
struct path path;
|
||||
int lookup_flags = 0;
|
||||
|
||||
if (!(flags & AT_SYMLINK_NOFOLLOW))
|
||||
lookup_flags |= LOOKUP_FOLLOW;
|
||||
|
||||
error = __user_walk_fd(dfd, filename, lookup_flags, &nd);
|
||||
error = user_path_at(dfd, filename, lookup_flags, &path);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
error = utimes_common(&nd.path, times);
|
||||
path_put(&nd.path);
|
||||
error = utimes_common(&path, times);
|
||||
path_put(&path);
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
96
fs/xattr.c
96
fs/xattr.c
|
@ -252,40 +252,40 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value,
|
|||
}
|
||||
|
||||
asmlinkage long
|
||||
sys_setxattr(const char __user *path, const char __user *name,
|
||||
sys_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(const char __user *path, const char __user *name,
|
||||
sys_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;
|
||||
}
|
||||
|
||||
|
@ -350,32 +350,32 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
|
|||
}
|
||||
|
||||
asmlinkage ssize_t
|
||||
sys_getxattr(const char __user *path, const char __user *name,
|
||||
sys_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(const char __user *path, const char __user *name, void __user *value,
|
||||
sys_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;
|
||||
}
|
||||
|
||||
|
@ -425,30 +425,30 @@ listxattr(struct dentry *d, char __user *list, size_t size)
|
|||
}
|
||||
|
||||
asmlinkage ssize_t
|
||||
sys_listxattr(const char __user *path, char __user *list, size_t size)
|
||||
sys_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(const char __user *path, char __user *list, size_t size)
|
||||
sys_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;
|
||||
}
|
||||
|
||||
|
@ -486,38 +486,38 @@ removexattr(struct dentry *d, const char __user *name)
|
|||
}
|
||||
|
||||
asmlinkage long
|
||||
sys_removexattr(const char __user *path, const char __user *name)
|
||||
sys_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(const char __user *path, const char __user *name)
|
||||
sys_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;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,17 +84,15 @@ xfs_find_handle(
|
|||
switch (cmd) {
|
||||
case XFS_IOC_PATH_TO_FSHANDLE:
|
||||
case XFS_IOC_PATH_TO_HANDLE: {
|
||||
struct nameidata nd;
|
||||
int error;
|
||||
|
||||
error = user_path_walk_link((const char __user *)hreq.path, &nd);
|
||||
struct path path;
|
||||
int error = user_lpath((const char __user *)hreq.path, &path);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
ASSERT(nd.path.dentry);
|
||||
ASSERT(nd.path.dentry->d_inode);
|
||||
inode = igrab(nd.path.dentry->d_inode);
|
||||
path_put(&nd.path);
|
||||
ASSERT(path.dentry);
|
||||
ASSERT(path.dentry->d_inode);
|
||||
inode = igrab(path.dentry->d_inode);
|
||||
path_put(&path);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,12 +54,13 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
|
|||
#define LOOKUP_OPEN (0x0100)
|
||||
#define LOOKUP_CREATE (0x0200)
|
||||
|
||||
extern int __user_walk(const char __user *, unsigned, struct nameidata *);
|
||||
extern int __user_walk_fd(int dfd, const char __user *, unsigned, struct nameidata *);
|
||||
#define user_path_walk(name,nd) \
|
||||
__user_walk_fd(AT_FDCWD, name, LOOKUP_FOLLOW, nd)
|
||||
#define user_path_walk_link(name,nd) \
|
||||
__user_walk_fd(AT_FDCWD, name, 0, nd)
|
||||
extern int user_path_at(int, const char __user *, unsigned, struct path *);
|
||||
|
||||
#define user_path(name, path) user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW, path)
|
||||
#define user_lpath(name, path) user_path_at(AT_FDCWD, name, 0, path)
|
||||
#define user_path_dir(name, path) \
|
||||
user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, path)
|
||||
|
||||
extern int path_lookup(const char *, unsigned, struct nameidata *);
|
||||
extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
|
||||
const char *, unsigned int, struct nameidata *);
|
||||
|
|
Loading…
Reference in New Issue
Block a user