aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/exec.c18
-rw-r--r--fs/internal.h8
-rw-r--r--fs/namei.c88
-rw-r--r--fs/open.c73
4 files changed, 101 insertions, 86 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 52a447d9b6ab..ba99e1abb1aa 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -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);
106struct nameidata; 106struct nameidata;
107extern struct file *nameidata_to_filp(struct nameidata *); 107extern struct file *nameidata_to_filp(struct nameidata *);
108extern void release_open_intent(struct nameidata *); 108extern void release_open_intent(struct nameidata *);
109struct open_flags {
110 int open_flag;
111 int mode;
112 int acc_mode;
113 int intent;
114};
115extern 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
2172struct 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 */
2307struct file *do_filp_open(int dfd, const char *pathname, 2300struct 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);
2390out2: 2337out2:
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 */
2479struct file *filp_open(const char *filename, int flags, int mode)
2480{
2481 return do_filp_open(AT_FDCWD, filename, flags, mode, 0);
2482}
2483EXPORT_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
diff --git a/fs/open.c b/fs/open.c
index b47aab39c057..d05e18c60bae 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -890,15 +890,86 @@ void fd_install(unsigned int fd, struct file *file)
890 890
891EXPORT_SYMBOL(fd_install); 891EXPORT_SYMBOL(fd_install);
892 892
893static 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 */
954struct 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}
960EXPORT_SYMBOL(filp_open);
961
893long do_sys_open(int dfd, const char __user *filename, int flags, int mode) 962long 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);