Commit a8104a9f authored by Al Viro's avatar Al Viro

pull mnt_want_write()/mnt_drop_write() into kern_path_create()/done_path_create() resp.

One side effect - attempt to create a cross-device link on a read-only fs fails
with EROFS instead of EXDEV now.  Makes more sense, POSIX allows, etc.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 8e4bfca1
...@@ -2865,10 +2865,11 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path ...@@ -2865,10 +2865,11 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path
mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
dentry = lookup_hash(&nd); dentry = lookup_hash(&nd);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
goto fail; goto unlock;
error = -EEXIST;
if (dentry->d_inode) if (dentry->d_inode)
goto eexist; goto fail;
/* /*
* Special case - lookup gave negative, but... we had foo/bar/ * Special case - lookup gave negative, but... we had foo/bar/
* From the vfs_mknod() POV we just have a negative dentry - * From the vfs_mknod() POV we just have a negative dentry -
...@@ -2876,16 +2877,18 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path ...@@ -2876,16 +2877,18 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path
* been asking for (non-existent) directory. -ENOENT for you. * been asking for (non-existent) directory. -ENOENT for you.
*/ */
if (unlikely(!is_dir && nd.last.name[nd.last.len])) { if (unlikely(!is_dir && nd.last.name[nd.last.len])) {
dput(dentry); error = -ENOENT;
dentry = ERR_PTR(-ENOENT);
goto fail; goto fail;
} }
error = mnt_want_write(nd.path.mnt);
if (error)
goto fail;
*path = nd.path; *path = nd.path;
return dentry; return dentry;
eexist:
dput(dentry);
dentry = ERR_PTR(-EEXIST);
fail: fail:
dput(dentry);
dentry = ERR_PTR(error);
unlock:
mutex_unlock(&nd.path.dentry->d_inode->i_mutex); mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
out: out:
path_put(&nd.path); path_put(&nd.path);
...@@ -2897,6 +2900,7 @@ void done_path_create(struct path *path, struct dentry *dentry) ...@@ -2897,6 +2900,7 @@ void done_path_create(struct path *path, struct dentry *dentry)
{ {
dput(dentry); dput(dentry);
mutex_unlock(&path->dentry->d_inode->i_mutex); mutex_unlock(&path->dentry->d_inode->i_mutex);
mnt_drop_write(path->mnt);
path_put(path); path_put(path);
} }
EXPORT_SYMBOL(done_path_create); EXPORT_SYMBOL(done_path_create);
...@@ -2974,12 +2978,9 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, ...@@ -2974,12 +2978,9 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
if (!IS_POSIXACL(path.dentry->d_inode)) if (!IS_POSIXACL(path.dentry->d_inode))
mode &= ~current_umask(); mode &= ~current_umask();
error = mnt_want_write(path.mnt);
if (error)
goto out_dput;
error = security_path_mknod(&path, dentry, mode, dev); error = security_path_mknod(&path, dentry, mode, dev);
if (error) if (error)
goto out_drop_write; goto out;
switch (mode & S_IFMT) { switch (mode & S_IFMT) {
case 0: case S_IFREG: case 0: case S_IFREG:
error = vfs_create(path.dentry->d_inode,dentry,mode,true); error = vfs_create(path.dentry->d_inode,dentry,mode,true);
...@@ -2992,11 +2993,8 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, ...@@ -2992,11 +2993,8 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
error = vfs_mknod(path.dentry->d_inode,dentry,mode,0); error = vfs_mknod(path.dentry->d_inode,dentry,mode,0);
break; break;
} }
out_drop_write: out:
mnt_drop_write(path.mnt);
out_dput:
done_path_create(&path, dentry); done_path_create(&path, dentry);
return error; return error;
} }
...@@ -3042,16 +3040,9 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode) ...@@ -3042,16 +3040,9 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
if (!IS_POSIXACL(path.dentry->d_inode)) if (!IS_POSIXACL(path.dentry->d_inode))
mode &= ~current_umask(); mode &= ~current_umask();
error = mnt_want_write(path.mnt);
if (error)
goto out_dput;
error = security_path_mkdir(&path, dentry, mode); error = security_path_mkdir(&path, dentry, mode);
if (error) if (!error)
goto out_drop_write; error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
out_drop_write:
mnt_drop_write(path.mnt);
out_dput:
done_path_create(&path, dentry); done_path_create(&path, dentry);
return error; return error;
} }
...@@ -3326,16 +3317,9 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname, ...@@ -3326,16 +3317,9 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
if (IS_ERR(dentry)) if (IS_ERR(dentry))
goto out_putname; goto out_putname;
error = mnt_want_write(path.mnt);
if (error)
goto out_dput;
error = security_path_symlink(&path, dentry, from); error = security_path_symlink(&path, dentry, from);
if (error) if (!error)
goto out_drop_write; error = vfs_symlink(path.dentry->d_inode, dentry, from);
error = vfs_symlink(path.dentry->d_inode, dentry, from);
out_drop_write:
mnt_drop_write(path.mnt);
out_dput:
done_path_create(&path, dentry); done_path_create(&path, dentry);
out_putname: out_putname:
putname(from); putname(from);
...@@ -3436,15 +3420,10 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, ...@@ -3436,15 +3420,10 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
error = -EXDEV; error = -EXDEV;
if (old_path.mnt != new_path.mnt) if (old_path.mnt != new_path.mnt)
goto out_dput; goto out_dput;
error = mnt_want_write(new_path.mnt);
if (error)
goto out_dput;
error = security_path_link(old_path.dentry, &new_path, new_dentry); error = security_path_link(old_path.dentry, &new_path, new_dentry);
if (error) if (error)
goto out_drop_write; goto out_dput;
error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry); error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry);
out_drop_write:
mnt_drop_write(new_path.mnt);
out_dput: out_dput:
done_path_create(&new_path, new_dentry); done_path_create(&new_path, new_dentry);
out: out:
......
...@@ -4466,16 +4466,9 @@ int ocfs2_reflink_ioctl(struct inode *inode, ...@@ -4466,16 +4466,9 @@ int ocfs2_reflink_ioctl(struct inode *inode,
goto out_dput; goto out_dput;
} }
error = mnt_want_write(new_path.mnt);
if (error) {
mlog_errno(error);
goto out_dput;
}
error = ocfs2_vfs_reflink(old_path.dentry, error = ocfs2_vfs_reflink(old_path.dentry,
new_path.dentry->d_inode, new_path.dentry->d_inode,
new_dentry, preserve); new_dentry, preserve);
mnt_drop_write(new_path.mnt);
out_dput: out_dput:
done_path_create(&new_path, new_dentry); done_path_create(&new_path, new_dentry);
out: out:
......
...@@ -876,15 +876,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ...@@ -876,15 +876,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
*/ */
mode = S_IFSOCK | mode = S_IFSOCK |
(SOCK_INODE(sock)->i_mode & ~current_umask()); (SOCK_INODE(sock)->i_mode & ~current_umask());
err = mnt_want_write(path.mnt);
if (err)
goto out_mknod_dput;
err = security_path_mknod(&path, dentry, mode, 0); err = security_path_mknod(&path, dentry, mode, 0);
if (err) if (err)
goto out_mknod_drop_write; goto out_mknod_drop_write;
err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0); err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
out_mknod_drop_write: out_mknod_drop_write:
mnt_drop_write(path.mnt);
if (err) if (err)
goto out_mknod_dput; goto out_mknod_dput;
mntget(path.mnt); mntget(path.mnt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment