aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2009-12-19 10:10:39 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2009-12-22 12:27:34 -0500
commit482928d59db668b8d82a48717f78986d8cea72e9 (patch)
tree6985c64474172ddfb67c737bc4a49e588c49d055
parent628ff7c1d8d8466a5ad8078bd0206a130f8b8a51 (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.h7
-rw-r--r--fs/namei.c6
-rw-r--r--fs/open.c13
-rw-r--r--include/linux/namei.h2
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 */
87extern int do_remount_sb(struct super_block *, int, void *, int); 87extern int do_remount_sb(struct super_block *, int, void *, int);
88
89/*
90 * open.c
91 */
92struct nameidata;
93extern struct file *nameidata_to_filp(struct nameidata *);
94extern 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));
diff --git a/fs/open.c b/fs/open.c
index ca69241796bd..6daee28f6e8f 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -821,15 +821,14 @@ static inline int __get_file_write_access(struct inode *inode,
821} 821}
822 822
823static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, 823static 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);
936out: 934out:
@@ -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 */
952struct file *nameidata_to_filp(struct nameidata *nd, int flags) 950struct 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}
1002EXPORT_SYMBOL(dentry_open); 1001EXPORT_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
73extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, 73extern 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 *));
75extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
76extern void release_open_intent(struct nameidata *);
77 75
78extern struct dentry *lookup_one_len(const char *, struct dentry *, int); 76extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
79 77