Commit f9652e10c12b43d9bb957269745cf2fa5682fa92
1 parent
50cd2c5776
Exists in
master
and in
20 other branches
allow build_open_flags() to return an error
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 4 changed files with 41 additions and 31 deletions Side-by-side Diff
fs/exec.c
... | ... | @@ -110,13 +110,14 @@ |
110 | 110 | static const struct open_flags uselib_flags = { |
111 | 111 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, |
112 | 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 | 117 | if (IS_ERR(tmp)) |
117 | 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 | 121 | putname(tmp); |
121 | 122 | error = PTR_ERR(file); |
122 | 123 | if (IS_ERR(file)) |
123 | 124 | |
... | ... | @@ -756,10 +757,11 @@ |
756 | 757 | static const struct open_flags open_exec_flags = { |
757 | 758 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, |
758 | 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 | 765 | if (IS_ERR(file)) |
764 | 766 | goto out; |
765 | 767 |
fs/internal.h
... | ... | @@ -96,11 +96,12 @@ |
96 | 96 | umode_t mode; |
97 | 97 | int acc_mode; |
98 | 98 | int intent; |
99 | + int lookup_flags; | |
99 | 100 | }; |
100 | 101 | extern struct file *do_filp_open(int dfd, struct filename *pathname, |
101 | - const struct open_flags *op, int flags); | |
102 | + const struct open_flags *op); | |
102 | 103 | extern 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 | |
105 | 106 | extern long do_handle_open(int mountdirfd, |
106 | 107 | struct file_handle __user *ufh, int open_flag); |
fs/namei.c
... | ... | @@ -2969,9 +2969,10 @@ |
2969 | 2969 | } |
2970 | 2970 | |
2971 | 2971 | struct 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 | 2974 | struct nameidata nd; |
2975 | + int flags = op->lookup_flags; | |
2975 | 2976 | struct file *filp; |
2976 | 2977 | |
2977 | 2978 | filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU); |
2978 | 2979 | |
2979 | 2980 | |
... | ... | @@ -2983,16 +2984,15 @@ |
2983 | 2984 | } |
2984 | 2985 | |
2985 | 2986 | struct 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 | 2989 | struct nameidata nd; |
2989 | 2990 | struct file *file; |
2990 | 2991 | struct filename filename = { .name = name }; |
2992 | + int flags = op->lookup_flags | LOOKUP_ROOT; | |
2991 | 2993 | |
2992 | 2994 | nd.root.mnt = mnt; |
2993 | 2995 | nd.root.dentry = dentry; |
2994 | - | |
2995 | - flags |= LOOKUP_ROOT; | |
2996 | 2996 | |
2997 | 2997 | if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN) |
2998 | 2998 | return ERR_PTR(-ELOOP); |
fs/open.c
... | ... | @@ -876,7 +876,8 @@ |
876 | 876 | lookup_flags |= LOOKUP_DIRECTORY; |
877 | 877 | if (!(flags & O_NOFOLLOW)) |
878 | 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 @@ |
893 | 894 | struct file *file_open_name(struct filename *name, int flags, umode_t mode) |
894 | 895 | { |
895 | 896 | struct open_flags op; |
896 | - int lookup = build_open_flags(flags, mode, &op); | |
897 | - return do_filp_open(AT_FDCWD, name, &op, lookup); | |
897 | + int err = build_open_flags(flags, mode, &op); | |
898 | + return err ? ERR_PTR(err) : do_filp_open(AT_FDCWD, name, &op); | |
898 | 899 | } |
899 | 900 | |
900 | 901 | /** |
901 | 902 | |
902 | 903 | |
903 | 904 | |
904 | 905 | |
905 | 906 | |
... | ... | @@ -919,37 +920,43 @@ |
919 | 920 | const char *filename, int flags) |
920 | 921 | { |
921 | 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 | 926 | if (flags & O_CREAT) |
924 | 927 | return ERR_PTR(-EINVAL); |
925 | 928 | if (!filename && (flags & O_DIRECTORY)) |
926 | 929 | if (!dentry->d_inode->i_op->lookup) |
927 | 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 | } |
930 | 933 | EXPORT_SYMBOL(file_open_root); |
931 | 934 | |
932 | 935 | long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) |
933 | 936 | { |
934 | 937 | struct open_flags op; |
935 | - int lookup = build_open_flags(flags, mode, &op); | |
936 | - struct filename *tmp = getname(filename); | |
937 | - int fd = PTR_ERR(tmp); | |
938 | + int fd = build_open_flags(flags, mode, &op); | |
939 | + struct filename *tmp; | |
938 | 940 | |
939 | - if (!IS_ERR(tmp)) { | |
940 | - fd = get_unused_fd_flags(flags); | |
941 | - if (fd >= 0) { | |
942 | - struct file *f = do_filp_open(dfd, tmp, &op, lookup); | |
943 | - if (IS_ERR(f)) { | |
944 | - put_unused_fd(fd); | |
945 | - fd = PTR_ERR(f); | |
946 | - } else { | |
947 | - fsnotify_open(f); | |
948 | - fd_install(fd, f); | |
949 | - } | |
941 | + if (fd) | |
942 | + return fd; | |
943 | + | |
944 | + tmp = getname(filename); | |
945 | + if (IS_ERR(tmp)) | |
946 | + return PTR_ERR(tmp); | |
947 | + | |
948 | + fd = get_unused_fd_flags(flags); | |
949 | + if (fd >= 0) { | |
950 | + struct file *f = do_filp_open(dfd, tmp, &op); | |
951 | + if (IS_ERR(f)) { | |
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 | 960 | return fd; |
954 | 961 | } |
955 | 962 |