diff options
Diffstat (limited to 'fs/open.c')
| -rw-r--r-- | fs/open.c | 44 |
1 files changed, 30 insertions, 14 deletions
| @@ -30,6 +30,9 @@ | |||
| 30 | #include <linux/audit.h> | 30 | #include <linux/audit.h> |
| 31 | #include <linux/falloc.h> | 31 | #include <linux/falloc.h> |
| 32 | #include <linux/fs_struct.h> | 32 | #include <linux/fs_struct.h> |
| 33 | #include <linux/ima.h> | ||
| 34 | |||
| 35 | #include "internal.h" | ||
| 33 | 36 | ||
| 34 | int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 37 | int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
| 35 | { | 38 | { |
| @@ -587,6 +590,9 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename) | |||
| 587 | error = -EPERM; | 590 | error = -EPERM; |
| 588 | if (!capable(CAP_SYS_CHROOT)) | 591 | if (!capable(CAP_SYS_CHROOT)) |
| 589 | goto dput_and_out; | 592 | goto dput_and_out; |
| 593 | error = security_path_chroot(&path); | ||
| 594 | if (error) | ||
| 595 | goto dput_and_out; | ||
| 590 | 596 | ||
| 591 | set_fs_root(current->fs, &path); | 597 | set_fs_root(current->fs, &path); |
| 592 | error = 0; | 598 | error = 0; |
| @@ -617,11 +623,15 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode) | |||
| 617 | if (err) | 623 | if (err) |
| 618 | goto out_putf; | 624 | goto out_putf; |
| 619 | mutex_lock(&inode->i_mutex); | 625 | mutex_lock(&inode->i_mutex); |
| 626 | err = security_path_chmod(dentry, file->f_vfsmnt, mode); | ||
| 627 | if (err) | ||
| 628 | goto out_unlock; | ||
| 620 | if (mode == (mode_t) -1) | 629 | if (mode == (mode_t) -1) |
| 621 | mode = inode->i_mode; | 630 | mode = inode->i_mode; |
| 622 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); | 631 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
| 623 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 632 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
| 624 | err = notify_change(dentry, &newattrs); | 633 | err = notify_change(dentry, &newattrs); |
| 634 | out_unlock: | ||
| 625 | mutex_unlock(&inode->i_mutex); | 635 | mutex_unlock(&inode->i_mutex); |
| 626 | mnt_drop_write(file->f_path.mnt); | 636 | mnt_drop_write(file->f_path.mnt); |
| 627 | out_putf: | 637 | out_putf: |
| @@ -646,11 +656,15 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode) | |||
| 646 | if (error) | 656 | if (error) |
| 647 | goto dput_and_out; | 657 | goto dput_and_out; |
| 648 | mutex_lock(&inode->i_mutex); | 658 | mutex_lock(&inode->i_mutex); |
| 659 | error = security_path_chmod(path.dentry, path.mnt, mode); | ||
| 660 | if (error) | ||
| 661 | goto out_unlock; | ||
| 649 | if (mode == (mode_t) -1) | 662 | if (mode == (mode_t) -1) |
| 650 | mode = inode->i_mode; | 663 | mode = inode->i_mode; |
| 651 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); | 664 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
| 652 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 665 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
| 653 | error = notify_change(path.dentry, &newattrs); | 666 | error = notify_change(path.dentry, &newattrs); |
| 667 | out_unlock: | ||
| 654 | mutex_unlock(&inode->i_mutex); | 668 | mutex_unlock(&inode->i_mutex); |
| 655 | mnt_drop_write(path.mnt); | 669 | mnt_drop_write(path.mnt); |
| 656 | dput_and_out: | 670 | dput_and_out: |
| @@ -664,9 +678,9 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode) | |||
| 664 | return sys_fchmodat(AT_FDCWD, filename, mode); | 678 | return sys_fchmodat(AT_FDCWD, filename, mode); |
| 665 | } | 679 | } |
| 666 | 680 | ||
| 667 | static int chown_common(struct dentry * dentry, uid_t user, gid_t group) | 681 | static int chown_common(struct path *path, uid_t user, gid_t group) |
| 668 | { | 682 | { |
| 669 | struct inode *inode = dentry->d_inode; | 683 | struct inode *inode = path->dentry->d_inode; |
| 670 | int error; | 684 | int error; |
| 671 | struct iattr newattrs; | 685 | struct iattr newattrs; |
| 672 | 686 | ||
| @@ -683,7 +697,9 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group) | |||
| 683 | newattrs.ia_valid |= | 697 | newattrs.ia_valid |= |
| 684 | ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; | 698 | ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; |
| 685 | mutex_lock(&inode->i_mutex); | 699 | mutex_lock(&inode->i_mutex); |
| 686 | error = notify_change(dentry, &newattrs); | 700 | error = security_path_chown(path, user, group); |
| 701 | if (!error) | ||
| 702 | error = notify_change(path->dentry, &newattrs); | ||
| 687 | mutex_unlock(&inode->i_mutex); | 703 | mutex_unlock(&inode->i_mutex); |
| 688 | 704 | ||
| 689 | return error; | 705 | return error; |
| @@ -700,7 +716,7 @@ SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group) | |||
| 700 | error = mnt_want_write(path.mnt); | 716 | error = mnt_want_write(path.mnt); |
| 701 | if (error) | 717 | if (error) |
| 702 | goto out_release; | 718 | goto out_release; |
| 703 | error = chown_common(path.dentry, user, group); | 719 | error = chown_common(&path, user, group); |
| 704 | mnt_drop_write(path.mnt); | 720 | mnt_drop_write(path.mnt); |
| 705 | out_release: | 721 | out_release: |
| 706 | path_put(&path); | 722 | path_put(&path); |
| @@ -725,7 +741,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, | |||
| 725 | error = mnt_want_write(path.mnt); | 741 | error = mnt_want_write(path.mnt); |
| 726 | if (error) | 742 | if (error) |
| 727 | goto out_release; | 743 | goto out_release; |
| 728 | error = chown_common(path.dentry, user, group); | 744 | error = chown_common(&path, user, group); |
| 729 | mnt_drop_write(path.mnt); | 745 | mnt_drop_write(path.mnt); |
| 730 | out_release: | 746 | out_release: |
| 731 | path_put(&path); | 747 | path_put(&path); |
| @@ -744,7 +760,7 @@ SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group | |||
| 744 | error = mnt_want_write(path.mnt); | 760 | error = mnt_want_write(path.mnt); |
| 745 | if (error) | 761 | if (error) |
| 746 | goto out_release; | 762 | goto out_release; |
| 747 | error = chown_common(path.dentry, user, group); | 763 | error = chown_common(&path, user, group); |
| 748 | mnt_drop_write(path.mnt); | 764 | mnt_drop_write(path.mnt); |
| 749 | out_release: | 765 | out_release: |
| 750 | path_put(&path); | 766 | path_put(&path); |
| @@ -767,7 +783,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) | |||
| 767 | goto out_fput; | 783 | goto out_fput; |
| 768 | dentry = file->f_path.dentry; | 784 | dentry = file->f_path.dentry; |
| 769 | audit_inode(NULL, dentry); | 785 | audit_inode(NULL, dentry); |
| 770 | error = chown_common(dentry, user, group); | 786 | error = chown_common(&file->f_path, user, group); |
| 771 | mnt_drop_write(file->f_path.mnt); | 787 | mnt_drop_write(file->f_path.mnt); |
| 772 | out_fput: | 788 | out_fput: |
| 773 | fput(file); | 789 | fput(file); |
| @@ -805,15 +821,14 @@ static inline int __get_file_write_access(struct inode *inode, | |||
| 805 | } | 821 | } |
| 806 | 822 | ||
| 807 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | 823 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, |
| 808 | int flags, struct file *f, | 824 | struct file *f, |
| 809 | int (*open)(struct inode *, struct file *), | 825 | int (*open)(struct inode *, struct file *), |
| 810 | const struct cred *cred) | 826 | const struct cred *cred) |
| 811 | { | 827 | { |
| 812 | struct inode *inode; | 828 | struct inode *inode; |
| 813 | int error; | 829 | int error; |
| 814 | 830 | ||
| 815 | f->f_flags = flags; | 831 | f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK | |
| 816 | f->f_mode = (__force fmode_t)((flags+1) & O_ACCMODE) | FMODE_LSEEK | | ||
| 817 | FMODE_PREAD | FMODE_PWRITE; | 832 | FMODE_PREAD | FMODE_PWRITE; |
| 818 | inode = dentry->d_inode; | 833 | inode = dentry->d_inode; |
| 819 | if (f->f_mode & FMODE_WRITE) { | 834 | if (f->f_mode & FMODE_WRITE) { |
| @@ -842,6 +857,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
| 842 | if (error) | 857 | if (error) |
| 843 | goto cleanup_all; | 858 | goto cleanup_all; |
| 844 | } | 859 | } |
| 860 | ima_counts_get(f); | ||
| 845 | 861 | ||
| 846 | f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); | 862 | f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); |
| 847 | 863 | ||
| @@ -913,7 +929,6 @@ struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry | |||
| 913 | if (IS_ERR(dentry)) | 929 | if (IS_ERR(dentry)) |
| 914 | goto out_err; | 930 | goto out_err; |
| 915 | nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt), | 931 | nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt), |
| 916 | nd->intent.open.flags - 1, | ||
| 917 | nd->intent.open.file, | 932 | nd->intent.open.file, |
| 918 | open, cred); | 933 | open, cred); |
| 919 | out: | 934 | out: |
| @@ -932,7 +947,7 @@ EXPORT_SYMBOL_GPL(lookup_instantiate_filp); | |||
| 932 | * | 947 | * |
| 933 | * Note that this function destroys the original nameidata | 948 | * Note that this function destroys the original nameidata |
| 934 | */ | 949 | */ |
| 935 | struct file *nameidata_to_filp(struct nameidata *nd, int flags) | 950 | struct file *nameidata_to_filp(struct nameidata *nd) |
| 936 | { | 951 | { |
| 937 | const struct cred *cred = current_cred(); | 952 | const struct cred *cred = current_cred(); |
| 938 | struct file *filp; | 953 | struct file *filp; |
| @@ -941,7 +956,7 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags) | |||
| 941 | filp = nd->intent.open.file; | 956 | filp = nd->intent.open.file; |
| 942 | /* Has the filesystem initialised the file for us? */ | 957 | /* Has the filesystem initialised the file for us? */ |
| 943 | if (filp->f_path.dentry == NULL) | 958 | if (filp->f_path.dentry == NULL) |
| 944 | filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp, | 959 | filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp, |
| 945 | NULL, cred); | 960 | NULL, cred); |
| 946 | else | 961 | else |
| 947 | path_put(&nd->path); | 962 | path_put(&nd->path); |
| @@ -980,7 +995,8 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, | |||
| 980 | return ERR_PTR(error); | 995 | return ERR_PTR(error); |
| 981 | } | 996 | } |
| 982 | 997 | ||
| 983 | return __dentry_open(dentry, mnt, flags, f, NULL, cred); | 998 | f->f_flags = flags; |
| 999 | return __dentry_open(dentry, mnt, f, NULL, cred); | ||
| 984 | } | 1000 | } |
| 985 | EXPORT_SYMBOL(dentry_open); | 1001 | EXPORT_SYMBOL(dentry_open); |
| 986 | 1002 | ||
