Skip to content

Commit

Permalink
[PATCH] sanitize __user_walk_fd() et.al.
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
Al Viro committed Jul 27, 2008
1 parent 256984a commit 2d8f303
Show file tree
Hide file tree
Showing 13 changed files with 235 additions and 238 deletions.
10 changes: 5 additions & 5 deletions arch/alpha/kernel/osf_sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
10 changes: 5 additions & 5 deletions arch/parisc/hpux/sys_hpux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
14 changes: 7 additions & 7 deletions fs/coda/pioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

Expand All @@ -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 changes: 10 additions & 10 deletions fs/compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down
22 changes: 11 additions & 11 deletions fs/inotify_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand Down
36 changes: 18 additions & 18 deletions fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);

Expand Down Expand Up @@ -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 */
Expand Down
Loading

0 comments on commit 2d8f303

Please sign in to comment.