diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /fs/open.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'fs/open.c')
-rw-r--r-- | fs/open.c | 53 |
1 files changed, 33 insertions, 20 deletions
@@ -8,10 +8,8 @@ | |||
8 | #include <linux/mm.h> | 8 | #include <linux/mm.h> |
9 | #include <linux/file.h> | 9 | #include <linux/file.h> |
10 | #include <linux/fdtable.h> | 10 | #include <linux/fdtable.h> |
11 | #include <linux/quotaops.h> | ||
12 | #include <linux/fsnotify.h> | 11 | #include <linux/fsnotify.h> |
13 | #include <linux/module.h> | 12 | #include <linux/module.h> |
14 | #include <linux/slab.h> | ||
15 | #include <linux/tty.h> | 13 | #include <linux/tty.h> |
16 | #include <linux/namei.h> | 14 | #include <linux/namei.h> |
17 | #include <linux/backing-dev.h> | 15 | #include <linux/backing-dev.h> |
@@ -21,6 +19,7 @@ | |||
21 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
22 | #include <linux/vfs.h> | 20 | #include <linux/vfs.h> |
23 | #include <linux/fcntl.h> | 21 | #include <linux/fcntl.h> |
22 | #include <linux/slab.h> | ||
24 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
25 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
26 | #include <linux/personality.h> | 25 | #include <linux/personality.h> |
@@ -30,6 +29,9 @@ | |||
30 | #include <linux/audit.h> | 29 | #include <linux/audit.h> |
31 | #include <linux/falloc.h> | 30 | #include <linux/falloc.h> |
32 | #include <linux/fs_struct.h> | 31 | #include <linux/fs_struct.h> |
32 | #include <linux/ima.h> | ||
33 | |||
34 | #include "internal.h" | ||
33 | 35 | ||
34 | int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 36 | int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
35 | { | 37 | { |
@@ -268,17 +270,15 @@ static long do_sys_truncate(const char __user *pathname, loff_t length) | |||
268 | * Make sure that there are no leases. get_write_access() protects | 270 | * Make sure that there are no leases. get_write_access() protects |
269 | * against the truncate racing with a lease-granting setlease(). | 271 | * against the truncate racing with a lease-granting setlease(). |
270 | */ | 272 | */ |
271 | error = break_lease(inode, FMODE_WRITE); | 273 | error = break_lease(inode, O_WRONLY); |
272 | if (error) | 274 | if (error) |
273 | goto put_write_and_out; | 275 | goto put_write_and_out; |
274 | 276 | ||
275 | error = locks_verify_truncate(inode, NULL, length); | 277 | error = locks_verify_truncate(inode, NULL, length); |
276 | if (!error) | 278 | if (!error) |
277 | error = security_path_truncate(&path, length, 0); | 279 | error = security_path_truncate(&path, length, 0); |
278 | if (!error) { | 280 | if (!error) |
279 | vfs_dq_init(inode); | ||
280 | error = do_truncate(path.dentry, length, 0, NULL); | 281 | error = do_truncate(path.dentry, length, 0, NULL); |
281 | } | ||
282 | 282 | ||
283 | put_write_and_out: | 283 | put_write_and_out: |
284 | put_write_access(inode); | 284 | put_write_access(inode); |
@@ -587,6 +587,9 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename) | |||
587 | error = -EPERM; | 587 | error = -EPERM; |
588 | if (!capable(CAP_SYS_CHROOT)) | 588 | if (!capable(CAP_SYS_CHROOT)) |
589 | goto dput_and_out; | 589 | goto dput_and_out; |
590 | error = security_path_chroot(&path); | ||
591 | if (error) | ||
592 | goto dput_and_out; | ||
590 | 593 | ||
591 | set_fs_root(current->fs, &path); | 594 | set_fs_root(current->fs, &path); |
592 | error = 0; | 595 | error = 0; |
@@ -617,11 +620,15 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode) | |||
617 | if (err) | 620 | if (err) |
618 | goto out_putf; | 621 | goto out_putf; |
619 | mutex_lock(&inode->i_mutex); | 622 | mutex_lock(&inode->i_mutex); |
623 | err = security_path_chmod(dentry, file->f_vfsmnt, mode); | ||
624 | if (err) | ||
625 | goto out_unlock; | ||
620 | if (mode == (mode_t) -1) | 626 | if (mode == (mode_t) -1) |
621 | mode = inode->i_mode; | 627 | mode = inode->i_mode; |
622 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); | 628 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
623 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 629 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
624 | err = notify_change(dentry, &newattrs); | 630 | err = notify_change(dentry, &newattrs); |
631 | out_unlock: | ||
625 | mutex_unlock(&inode->i_mutex); | 632 | mutex_unlock(&inode->i_mutex); |
626 | mnt_drop_write(file->f_path.mnt); | 633 | mnt_drop_write(file->f_path.mnt); |
627 | out_putf: | 634 | out_putf: |
@@ -646,11 +653,15 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode) | |||
646 | if (error) | 653 | if (error) |
647 | goto dput_and_out; | 654 | goto dput_and_out; |
648 | mutex_lock(&inode->i_mutex); | 655 | mutex_lock(&inode->i_mutex); |
656 | error = security_path_chmod(path.dentry, path.mnt, mode); | ||
657 | if (error) | ||
658 | goto out_unlock; | ||
649 | if (mode == (mode_t) -1) | 659 | if (mode == (mode_t) -1) |
650 | mode = inode->i_mode; | 660 | mode = inode->i_mode; |
651 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); | 661 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
652 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 662 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
653 | error = notify_change(path.dentry, &newattrs); | 663 | error = notify_change(path.dentry, &newattrs); |
664 | out_unlock: | ||
654 | mutex_unlock(&inode->i_mutex); | 665 | mutex_unlock(&inode->i_mutex); |
655 | mnt_drop_write(path.mnt); | 666 | mnt_drop_write(path.mnt); |
656 | dput_and_out: | 667 | dput_and_out: |
@@ -664,9 +675,9 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode) | |||
664 | return sys_fchmodat(AT_FDCWD, filename, mode); | 675 | return sys_fchmodat(AT_FDCWD, filename, mode); |
665 | } | 676 | } |
666 | 677 | ||
667 | 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) |
668 | { | 679 | { |
669 | struct inode *inode = dentry->d_inode; | 680 | struct inode *inode = path->dentry->d_inode; |
670 | int error; | 681 | int error; |
671 | struct iattr newattrs; | 682 | struct iattr newattrs; |
672 | 683 | ||
@@ -683,7 +694,9 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group) | |||
683 | newattrs.ia_valid |= | 694 | newattrs.ia_valid |= |
684 | ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; | 695 | ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; |
685 | mutex_lock(&inode->i_mutex); | 696 | mutex_lock(&inode->i_mutex); |
686 | error = notify_change(dentry, &newattrs); | 697 | error = security_path_chown(path, user, group); |
698 | if (!error) | ||
699 | error = notify_change(path->dentry, &newattrs); | ||
687 | mutex_unlock(&inode->i_mutex); | 700 | mutex_unlock(&inode->i_mutex); |
688 | 701 | ||
689 | return error; | 702 | return error; |
@@ -700,7 +713,7 @@ SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group) | |||
700 | error = mnt_want_write(path.mnt); | 713 | error = mnt_want_write(path.mnt); |
701 | if (error) | 714 | if (error) |
702 | goto out_release; | 715 | goto out_release; |
703 | error = chown_common(path.dentry, user, group); | 716 | error = chown_common(&path, user, group); |
704 | mnt_drop_write(path.mnt); | 717 | mnt_drop_write(path.mnt); |
705 | out_release: | 718 | out_release: |
706 | path_put(&path); | 719 | path_put(&path); |
@@ -725,7 +738,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, | |||
725 | error = mnt_want_write(path.mnt); | 738 | error = mnt_want_write(path.mnt); |
726 | if (error) | 739 | if (error) |
727 | goto out_release; | 740 | goto out_release; |
728 | error = chown_common(path.dentry, user, group); | 741 | error = chown_common(&path, user, group); |
729 | mnt_drop_write(path.mnt); | 742 | mnt_drop_write(path.mnt); |
730 | out_release: | 743 | out_release: |
731 | path_put(&path); | 744 | path_put(&path); |
@@ -744,7 +757,7 @@ SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group | |||
744 | error = mnt_want_write(path.mnt); | 757 | error = mnt_want_write(path.mnt); |
745 | if (error) | 758 | if (error) |
746 | goto out_release; | 759 | goto out_release; |
747 | error = chown_common(path.dentry, user, group); | 760 | error = chown_common(&path, user, group); |
748 | mnt_drop_write(path.mnt); | 761 | mnt_drop_write(path.mnt); |
749 | out_release: | 762 | out_release: |
750 | path_put(&path); | 763 | path_put(&path); |
@@ -767,7 +780,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) | |||
767 | goto out_fput; | 780 | goto out_fput; |
768 | dentry = file->f_path.dentry; | 781 | dentry = file->f_path.dentry; |
769 | audit_inode(NULL, dentry); | 782 | audit_inode(NULL, dentry); |
770 | error = chown_common(dentry, user, group); | 783 | error = chown_common(&file->f_path, user, group); |
771 | mnt_drop_write(file->f_path.mnt); | 784 | mnt_drop_write(file->f_path.mnt); |
772 | out_fput: | 785 | out_fput: |
773 | fput(file); | 786 | fput(file); |
@@ -805,15 +818,14 @@ static inline int __get_file_write_access(struct inode *inode, | |||
805 | } | 818 | } |
806 | 819 | ||
807 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | 820 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, |
808 | int flags, struct file *f, | 821 | struct file *f, |
809 | int (*open)(struct inode *, struct file *), | 822 | int (*open)(struct inode *, struct file *), |
810 | const struct cred *cred) | 823 | const struct cred *cred) |
811 | { | 824 | { |
812 | struct inode *inode; | 825 | struct inode *inode; |
813 | int error; | 826 | int error; |
814 | 827 | ||
815 | f->f_flags = flags; | 828 | 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; | 829 | FMODE_PREAD | FMODE_PWRITE; |
818 | inode = dentry->d_inode; | 830 | inode = dentry->d_inode; |
819 | if (f->f_mode & FMODE_WRITE) { | 831 | if (f->f_mode & FMODE_WRITE) { |
@@ -842,6 +854,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
842 | if (error) | 854 | if (error) |
843 | goto cleanup_all; | 855 | goto cleanup_all; |
844 | } | 856 | } |
857 | ima_counts_get(f); | ||
845 | 858 | ||
846 | f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); | 859 | f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); |
847 | 860 | ||
@@ -913,7 +926,6 @@ struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry | |||
913 | if (IS_ERR(dentry)) | 926 | if (IS_ERR(dentry)) |
914 | goto out_err; | 927 | goto out_err; |
915 | nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt), | 928 | nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt), |
916 | nd->intent.open.flags - 1, | ||
917 | nd->intent.open.file, | 929 | nd->intent.open.file, |
918 | open, cred); | 930 | open, cred); |
919 | out: | 931 | out: |
@@ -932,7 +944,7 @@ EXPORT_SYMBOL_GPL(lookup_instantiate_filp); | |||
932 | * | 944 | * |
933 | * Note that this function destroys the original nameidata | 945 | * Note that this function destroys the original nameidata |
934 | */ | 946 | */ |
935 | struct file *nameidata_to_filp(struct nameidata *nd, int flags) | 947 | struct file *nameidata_to_filp(struct nameidata *nd) |
936 | { | 948 | { |
937 | const struct cred *cred = current_cred(); | 949 | const struct cred *cred = current_cred(); |
938 | struct file *filp; | 950 | struct file *filp; |
@@ -941,7 +953,7 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags) | |||
941 | filp = nd->intent.open.file; | 953 | filp = nd->intent.open.file; |
942 | /* Has the filesystem initialised the file for us? */ | 954 | /* Has the filesystem initialised the file for us? */ |
943 | if (filp->f_path.dentry == NULL) | 955 | if (filp->f_path.dentry == NULL) |
944 | filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp, | 956 | filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp, |
945 | NULL, cred); | 957 | NULL, cred); |
946 | else | 958 | else |
947 | path_put(&nd->path); | 959 | path_put(&nd->path); |
@@ -980,7 +992,8 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, | |||
980 | return ERR_PTR(error); | 992 | return ERR_PTR(error); |
981 | } | 993 | } |
982 | 994 | ||
983 | return __dentry_open(dentry, mnt, flags, f, NULL, cred); | 995 | f->f_flags = flags; |
996 | return __dentry_open(dentry, mnt, f, NULL, cred); | ||
984 | } | 997 | } |
985 | EXPORT_SYMBOL(dentry_open); | 998 | EXPORT_SYMBOL(dentry_open); |
986 | 999 | ||