aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-06-11 00:23:01 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-06-29 04:57:09 -0400
commitf9652e10c12b43d9bb957269745cf2fa5682fa92 (patch)
treefd358891b9778f7bdd8764163aa2029d01efcf9c /fs
parent50cd2c577668a170750b15f9a88f022f681ce3c7 (diff)
allow build_open_flags() to return an error
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/exec.c10
-rw-r--r--fs/internal.h5
-rw-r--r--fs/namei.c8
-rw-r--r--fs/open.c49
4 files changed, 41 insertions, 31 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 643019585574..0f6c96c57b2f 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -110,13 +110,14 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
110 static const struct open_flags uselib_flags = { 110 static const struct open_flags uselib_flags = {
111 .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 111 .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
112 .acc_mode = MAY_READ | MAY_EXEC | MAY_OPEN, 112 .acc_mode = MAY_READ | MAY_EXEC | MAY_OPEN,
113 .intent = LOOKUP_OPEN 113 .intent = LOOKUP_OPEN,
114 .lookup_flags = LOOKUP_FOLLOW,
114 }; 115 };
115 116
116 if (IS_ERR(tmp)) 117 if (IS_ERR(tmp))
117 goto out; 118 goto out;
118 119
119 file = do_filp_open(AT_FDCWD, tmp, &uselib_flags, LOOKUP_FOLLOW); 120 file = do_filp_open(AT_FDCWD, tmp, &uselib_flags);
120 putname(tmp); 121 putname(tmp);
121 error = PTR_ERR(file); 122 error = PTR_ERR(file);
122 if (IS_ERR(file)) 123 if (IS_ERR(file))
@@ -756,10 +757,11 @@ struct file *open_exec(const char *name)
756 static const struct open_flags open_exec_flags = { 757 static const struct open_flags open_exec_flags = {
757 .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 758 .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
758 .acc_mode = MAY_EXEC | MAY_OPEN, 759 .acc_mode = MAY_EXEC | MAY_OPEN,
759 .intent = LOOKUP_OPEN 760 .intent = LOOKUP_OPEN,
761 .lookup_flags = LOOKUP_FOLLOW,
760 }; 762 };
761 763
762 file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags, LOOKUP_FOLLOW); 764 file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags);
763 if (IS_ERR(file)) 765 if (IS_ERR(file))
764 goto out; 766 goto out;
765 767
diff --git a/fs/internal.h b/fs/internal.h
index 68121584ae37..f6ad34362823 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -96,11 +96,12 @@ struct open_flags {
96 umode_t mode; 96 umode_t mode;
97 int acc_mode; 97 int acc_mode;
98 int intent; 98 int intent;
99 int lookup_flags;
99}; 100};
100extern struct file *do_filp_open(int dfd, struct filename *pathname, 101extern struct file *do_filp_open(int dfd, struct filename *pathname,
101 const struct open_flags *op, int flags); 102 const struct open_flags *op);
102extern struct file *do_file_open_root(struct dentry *, struct vfsmount *, 103extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
103 const char *, const struct open_flags *, int lookup_flags); 104 const char *, const struct open_flags *);
104 105
105extern long do_handle_open(int mountdirfd, 106extern long do_handle_open(int mountdirfd,
106 struct file_handle __user *ufh, int open_flag); 107 struct file_handle __user *ufh, int open_flag);
diff --git a/fs/namei.c b/fs/namei.c
index 1bc7b7582a66..402eda351d07 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2969,9 +2969,10 @@ out:
2969} 2969}
2970 2970
2971struct file *do_filp_open(int dfd, struct filename *pathname, 2971struct file *do_filp_open(int dfd, struct filename *pathname,
2972 const struct open_flags *op, int flags) 2972 const struct open_flags *op)
2973{ 2973{
2974 struct nameidata nd; 2974 struct nameidata nd;
2975 int flags = op->lookup_flags;
2975 struct file *filp; 2976 struct file *filp;
2976 2977
2977 filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU); 2978 filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU);
@@ -2983,17 +2984,16 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
2983} 2984}
2984 2985
2985struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, 2986struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
2986 const char *name, const struct open_flags *op, int flags) 2987 const char *name, const struct open_flags *op)
2987{ 2988{
2988 struct nameidata nd; 2989 struct nameidata nd;
2989 struct file *file; 2990 struct file *file;
2990 struct filename filename = { .name = name }; 2991 struct filename filename = { .name = name };
2992 int flags = op->lookup_flags | LOOKUP_ROOT;
2991 2993
2992 nd.root.mnt = mnt; 2994 nd.root.mnt = mnt;
2993 nd.root.dentry = dentry; 2995 nd.root.dentry = dentry;
2994 2996
2995 flags |= LOOKUP_ROOT;
2996
2997 if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN) 2997 if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN)
2998 return ERR_PTR(-ELOOP); 2998 return ERR_PTR(-ELOOP);
2999 2999
diff --git a/fs/open.c b/fs/open.c
index 8c741002f947..5a40a4a51757 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -876,7 +876,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
876 lookup_flags |= LOOKUP_DIRECTORY; 876 lookup_flags |= LOOKUP_DIRECTORY;
877 if (!(flags & O_NOFOLLOW)) 877 if (!(flags & O_NOFOLLOW))
878 lookup_flags |= LOOKUP_FOLLOW; 878 lookup_flags |= LOOKUP_FOLLOW;
879 return lookup_flags; 879 op->lookup_flags = lookup_flags;
880 return 0;
880} 881}
881 882
882/** 883/**
@@ -893,8 +894,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
893struct file *file_open_name(struct filename *name, int flags, umode_t mode) 894struct file *file_open_name(struct filename *name, int flags, umode_t mode)
894{ 895{
895 struct open_flags op; 896 struct open_flags op;
896 int lookup = build_open_flags(flags, mode, &op); 897 int err = build_open_flags(flags, mode, &op);
897 return do_filp_open(AT_FDCWD, name, &op, lookup); 898 return err ? ERR_PTR(err) : do_filp_open(AT_FDCWD, name, &op);
898} 899}
899 900
900/** 901/**
@@ -919,37 +920,43 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
919 const char *filename, int flags) 920 const char *filename, int flags)
920{ 921{
921 struct open_flags op; 922 struct open_flags op;
922 int lookup = build_open_flags(flags, 0, &op); 923 int err = build_open_flags(flags, 0, &op);
924 if (err)
925 return ERR_PTR(err);
923 if (flags & O_CREAT) 926 if (flags & O_CREAT)
924 return ERR_PTR(-EINVAL); 927 return ERR_PTR(-EINVAL);
925 if (!filename && (flags & O_DIRECTORY)) 928 if (!filename && (flags & O_DIRECTORY))
926 if (!dentry->d_inode->i_op->lookup) 929 if (!dentry->d_inode->i_op->lookup)
927 return ERR_PTR(-ENOTDIR); 930 return ERR_PTR(-ENOTDIR);
928 return do_file_open_root(dentry, mnt, filename, &op, lookup); 931 return do_file_open_root(dentry, mnt, filename, &op);
929} 932}
930EXPORT_SYMBOL(file_open_root); 933EXPORT_SYMBOL(file_open_root);
931 934
932long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) 935long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
933{ 936{
934 struct open_flags op; 937 struct open_flags op;
935 int lookup = build_open_flags(flags, mode, &op); 938 int fd = build_open_flags(flags, mode, &op);
936 struct filename *tmp = getname(filename); 939 struct filename *tmp;
937 int fd = PTR_ERR(tmp); 940
938 941 if (fd)
939 if (!IS_ERR(tmp)) { 942 return fd;
940 fd = get_unused_fd_flags(flags); 943
941 if (fd >= 0) { 944 tmp = getname(filename);
942 struct file *f = do_filp_open(dfd, tmp, &op, lookup); 945 if (IS_ERR(tmp))
943 if (IS_ERR(f)) { 946 return PTR_ERR(tmp);
944 put_unused_fd(fd); 947
945 fd = PTR_ERR(f); 948 fd = get_unused_fd_flags(flags);
946 } else { 949 if (fd >= 0) {
947 fsnotify_open(f); 950 struct file *f = do_filp_open(dfd, tmp, &op);
948 fd_install(fd, f); 951 if (IS_ERR(f)) {
949 } 952 put_unused_fd(fd);
953 fd = PTR_ERR(f);
954 } else {
955 fsnotify_open(f);
956 fd_install(fd, f);
950 } 957 }
951 putname(tmp);
952 } 958 }
959 putname(tmp);
953 return fd; 960 return fd;
954} 961}
955 962