Commit fe542cf5 authored by Tetsuo Handa's avatar Tetsuo Handa Committed by James Morris

LSM: Move security_path_chmod()/security_path_chown() to after mutex_lock().

We should call security_path_chmod()/security_path_chown() after mutex_lock()
in order to avoid races.
Signed-off-by: default avatarTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Acked-by: default avatarJohn Johansen <john.johansen@canonical.com>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent 85c3b529
...@@ -619,17 +619,17 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode) ...@@ -619,17 +619,17 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
err = mnt_want_write_file(file); err = mnt_want_write_file(file);
if (err) if (err)
goto out_putf; goto out_putf;
mutex_lock(&inode->i_mutex);
err = security_path_chmod(dentry, file->f_vfsmnt, mode); err = security_path_chmod(dentry, file->f_vfsmnt, mode);
if (err) if (err)
goto out_drop_write; goto out_unlock;
mutex_lock(&inode->i_mutex);
if (mode == (mode_t) -1) if (mode == (mode_t) -1)
mode = inode->i_mode; mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
err = notify_change(dentry, &newattrs); err = notify_change(dentry, &newattrs);
out_unlock:
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
out_drop_write:
mnt_drop_write(file->f_path.mnt); mnt_drop_write(file->f_path.mnt);
out_putf: out_putf:
fput(file); fput(file);
...@@ -652,17 +652,17 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode) ...@@ -652,17 +652,17 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode)
error = mnt_want_write(path.mnt); error = mnt_want_write(path.mnt);
if (error) if (error)
goto dput_and_out; goto dput_and_out;
mutex_lock(&inode->i_mutex);
error = security_path_chmod(path.dentry, path.mnt, mode); error = security_path_chmod(path.dentry, path.mnt, mode);
if (error) if (error)
goto out_drop_write; goto out_unlock;
mutex_lock(&inode->i_mutex);
if (mode == (mode_t) -1) if (mode == (mode_t) -1)
mode = inode->i_mode; mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
error = notify_change(path.dentry, &newattrs); error = notify_change(path.dentry, &newattrs);
out_unlock:
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
out_drop_write:
mnt_drop_write(path.mnt); mnt_drop_write(path.mnt);
dput_and_out: dput_and_out:
path_put(&path); path_put(&path);
...@@ -675,9 +675,9 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode) ...@@ -675,9 +675,9 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode)
return sys_fchmodat(AT_FDCWD, filename, mode); return sys_fchmodat(AT_FDCWD, filename, mode);
} }
static int chown_common(struct dentry * dentry, uid_t user, gid_t group) static int chown_common(struct path *path, uid_t user, gid_t group)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = path->dentry->d_inode;
int error; int error;
struct iattr newattrs; struct iattr newattrs;
...@@ -694,7 +694,9 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group) ...@@ -694,7 +694,9 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
newattrs.ia_valid |= newattrs.ia_valid |=
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
error = notify_change(dentry, &newattrs); error = security_path_chown(path, user, group);
if (!error)
error = notify_change(path->dentry, &newattrs);
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
return error; return error;
...@@ -711,9 +713,7 @@ SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group) ...@@ -711,9 +713,7 @@ SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
error = mnt_want_write(path.mnt); error = mnt_want_write(path.mnt);
if (error) if (error)
goto out_release; goto out_release;
error = security_path_chown(&path, user, group); error = chown_common(&path, user, group);
if (!error)
error = chown_common(path.dentry, user, group);
mnt_drop_write(path.mnt); mnt_drop_write(path.mnt);
out_release: out_release:
path_put(&path); path_put(&path);
...@@ -738,9 +738,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, ...@@ -738,9 +738,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
error = mnt_want_write(path.mnt); error = mnt_want_write(path.mnt);
if (error) if (error)
goto out_release; goto out_release;
error = security_path_chown(&path, user, group); error = chown_common(&path, user, group);
if (!error)
error = chown_common(path.dentry, user, group);
mnt_drop_write(path.mnt); mnt_drop_write(path.mnt);
out_release: out_release:
path_put(&path); path_put(&path);
...@@ -759,9 +757,7 @@ SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group ...@@ -759,9 +757,7 @@ SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group
error = mnt_want_write(path.mnt); error = mnt_want_write(path.mnt);
if (error) if (error)
goto out_release; goto out_release;
error = security_path_chown(&path, user, group); error = chown_common(&path, user, group);
if (!error)
error = chown_common(path.dentry, user, group);
mnt_drop_write(path.mnt); mnt_drop_write(path.mnt);
out_release: out_release:
path_put(&path); path_put(&path);
...@@ -784,9 +780,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) ...@@ -784,9 +780,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
goto out_fput; goto out_fput;
dentry = file->f_path.dentry; dentry = file->f_path.dentry;
audit_inode(NULL, dentry); audit_inode(NULL, dentry);
error = security_path_chown(&file->f_path, user, group); error = chown_common(&file->f_path, user, group);
if (!error)
error = chown_common(dentry, user, group);
mnt_drop_write(file->f_path.mnt); mnt_drop_write(file->f_path.mnt);
out_fput: out_fput:
fput(file); fput(file);
......
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