diff options
| author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2009-11-21 21:49:55 -0500 |
|---|---|---|
| committer | James Morris <jmorris@namei.org> | 2009-11-23 16:49:26 -0500 |
| commit | fe542cf59bf0b31afe72b9e9749c0f6645419fa0 (patch) | |
| tree | fcb1273863e96f4dd8206578f59ccaabceb46415 | |
| parent | 85c3b529f8ad4d65ba86b982ef050212ae7dd976 (diff) | |
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: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Acked-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: James Morris <jmorris@namei.org>
| -rw-r--r-- | fs/open.c | 36 |
1 files changed, 15 insertions, 21 deletions
| @@ -619,17 +619,17 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode) | |||
| 619 | err = mnt_want_write_file(file); | 619 | err = mnt_want_write_file(file); |
| 620 | if (err) | 620 | if (err) |
| 621 | goto out_putf; | 621 | goto out_putf; |
| 622 | mutex_lock(&inode->i_mutex); | ||
| 622 | err = security_path_chmod(dentry, file->f_vfsmnt, mode); | 623 | err = security_path_chmod(dentry, file->f_vfsmnt, mode); |
| 623 | if (err) | 624 | if (err) |
| 624 | goto out_drop_write; | 625 | goto out_unlock; |
| 625 | mutex_lock(&inode->i_mutex); | ||
| 626 | if (mode == (mode_t) -1) | 626 | if (mode == (mode_t) -1) |
| 627 | mode = inode->i_mode; | 627 | mode = inode->i_mode; |
| 628 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); | 628 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
| 629 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 629 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
| 630 | err = notify_change(dentry, &newattrs); | 630 | err = notify_change(dentry, &newattrs); |
| 631 | out_unlock: | ||
| 631 | mutex_unlock(&inode->i_mutex); | 632 | mutex_unlock(&inode->i_mutex); |
| 632 | out_drop_write: | ||
| 633 | mnt_drop_write(file->f_path.mnt); | 633 | mnt_drop_write(file->f_path.mnt); |
| 634 | out_putf: | 634 | out_putf: |
| 635 | fput(file); | 635 | fput(file); |
| @@ -652,17 +652,17 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode) | |||
| 652 | error = mnt_want_write(path.mnt); | 652 | error = mnt_want_write(path.mnt); |
| 653 | if (error) | 653 | if (error) |
| 654 | goto dput_and_out; | 654 | goto dput_and_out; |
| 655 | mutex_lock(&inode->i_mutex); | ||
| 655 | error = security_path_chmod(path.dentry, path.mnt, mode); | 656 | error = security_path_chmod(path.dentry, path.mnt, mode); |
| 656 | if (error) | 657 | if (error) |
| 657 | goto out_drop_write; | 658 | goto out_unlock; |
| 658 | mutex_lock(&inode->i_mutex); | ||
| 659 | if (mode == (mode_t) -1) | 659 | if (mode == (mode_t) -1) |
| 660 | mode = inode->i_mode; | 660 | mode = inode->i_mode; |
| 661 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); | 661 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
| 662 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 662 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
| 663 | error = notify_change(path.dentry, &newattrs); | 663 | error = notify_change(path.dentry, &newattrs); |
| 664 | out_unlock: | ||
| 664 | mutex_unlock(&inode->i_mutex); | 665 | mutex_unlock(&inode->i_mutex); |
| 665 | out_drop_write: | ||
| 666 | mnt_drop_write(path.mnt); | 666 | mnt_drop_write(path.mnt); |
| 667 | dput_and_out: | 667 | dput_and_out: |
| 668 | path_put(&path); | 668 | path_put(&path); |
| @@ -675,9 +675,9 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode) | |||
| 675 | return sys_fchmodat(AT_FDCWD, filename, mode); | 675 | return sys_fchmodat(AT_FDCWD, filename, mode); |
| 676 | } | 676 | } |
| 677 | 677 | ||
| 678 | static int chown_common(struct dentry * dentry, uid_t user, gid_t group) | 678 | static int chown_common(struct path *path, uid_t user, gid_t group) |
| 679 | { | 679 | { |
| 680 | struct inode *inode = dentry->d_inode; | 680 | struct inode *inode = path->dentry->d_inode; |
| 681 | int error; | 681 | int error; |
| 682 | struct iattr newattrs; | 682 | struct iattr newattrs; |
| 683 | 683 | ||
| @@ -694,7 +694,9 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group) | |||
| 694 | newattrs.ia_valid |= | 694 | newattrs.ia_valid |= |
| 695 | ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; | 695 | ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; |
| 696 | mutex_lock(&inode->i_mutex); | 696 | mutex_lock(&inode->i_mutex); |
| 697 | error = notify_change(dentry, &newattrs); | 697 | error = security_path_chown(path, user, group); |
| 698 | if (!error) | ||
| 699 | error = notify_change(path->dentry, &newattrs); | ||
| 698 | mutex_unlock(&inode->i_mutex); | 700 | mutex_unlock(&inode->i_mutex); |
| 699 | 701 | ||
| 700 | return error; | 702 | return error; |
| @@ -711,9 +713,7 @@ SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group) | |||
| 711 | error = mnt_want_write(path.mnt); | 713 | error = mnt_want_write(path.mnt); |
| 712 | if (error) | 714 | if (error) |
| 713 | goto out_release; | 715 | goto out_release; |
| 714 | error = security_path_chown(&path, user, group); | 716 | error = chown_common(&path, user, group); |
| 715 | if (!error) | ||
| 716 | error = chown_common(path.dentry, user, group); | ||
| 717 | mnt_drop_write(path.mnt); | 717 | mnt_drop_write(path.mnt); |
| 718 | out_release: | 718 | out_release: |
| 719 | path_put(&path); | 719 | path_put(&path); |
| @@ -738,9 +738,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, | |||
| 738 | error = mnt_want_write(path.mnt); | 738 | error = mnt_want_write(path.mnt); |
| 739 | if (error) | 739 | if (error) |
| 740 | goto out_release; | 740 | goto out_release; |
| 741 | error = security_path_chown(&path, user, group); | 741 | error = chown_common(&path, user, group); |
| 742 | if (!error) | ||
| 743 | error = chown_common(path.dentry, user, group); | ||
| 744 | mnt_drop_write(path.mnt); | 742 | mnt_drop_write(path.mnt); |
| 745 | out_release: | 743 | out_release: |
| 746 | path_put(&path); | 744 | path_put(&path); |
| @@ -759,9 +757,7 @@ SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group | |||
| 759 | error = mnt_want_write(path.mnt); | 757 | error = mnt_want_write(path.mnt); |
| 760 | if (error) | 758 | if (error) |
| 761 | goto out_release; | 759 | goto out_release; |
| 762 | error = security_path_chown(&path, user, group); | 760 | error = chown_common(&path, user, group); |
| 763 | if (!error) | ||
| 764 | error = chown_common(path.dentry, user, group); | ||
| 765 | mnt_drop_write(path.mnt); | 761 | mnt_drop_write(path.mnt); |
| 766 | out_release: | 762 | out_release: |
| 767 | path_put(&path); | 763 | path_put(&path); |
| @@ -784,9 +780,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) | |||
| 784 | goto out_fput; | 780 | goto out_fput; |
| 785 | dentry = file->f_path.dentry; | 781 | dentry = file->f_path.dentry; |
| 786 | audit_inode(NULL, dentry); | 782 | audit_inode(NULL, dentry); |
| 787 | error = security_path_chown(&file->f_path, user, group); | 783 | error = chown_common(&file->f_path, user, group); |
| 788 | if (!error) | ||
| 789 | error = chown_common(dentry, user, group); | ||
| 790 | mnt_drop_write(file->f_path.mnt); | 784 | mnt_drop_write(file->f_path.mnt); |
| 791 | out_fput: | 785 | out_fput: |
| 792 | fput(file); | 786 | fput(file); |
