Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d8f3038 authored by Al Viro's avatar Al Viro
Browse files

[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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 256984a8
Loading
Loading
Loading
Loading
+5 −5
Original line number Original line Diff line number Diff line
@@ -253,15 +253,15 @@ do_osf_statfs(struct dentry * dentry, struct osf_statfs __user *buffer,
}
}


asmlinkage int
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;
	int retval;


	retval = user_path_walk(path, &nd);
	retval = user_path(pathname, &path);
	if (!retval) {
	if (!retval) {
		retval = do_osf_statfs(nd.path.dentry, buffer, bufsiz);
		retval = do_osf_statfs(path.dentry, buffer, bufsiz);
		path_put(&nd.path);
		path_put(&path);
	}
	}
	return retval;
	return retval;
}
}
+5 −5
Original line number Original line Diff line number Diff line
@@ -210,19 +210,19 @@ static int vfs_statfs_hpux(struct dentry *dentry, struct hpux_statfs *buf)
}
}


/* hpux statfs */
/* hpux statfs */
asmlinkage long hpux_statfs(const char __user *path,
asmlinkage long hpux_statfs(const char __user *pathname,
						struct hpux_statfs __user *buf)
						struct hpux_statfs __user *buf)
{
{
	struct nameidata nd;
	struct path path;
	int error;
	int error;


	error = user_path_walk(path, &nd);
	error = user_path(pathname, &path);
	if (!error) {
	if (!error) {
		struct hpux_statfs tmp;
		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)))
		if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
			error = -EFAULT;
			error = -EFAULT;
		path_put(&nd.path);
		path_put(&path);
	}
	}
	return error;
	return error;
}
}
+7 −7
Original line number Original line Diff line number Diff line
@@ -49,7 +49,7 @@ static int coda_ioctl_permission(struct inode *inode, int mask)
static int coda_pioctl(struct inode * inode, struct file * filp, 
static int coda_pioctl(struct inode * inode, struct file * filp, 
                       unsigned int cmd, unsigned long user_data)
                       unsigned int cmd, unsigned long user_data)
{
{
	struct nameidata nd;
	struct path path;
        int error;
        int error;
	struct PioctlData data;
	struct PioctlData data;
        struct inode *target_inode = NULL;
        struct inode *target_inode = NULL;
@@ -65,20 +65,20 @@ static int coda_pioctl(struct inode * inode, struct file * filp,
         * user memory, and namei takes care of this
         * user memory, and namei takes care of this
         */
         */
        if (data.follow) {
        if (data.follow) {
                error = user_path_walk(data.path, &nd);
                error = user_path(data.path, &path);
	} else {
	} else {
	        error = user_path_walk_link(data.path, &nd);
	        error = user_lpath(data.path, &path);
	}
	}
		
		
	if ( error ) {
	if ( error ) {
		return error;
		return error;
        } else {
        } else {
		target_inode = nd.path.dentry->d_inode;
		target_inode = path.dentry->d_inode;
	}
	}
	
	
	/* return if it is not a Coda inode */
	/* return if it is not a Coda inode */
	if ( target_inode->i_sb != inode->i_sb ) {
	if ( target_inode->i_sb != inode->i_sb ) {
		path_put(&nd.path);
		path_put(&path);
	        return  -EINVAL;
	        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);
	error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data);


	path_put(&nd.path);
	path_put(&path);
        return error;
        return error;
}
}
+10 −10
Original line number Original line Diff line number Diff line
@@ -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
 * The following statfs calls are copies of code from fs/open.c and
 * should be checked against those from time to time
 * 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;
	int error;


	error = user_path_walk(path, &nd);
	error = user_path(pathname, &path);
	if (!error) {
	if (!error) {
		struct kstatfs tmp;
		struct kstatfs tmp;
		error = vfs_statfs(nd.path.dentry, &tmp);
		error = vfs_statfs(path.dentry, &tmp);
		if (!error)
		if (!error)
			error = put_compat_statfs(buf, &tmp);
			error = put_compat_statfs(buf, &tmp);
		path_put(&nd.path);
		path_put(&path);
	}
	}
	return error;
	return error;
}
}
@@ -299,21 +299,21 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat
	return 0;
	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;
	int error;


	if (sz != sizeof(*buf))
	if (sz != sizeof(*buf))
		return -EINVAL;
		return -EINVAL;


	error = user_path_walk(path, &nd);
	error = user_path(pathname, &path);
	if (!error) {
	if (!error) {
		struct kstatfs tmp;
		struct kstatfs tmp;
		error = vfs_statfs(nd.path.dentry, &tmp);
		error = vfs_statfs(path.dentry, &tmp);
		if (!error)
		if (!error)
			error = put_compat_statfs64(buf, &tmp);
			error = put_compat_statfs64(buf, &tmp);
		path_put(&nd.path);
		path_put(&path);
	}
	}
	return error;
	return error;
}
}
+11 −11
Original line number Original line Diff line number Diff line
@@ -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)
		      unsigned flags)
{
{
	int error;
	int error;


	error = __user_walk(dirname, flags, nd);
	error = user_path_at(AT_FDCWD, dirname, flags, path);
	if (error)
	if (error)
		return error;
		return error;
	/* you can only watch an inode if you have read permissions on it */
	/* 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)
	if (error)
		path_put(&nd->path);
		path_put(path);
	return error;
	return error;
}
}


@@ -650,11 +650,11 @@ asmlinkage long sys_inotify_init(void)
	return sys_inotify_init1(0);
	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 inode *inode;
	struct inotify_device *dev;
	struct inotify_device *dev;
	struct nameidata nd;
	struct path path;
	struct file *filp;
	struct file *filp;
	int ret, fput_needed;
	int ret, fput_needed;
	unsigned flags = 0;
	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)
	if (mask & IN_ONLYDIR)
		flags |= LOOKUP_DIRECTORY;
		flags |= LOOKUP_DIRECTORY;


	ret = find_inode(path, &nd, flags);
	ret = find_inode(pathname, &path, flags);
	if (unlikely(ret))
	if (unlikely(ret))
		goto fput_and_out;
		goto fput_and_out;


	/* inode held in place by reference to nd; dev by fget on fd */
	/* inode held in place by reference to path; dev by fget on fd */
	inode = nd.path.dentry->d_inode;
	inode = path.dentry->d_inode;
	dev = filp->private_data;
	dev = filp->private_data;


	mutex_lock(&dev->up_mutex);
	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);
		ret = create_watch(dev, inode, mask);
	mutex_unlock(&dev->up_mutex);
	mutex_unlock(&dev->up_mutex);


	path_put(&nd.path);
	path_put(&path);
fput_and_out:
fput_and_out:
	fput_light(filp, fput_needed);
	fput_light(filp, fput_needed);
	return ret;
	return ret;
Loading