diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/exec.c | 18 | ||||
-rw-r--r-- | fs/internal.h | 8 | ||||
-rw-r--r-- | fs/namei.c | 88 | ||||
-rw-r--r-- | fs/open.c | 73 |
4 files changed, 101 insertions, 86 deletions
@@ -115,13 +115,16 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) | |||
115 | struct file *file; | 115 | struct file *file; |
116 | char *tmp = getname(library); | 116 | char *tmp = getname(library); |
117 | int error = PTR_ERR(tmp); | 117 | int error = PTR_ERR(tmp); |
118 | static const struct open_flags uselib_flags = { | ||
119 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, | ||
120 | .acc_mode = MAY_READ | MAY_EXEC | MAY_OPEN, | ||
121 | .intent = LOOKUP_OPEN | ||
122 | }; | ||
118 | 123 | ||
119 | if (IS_ERR(tmp)) | 124 | if (IS_ERR(tmp)) |
120 | goto out; | 125 | goto out; |
121 | 126 | ||
122 | file = do_filp_open(AT_FDCWD, tmp, | 127 | file = do_filp_open(AT_FDCWD, tmp, &uselib_flags, LOOKUP_FOLLOW); |
123 | O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0, | ||
124 | MAY_READ | MAY_EXEC | MAY_OPEN); | ||
125 | putname(tmp); | 128 | putname(tmp); |
126 | error = PTR_ERR(file); | 129 | error = PTR_ERR(file); |
127 | if (IS_ERR(file)) | 130 | if (IS_ERR(file)) |
@@ -721,10 +724,13 @@ struct file *open_exec(const char *name) | |||
721 | { | 724 | { |
722 | struct file *file; | 725 | struct file *file; |
723 | int err; | 726 | int err; |
727 | static const struct open_flags open_exec_flags = { | ||
728 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, | ||
729 | .acc_mode = MAY_EXEC | MAY_OPEN, | ||
730 | .intent = LOOKUP_OPEN | ||
731 | }; | ||
724 | 732 | ||
725 | file = do_filp_open(AT_FDCWD, name, | 733 | file = do_filp_open(AT_FDCWD, name, &open_exec_flags, LOOKUP_FOLLOW); |
726 | O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0, | ||
727 | MAY_EXEC | MAY_OPEN); | ||
728 | if (IS_ERR(file)) | 734 | if (IS_ERR(file)) |
729 | goto out; | 735 | goto out; |
730 | 736 | ||
diff --git a/fs/internal.h b/fs/internal.h index 9b976b57d7fe..6fdbdf2c6047 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -106,6 +106,14 @@ extern void put_super(struct super_block *sb); | |||
106 | struct nameidata; | 106 | struct nameidata; |
107 | extern struct file *nameidata_to_filp(struct nameidata *); | 107 | extern struct file *nameidata_to_filp(struct nameidata *); |
108 | extern void release_open_intent(struct nameidata *); | 108 | extern void release_open_intent(struct nameidata *); |
109 | struct open_flags { | ||
110 | int open_flag; | ||
111 | int mode; | ||
112 | int acc_mode; | ||
113 | int intent; | ||
114 | }; | ||
115 | extern struct file *do_filp_open(int dfd, const char *pathname, | ||
116 | const struct open_flags *op, int lookup_flags); | ||
109 | 117 | ||
110 | /* | 118 | /* |
111 | * inode.c | 119 | * inode.c |
diff --git a/fs/namei.c b/fs/namei.c index 5e4206f45371..9c7fa946abe1 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2169,13 +2169,6 @@ exit: | |||
2169 | return ERR_PTR(error); | 2169 | return ERR_PTR(error); |
2170 | } | 2170 | } |
2171 | 2171 | ||
2172 | struct open_flags { | ||
2173 | int open_flag; | ||
2174 | int mode; | ||
2175 | int acc_mode; | ||
2176 | int intent; | ||
2177 | }; | ||
2178 | |||
2179 | /* | 2172 | /* |
2180 | * Handle O_CREAT case for do_filp_open | 2173 | * Handle O_CREAT case for do_filp_open |
2181 | */ | 2174 | */ |
@@ -2305,74 +2298,28 @@ exit: | |||
2305 | * open_to_namei_flags() for more details. | 2298 | * open_to_namei_flags() for more details. |
2306 | */ | 2299 | */ |
2307 | struct file *do_filp_open(int dfd, const char *pathname, | 2300 | struct file *do_filp_open(int dfd, const char *pathname, |
2308 | int open_flag, int mode, int acc_mode) | 2301 | const struct open_flags *op, int flags) |
2309 | { | 2302 | { |
2310 | struct file *filp; | 2303 | struct file *filp; |
2311 | struct nameidata nd; | 2304 | struct nameidata nd; |
2312 | int error; | 2305 | int error; |
2313 | struct path path; | 2306 | struct path path; |
2314 | int count = 0; | 2307 | int count = 0; |
2315 | int flag = open_to_namei_flags(open_flag); | ||
2316 | int flags = 0; | ||
2317 | struct open_flags op; | ||
2318 | |||
2319 | if (!(open_flag & O_CREAT)) | ||
2320 | mode = 0; | ||
2321 | |||
2322 | /* Must never be set by userspace */ | ||
2323 | open_flag &= ~FMODE_NONOTIFY; | ||
2324 | |||
2325 | /* | ||
2326 | * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only | ||
2327 | * check for O_DSYNC if the need any syncing at all we enforce it's | ||
2328 | * always set instead of having to deal with possibly weird behaviour | ||
2329 | * for malicious applications setting only __O_SYNC. | ||
2330 | */ | ||
2331 | if (open_flag & __O_SYNC) | ||
2332 | open_flag |= O_DSYNC; | ||
2333 | |||
2334 | op.open_flag = open_flag; | ||
2335 | |||
2336 | if (!acc_mode) | ||
2337 | acc_mode = MAY_OPEN | ACC_MODE(open_flag); | ||
2338 | |||
2339 | /* O_TRUNC implies we need access checks for write permissions */ | ||
2340 | if (open_flag & O_TRUNC) | ||
2341 | acc_mode |= MAY_WRITE; | ||
2342 | |||
2343 | /* Allow the LSM permission hook to distinguish append | ||
2344 | access from general write access. */ | ||
2345 | if (open_flag & O_APPEND) | ||
2346 | acc_mode |= MAY_APPEND; | ||
2347 | |||
2348 | op.acc_mode = acc_mode; | ||
2349 | |||
2350 | op.intent = LOOKUP_OPEN; | ||
2351 | if (open_flag & O_CREAT) { | ||
2352 | op.intent |= LOOKUP_CREATE; | ||
2353 | if (open_flag & O_EXCL) | ||
2354 | op.intent |= LOOKUP_EXCL; | ||
2355 | } | ||
2356 | |||
2357 | if (open_flag & O_DIRECTORY) | ||
2358 | flags |= LOOKUP_DIRECTORY; | ||
2359 | if (!(open_flag & O_NOFOLLOW)) | ||
2360 | flags |= LOOKUP_FOLLOW; | ||
2361 | 2308 | ||
2362 | filp = get_empty_filp(); | 2309 | filp = get_empty_filp(); |
2363 | if (!filp) | 2310 | if (!filp) |
2364 | return ERR_PTR(-ENFILE); | 2311 | return ERR_PTR(-ENFILE); |
2365 | 2312 | ||
2366 | filp->f_flags = open_flag; | 2313 | filp->f_flags = op->open_flag; |
2367 | nd.intent.open.file = filp; | 2314 | nd.intent.open.file = filp; |
2368 | nd.intent.open.flags = flag; | 2315 | nd.intent.open.flags = open_to_namei_flags(op->open_flag); |
2369 | nd.intent.open.create_mode = mode; | 2316 | nd.intent.open.create_mode = op->mode; |
2370 | 2317 | ||
2371 | if (open_flag & O_CREAT) | 2318 | if (op->open_flag & O_CREAT) |
2372 | goto creat; | 2319 | goto creat; |
2373 | 2320 | ||
2374 | /* !O_CREAT, simple open */ | 2321 | /* !O_CREAT, simple open */ |
2375 | error = do_path_lookup(dfd, pathname, flags | op.intent, &nd); | 2322 | error = do_path_lookup(dfd, pathname, flags | op->intent, &nd); |
2376 | if (unlikely(error)) | 2323 | if (unlikely(error)) |
2377 | goto out_filp2; | 2324 | goto out_filp2; |
2378 | error = -ELOOP; | 2325 | error = -ELOOP; |
@@ -2386,7 +2333,7 @@ struct file *do_filp_open(int dfd, const char *pathname, | |||
2386 | goto out_path2; | 2333 | goto out_path2; |
2387 | } | 2334 | } |
2388 | audit_inode(pathname, nd.path.dentry); | 2335 | audit_inode(pathname, nd.path.dentry); |
2389 | filp = finish_open(&nd, open_flag, acc_mode); | 2336 | filp = finish_open(&nd, op->open_flag, op->acc_mode); |
2390 | out2: | 2337 | out2: |
2391 | release_open_intent(&nd); | 2338 | release_open_intent(&nd); |
2392 | return filp; | 2339 | return filp; |
@@ -2416,7 +2363,7 @@ reval: | |||
2416 | /* | 2363 | /* |
2417 | * We have the parent and last component. | 2364 | * We have the parent and last component. |
2418 | */ | 2365 | */ |
2419 | filp = do_last(&nd, &path, &op, pathname); | 2366 | filp = do_last(&nd, &path, op, pathname); |
2420 | while (unlikely(!filp)) { /* trailing symlink */ | 2367 | while (unlikely(!filp)) { /* trailing symlink */ |
2421 | struct path link = path; | 2368 | struct path link = path; |
2422 | struct inode *linki = link.dentry->d_inode; | 2369 | struct inode *linki = link.dentry->d_inode; |
@@ -2443,7 +2390,7 @@ reval: | |||
2443 | if (unlikely(error)) | 2390 | if (unlikely(error)) |
2444 | filp = ERR_PTR(error); | 2391 | filp = ERR_PTR(error); |
2445 | else | 2392 | else |
2446 | filp = do_last(&nd, &path, &op, pathname); | 2393 | filp = do_last(&nd, &path, op, pathname); |
2447 | if (!IS_ERR(cookie) && linki->i_op->put_link) | 2394 | if (!IS_ERR(cookie) && linki->i_op->put_link) |
2448 | linki->i_op->put_link(link.dentry, &nd, cookie); | 2395 | linki->i_op->put_link(link.dentry, &nd, cookie); |
2449 | path_put(&link); | 2396 | path_put(&link); |
@@ -2466,23 +2413,6 @@ out_filp: | |||
2466 | } | 2413 | } |
2467 | 2414 | ||
2468 | /** | 2415 | /** |
2469 | * filp_open - open file and return file pointer | ||
2470 | * | ||
2471 | * @filename: path to open | ||
2472 | * @flags: open flags as per the open(2) second argument | ||
2473 | * @mode: mode for the new file if O_CREAT is set, else ignored | ||
2474 | * | ||
2475 | * This is the helper to open a file from kernelspace if you really | ||
2476 | * have to. But in generally you should not do this, so please move | ||
2477 | * along, nothing to see here.. | ||
2478 | */ | ||
2479 | struct file *filp_open(const char *filename, int flags, int mode) | ||
2480 | { | ||
2481 | return do_filp_open(AT_FDCWD, filename, flags, mode, 0); | ||
2482 | } | ||
2483 | EXPORT_SYMBOL(filp_open); | ||
2484 | |||
2485 | /** | ||
2486 | * lookup_create - lookup a dentry, creating it if it doesn't exist | 2416 | * lookup_create - lookup a dentry, creating it if it doesn't exist |
2487 | * @nd: nameidata info | 2417 | * @nd: nameidata info |
2488 | * @is_dir: directory flag | 2418 | * @is_dir: directory flag |
@@ -890,15 +890,86 @@ void fd_install(unsigned int fd, struct file *file) | |||
890 | 890 | ||
891 | EXPORT_SYMBOL(fd_install); | 891 | EXPORT_SYMBOL(fd_install); |
892 | 892 | ||
893 | static inline int build_open_flags(int flags, int mode, struct open_flags *op) | ||
894 | { | ||
895 | int lookup_flags = 0; | ||
896 | int acc_mode; | ||
897 | |||
898 | if (!(flags & O_CREAT)) | ||
899 | mode = 0; | ||
900 | op->mode = mode; | ||
901 | |||
902 | /* Must never be set by userspace */ | ||
903 | flags &= ~FMODE_NONOTIFY; | ||
904 | |||
905 | /* | ||
906 | * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only | ||
907 | * check for O_DSYNC if the need any syncing at all we enforce it's | ||
908 | * always set instead of having to deal with possibly weird behaviour | ||
909 | * for malicious applications setting only __O_SYNC. | ||
910 | */ | ||
911 | if (flags & __O_SYNC) | ||
912 | flags |= O_DSYNC; | ||
913 | |||
914 | op->open_flag = flags; | ||
915 | |||
916 | acc_mode = MAY_OPEN | ACC_MODE(flags); | ||
917 | |||
918 | /* O_TRUNC implies we need access checks for write permissions */ | ||
919 | if (flags & O_TRUNC) | ||
920 | acc_mode |= MAY_WRITE; | ||
921 | |||
922 | /* Allow the LSM permission hook to distinguish append | ||
923 | access from general write access. */ | ||
924 | if (flags & O_APPEND) | ||
925 | acc_mode |= MAY_APPEND; | ||
926 | |||
927 | op->acc_mode = acc_mode; | ||
928 | |||
929 | op->intent = LOOKUP_OPEN; | ||
930 | if (flags & O_CREAT) { | ||
931 | op->intent |= LOOKUP_CREATE; | ||
932 | if (flags & O_EXCL) | ||
933 | op->intent |= LOOKUP_EXCL; | ||
934 | } | ||
935 | |||
936 | if (flags & O_DIRECTORY) | ||
937 | lookup_flags |= LOOKUP_DIRECTORY; | ||
938 | if (!(flags & O_NOFOLLOW)) | ||
939 | lookup_flags |= LOOKUP_FOLLOW; | ||
940 | return lookup_flags; | ||
941 | } | ||
942 | |||
943 | /** | ||
944 | * filp_open - open file and return file pointer | ||
945 | * | ||
946 | * @filename: path to open | ||
947 | * @flags: open flags as per the open(2) second argument | ||
948 | * @mode: mode for the new file if O_CREAT is set, else ignored | ||
949 | * | ||
950 | * This is the helper to open a file from kernelspace if you really | ||
951 | * have to. But in generally you should not do this, so please move | ||
952 | * along, nothing to see here.. | ||
953 | */ | ||
954 | struct file *filp_open(const char *filename, int flags, int mode) | ||
955 | { | ||
956 | struct open_flags op; | ||
957 | int lookup = build_open_flags(flags, mode, &op); | ||
958 | return do_filp_open(AT_FDCWD, filename, &op, lookup); | ||
959 | } | ||
960 | EXPORT_SYMBOL(filp_open); | ||
961 | |||
893 | long do_sys_open(int dfd, const char __user *filename, int flags, int mode) | 962 | long do_sys_open(int dfd, const char __user *filename, int flags, int mode) |
894 | { | 963 | { |
964 | struct open_flags op; | ||
965 | int lookup = build_open_flags(flags, mode, &op); | ||
895 | char *tmp = getname(filename); | 966 | char *tmp = getname(filename); |
896 | int fd = PTR_ERR(tmp); | 967 | int fd = PTR_ERR(tmp); |
897 | 968 | ||
898 | if (!IS_ERR(tmp)) { | 969 | if (!IS_ERR(tmp)) { |
899 | fd = get_unused_fd_flags(flags); | 970 | fd = get_unused_fd_flags(flags); |
900 | if (fd >= 0) { | 971 | if (fd >= 0) { |
901 | struct file *f = do_filp_open(dfd, tmp, flags, mode, 0); | 972 | struct file *f = do_filp_open(dfd, tmp, &op, lookup); |
902 | if (IS_ERR(f)) { | 973 | if (IS_ERR(f)) { |
903 | put_unused_fd(fd); | 974 | put_unused_fd(fd); |
904 | fd = PTR_ERR(f); | 975 | fd = PTR_ERR(f); |