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 /fs/open.c | |
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>
Diffstat (limited to 'fs/open.c')
-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); |