diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2009-12-19 10:10:39 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-12-22 12:27:34 -0500 |
commit | 482928d59db668b8d82a48717f78986d8cea72e9 (patch) | |
tree | 6985c64474172ddfb67c737bc4a49e588c49d055 | |
parent | 628ff7c1d8d8466a5ad8078bd0206a130f8b8a51 (diff) |
Fix f_flags/f_mode in case of lookup_instantiate_filp() from open(pathname, 3)
Just set f_flags when shoving struct file into nameidata; don't
postpone that until __dentry_open(). do_filp_open() has correct
value; lookup_instantiate_filp() doesn't - we lose the difference
between O_RDWR and 3 by that point.
We still set .intent.open.flags, so no fs code needs to be changed.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/internal.h | 7 | ||||
-rw-r--r-- | fs/namei.c | 6 | ||||
-rw-r--r-- | fs/open.c | 13 | ||||
-rw-r--r-- | include/linux/namei.h | 2 |
4 files changed, 17 insertions, 11 deletions
diff --git a/fs/internal.h b/fs/internal.h index f67cd141d9a8..e96a1667d749 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -85,3 +85,10 @@ extern struct file *get_empty_filp(void); | |||
85 | * super.c | 85 | * super.c |
86 | */ | 86 | */ |
87 | extern int do_remount_sb(struct super_block *, int, void *, int); | 87 | extern int do_remount_sb(struct super_block *, int, void *, int); |
88 | |||
89 | /* | ||
90 | * open.c | ||
91 | */ | ||
92 | struct nameidata; | ||
93 | extern struct file *nameidata_to_filp(struct nameidata *); | ||
94 | extern void release_open_intent(struct nameidata *); | ||
diff --git a/fs/namei.c b/fs/namei.c index dad4b80257db..d517f73aa36b 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1640,6 +1640,7 @@ struct file *do_filp_open(int dfd, const char *pathname, | |||
1640 | if (filp == NULL) | 1640 | if (filp == NULL) |
1641 | return ERR_PTR(-ENFILE); | 1641 | return ERR_PTR(-ENFILE); |
1642 | nd.intent.open.file = filp; | 1642 | nd.intent.open.file = filp; |
1643 | filp->f_flags = open_flag; | ||
1643 | nd.intent.open.flags = flag; | 1644 | nd.intent.open.flags = flag; |
1644 | nd.intent.open.create_mode = 0; | 1645 | nd.intent.open.create_mode = 0; |
1645 | error = do_path_lookup(dfd, pathname, | 1646 | error = do_path_lookup(dfd, pathname, |
@@ -1685,6 +1686,7 @@ struct file *do_filp_open(int dfd, const char *pathname, | |||
1685 | if (filp == NULL) | 1686 | if (filp == NULL) |
1686 | goto exit_parent; | 1687 | goto exit_parent; |
1687 | nd.intent.open.file = filp; | 1688 | nd.intent.open.file = filp; |
1689 | filp->f_flags = open_flag; | ||
1688 | nd.intent.open.flags = flag; | 1690 | nd.intent.open.flags = flag; |
1689 | nd.intent.open.create_mode = mode; | 1691 | nd.intent.open.create_mode = mode; |
1690 | dir = nd.path.dentry; | 1692 | dir = nd.path.dentry; |
@@ -1725,7 +1727,7 @@ do_last: | |||
1725 | mnt_drop_write(nd.path.mnt); | 1727 | mnt_drop_write(nd.path.mnt); |
1726 | goto exit; | 1728 | goto exit; |
1727 | } | 1729 | } |
1728 | filp = nameidata_to_filp(&nd, open_flag); | 1730 | filp = nameidata_to_filp(&nd); |
1729 | mnt_drop_write(nd.path.mnt); | 1731 | mnt_drop_write(nd.path.mnt); |
1730 | if (nd.root.mnt) | 1732 | if (nd.root.mnt) |
1731 | path_put(&nd.root); | 1733 | path_put(&nd.root); |
@@ -1789,7 +1791,7 @@ ok: | |||
1789 | mnt_drop_write(nd.path.mnt); | 1791 | mnt_drop_write(nd.path.mnt); |
1790 | goto exit; | 1792 | goto exit; |
1791 | } | 1793 | } |
1792 | filp = nameidata_to_filp(&nd, open_flag); | 1794 | filp = nameidata_to_filp(&nd); |
1793 | if (!IS_ERR(filp)) { | 1795 | if (!IS_ERR(filp)) { |
1794 | error = ima_path_check(&filp->f_path, filp->f_mode & | 1796 | error = ima_path_check(&filp->f_path, filp->f_mode & |
1795 | (MAY_READ | MAY_WRITE | MAY_EXEC)); | 1797 | (MAY_READ | MAY_WRITE | MAY_EXEC)); |
@@ -821,15 +821,14 @@ static inline int __get_file_write_access(struct inode *inode, | |||
821 | } | 821 | } |
822 | 822 | ||
823 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | 823 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, |
824 | int flags, struct file *f, | 824 | struct file *f, |
825 | int (*open)(struct inode *, struct file *), | 825 | int (*open)(struct inode *, struct file *), |
826 | const struct cred *cred) | 826 | const struct cred *cred) |
827 | { | 827 | { |
828 | struct inode *inode; | 828 | struct inode *inode; |
829 | int error; | 829 | int error; |
830 | 830 | ||
831 | f->f_flags = flags; | 831 | f->f_mode = (__force fmode_t)((f->f_flags+1) & O_ACCMODE) | FMODE_LSEEK | |
832 | f->f_mode = (__force fmode_t)((flags+1) & O_ACCMODE) | FMODE_LSEEK | | ||
833 | FMODE_PREAD | FMODE_PWRITE; | 832 | FMODE_PREAD | FMODE_PWRITE; |
834 | inode = dentry->d_inode; | 833 | inode = dentry->d_inode; |
835 | if (f->f_mode & FMODE_WRITE) { | 834 | if (f->f_mode & FMODE_WRITE) { |
@@ -930,7 +929,6 @@ struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry | |||
930 | if (IS_ERR(dentry)) | 929 | if (IS_ERR(dentry)) |
931 | goto out_err; | 930 | goto out_err; |
932 | 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), |
933 | nd->intent.open.flags - 1, | ||
934 | nd->intent.open.file, | 932 | nd->intent.open.file, |
935 | open, cred); | 933 | open, cred); |
936 | out: | 934 | out: |
@@ -949,7 +947,7 @@ EXPORT_SYMBOL_GPL(lookup_instantiate_filp); | |||
949 | * | 947 | * |
950 | * Note that this function destroys the original nameidata | 948 | * Note that this function destroys the original nameidata |
951 | */ | 949 | */ |
952 | struct file *nameidata_to_filp(struct nameidata *nd, int flags) | 950 | struct file *nameidata_to_filp(struct nameidata *nd) |
953 | { | 951 | { |
954 | const struct cred *cred = current_cred(); | 952 | const struct cred *cred = current_cred(); |
955 | struct file *filp; | 953 | struct file *filp; |
@@ -958,7 +956,7 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags) | |||
958 | filp = nd->intent.open.file; | 956 | filp = nd->intent.open.file; |
959 | /* Has the filesystem initialised the file for us? */ | 957 | /* Has the filesystem initialised the file for us? */ |
960 | if (filp->f_path.dentry == NULL) | 958 | if (filp->f_path.dentry == NULL) |
961 | filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp, | 959 | filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp, |
962 | NULL, cred); | 960 | NULL, cred); |
963 | else | 961 | else |
964 | path_put(&nd->path); | 962 | path_put(&nd->path); |
@@ -997,7 +995,8 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, | |||
997 | return ERR_PTR(error); | 995 | return ERR_PTR(error); |
998 | } | 996 | } |
999 | 997 | ||
1000 | return __dentry_open(dentry, mnt, flags, f, NULL, cred); | 998 | f->f_flags = flags; |
999 | return __dentry_open(dentry, mnt, f, NULL, cred); | ||
1001 | } | 1000 | } |
1002 | EXPORT_SYMBOL(dentry_open); | 1001 | EXPORT_SYMBOL(dentry_open); |
1003 | 1002 | ||
diff --git a/include/linux/namei.h b/include/linux/namei.h index 028946750289..05b441d93642 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h | |||
@@ -72,8 +72,6 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *, | |||
72 | 72 | ||
73 | extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, | 73 | extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, |
74 | int (*open)(struct inode *, struct file *)); | 74 | int (*open)(struct inode *, struct file *)); |
75 | extern struct file *nameidata_to_filp(struct nameidata *nd, int flags); | ||
76 | extern void release_open_intent(struct nameidata *); | ||
77 | 75 | ||
78 | extern struct dentry *lookup_one_len(const char *, struct dentry *, int); | 76 | extern struct dentry *lookup_one_len(const char *, struct dentry *, int); |
79 | 77 | ||