switch do_filp_open() to struct open_flags
Al Viro [Wed, 23 Feb 2011 22:44:09 +0000 (17:44 -0500)]
take calculation of open_flags by open(2) arguments into new helper
in fs/open.c, move filp_open() over there, have it and do_sys_open()
use that helper, switch exec.c callers of do_filp_open() to explicit
(and constant) struct open_flags.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

fs/exec.c
fs/internal.h
fs/namei.c
fs/open.c
include/linux/fs.h

index 52a447d..ba99e1a 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -115,13 +115,16 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
        struct file *file;
        char *tmp = getname(library);
        int error = PTR_ERR(tmp);
+       static const struct open_flags uselib_flags = {
+               .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
+               .acc_mode = MAY_READ | MAY_EXEC | MAY_OPEN,
+               .intent = LOOKUP_OPEN
+       };
 
        if (IS_ERR(tmp))
                goto out;
 
-       file = do_filp_open(AT_FDCWD, tmp,
-                               O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0,
-                               MAY_READ | MAY_EXEC | MAY_OPEN);
+       file = do_filp_open(AT_FDCWD, tmp, &uselib_flags, LOOKUP_FOLLOW);
        putname(tmp);
        error = PTR_ERR(file);
        if (IS_ERR(file))
@@ -721,10 +724,13 @@ struct file *open_exec(const char *name)
 {
        struct file *file;
        int err;
+       static const struct open_flags open_exec_flags = {
+               .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
+               .acc_mode = MAY_EXEC | MAY_OPEN,
+               .intent = LOOKUP_OPEN
+       };
 
-       file = do_filp_open(AT_FDCWD, name,
-                               O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0,
-                               MAY_EXEC | MAY_OPEN);
+       file = do_filp_open(AT_FDCWD, name, &open_exec_flags, LOOKUP_FOLLOW);
        if (IS_ERR(file))
                goto out;
 
index 9b976b5..6fdbdf2 100644 (file)
@@ -106,6 +106,14 @@ extern void put_super(struct super_block *sb);
 struct nameidata;
 extern struct file *nameidata_to_filp(struct nameidata *);
 extern void release_open_intent(struct nameidata *);
+struct open_flags {
+       int open_flag;
+       int mode;
+       int acc_mode;
+       int intent;
+};
+extern struct file *do_filp_open(int dfd, const char *pathname,
+               const struct open_flags *op, int lookup_flags);
 
 /*
  * inode.c
index 5e4206f..9c7fa94 100644 (file)
@@ -2169,13 +2169,6 @@ exit:
        return ERR_PTR(error);
 }
 
-struct open_flags {
-       int open_flag;
-       int mode;
-       int acc_mode;
-       int intent;
-};
-
 /*
  * Handle O_CREAT case for do_filp_open
  */
@@ -2305,74 +2298,28 @@ exit:
  * open_to_namei_flags() for more details.
  */
 struct file *do_filp_open(int dfd, const char *pathname,
-               int open_flag, int mode, int acc_mode)
+               const struct open_flags *op, int flags)
 {
        struct file *filp;
        struct nameidata nd;
        int error;
        struct path path;
        int count = 0;
-       int flag = open_to_namei_flags(open_flag);
-       int flags = 0;
-       struct open_flags op;
-
-       if (!(open_flag & O_CREAT))
-               mode = 0;
-
-       /* Must never be set by userspace */
-       open_flag &= ~FMODE_NONOTIFY;
-
-       /*
-        * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
-        * check for O_DSYNC if the need any syncing at all we enforce it's
-        * always set instead of having to deal with possibly weird behaviour
-        * for malicious applications setting only __O_SYNC.
-        */
-       if (open_flag & __O_SYNC)
-               open_flag |= O_DSYNC;
-
-       op.open_flag = open_flag;
-
-       if (!acc_mode)
-               acc_mode = MAY_OPEN | ACC_MODE(open_flag);
-
-       /* O_TRUNC implies we need access checks for write permissions */
-       if (open_flag & O_TRUNC)
-               acc_mode |= MAY_WRITE;
-
-       /* Allow the LSM permission hook to distinguish append 
-          access from general write access. */
-       if (open_flag & O_APPEND)
-               acc_mode |= MAY_APPEND;
-
-       op.acc_mode = acc_mode;
-
-       op.intent = LOOKUP_OPEN;
-       if (open_flag & O_CREAT) {
-               op.intent |= LOOKUP_CREATE;
-               if (open_flag & O_EXCL)
-                       op.intent |= LOOKUP_EXCL;
-       }
-
-       if (open_flag & O_DIRECTORY)
-               flags |= LOOKUP_DIRECTORY;
-       if (!(open_flag & O_NOFOLLOW))
-               flags |= LOOKUP_FOLLOW;
 
        filp = get_empty_filp();
        if (!filp)
                return ERR_PTR(-ENFILE);
 
-       filp->f_flags = open_flag;
+       filp->f_flags = op->open_flag;
        nd.intent.open.file = filp;
-       nd.intent.open.flags = flag;
-       nd.intent.open.create_mode = mode;
+       nd.intent.open.flags = open_to_namei_flags(op->open_flag);
+       nd.intent.open.create_mode = op->mode;
 
-       if (open_flag & O_CREAT)
+       if (op->open_flag & O_CREAT)
                goto creat;
 
        /* !O_CREAT, simple open */
-       error = do_path_lookup(dfd, pathname, flags | op.intent, &nd);
+       error = do_path_lookup(dfd, pathname, flags | op->intent, &nd);
        if (unlikely(error))
                goto out_filp2;
        error = -ELOOP;
@@ -2386,7 +2333,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
                        goto out_path2;
        }
        audit_inode(pathname, nd.path.dentry);
-       filp = finish_open(&nd, open_flag, acc_mode);
+       filp = finish_open(&nd, op->open_flag, op->acc_mode);
 out2:
        release_open_intent(&nd);
        return filp;
@@ -2416,7 +2363,7 @@ reval:
        /*
         * We have the parent and last component.
         */
-       filp = do_last(&nd, &path, &op, pathname);
+       filp = do_last(&nd, &path, op, pathname);
        while (unlikely(!filp)) { /* trailing symlink */
                struct path link = path;
                struct inode *linki = link.dentry->d_inode;
@@ -2443,7 +2390,7 @@ reval:
                if (unlikely(error))
                        filp = ERR_PTR(error);
                else
-                       filp = do_last(&nd, &path, &op, pathname);
+                       filp = do_last(&nd, &path, op, pathname);
                if (!IS_ERR(cookie) && linki->i_op->put_link)
                        linki->i_op->put_link(link.dentry, &nd, cookie);
                path_put(&link);
@@ -2466,23 +2413,6 @@ out_filp:
 }
 
 /**
- * filp_open - open file and return file pointer
- *
- * @filename:  path to open
- * @flags:     open flags as per the open(2) second argument
- * @mode:      mode for the new file if O_CREAT is set, else ignored
- *
- * This is the helper to open a file from kernelspace if you really
- * have to.  But in generally you should not do this, so please move
- * along, nothing to see here..
- */
-struct file *filp_open(const char *filename, int flags, int mode)
-{
-       return do_filp_open(AT_FDCWD, filename, flags, mode, 0);
-}
-EXPORT_SYMBOL(filp_open);
-
-/**
  * lookup_create - lookup a dentry, creating it if it doesn't exist
  * @nd: nameidata info
  * @is_dir: directory flag
index b47aab3..d05e18c 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -890,15 +890,86 @@ void fd_install(unsigned int fd, struct file *file)
 
 EXPORT_SYMBOL(fd_install);
 
+static inline int build_open_flags(int flags, int mode, struct open_flags *op)
+{
+       int lookup_flags = 0;
+       int acc_mode;
+
+       if (!(flags & O_CREAT))
+               mode = 0;
+       op->mode = mode;
+
+       /* Must never be set by userspace */
+       flags &= ~FMODE_NONOTIFY;
+
+       /*
+        * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
+        * check for O_DSYNC if the need any syncing at all we enforce it's
+        * always set instead of having to deal with possibly weird behaviour
+        * for malicious applications setting only __O_SYNC.
+        */
+       if (flags & __O_SYNC)
+               flags |= O_DSYNC;
+
+       op->open_flag = flags;
+
+       acc_mode = MAY_OPEN | ACC_MODE(flags);
+
+       /* O_TRUNC implies we need access checks for write permissions */
+       if (flags & O_TRUNC)
+               acc_mode |= MAY_WRITE;
+
+       /* Allow the LSM permission hook to distinguish append
+          access from general write access. */
+       if (flags & O_APPEND)
+               acc_mode |= MAY_APPEND;
+
+       op->acc_mode = acc_mode;
+
+       op->intent = LOOKUP_OPEN;
+       if (flags & O_CREAT) {
+               op->intent |= LOOKUP_CREATE;
+               if (flags & O_EXCL)
+                       op->intent |= LOOKUP_EXCL;
+       }
+
+       if (flags & O_DIRECTORY)
+               lookup_flags |= LOOKUP_DIRECTORY;
+       if (!(flags & O_NOFOLLOW))
+               lookup_flags |= LOOKUP_FOLLOW;
+       return lookup_flags;
+}
+
+/**
+ * filp_open - open file and return file pointer
+ *
+ * @filename:  path to open
+ * @flags:     open flags as per the open(2) second argument
+ * @mode:      mode for the new file if O_CREAT is set, else ignored
+ *
+ * This is the helper to open a file from kernelspace if you really
+ * have to.  But in generally you should not do this, so please move
+ * along, nothing to see here..
+ */
+struct file *filp_open(const char *filename, int flags, int mode)
+{
+       struct open_flags op;
+       int lookup = build_open_flags(flags, mode, &op);
+       return do_filp_open(AT_FDCWD, filename, &op, lookup);
+}
+EXPORT_SYMBOL(filp_open);
+
 long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
 {
+       struct open_flags op;
+       int lookup = build_open_flags(flags, mode, &op);
        char *tmp = getname(filename);
        int fd = PTR_ERR(tmp);
 
        if (!IS_ERR(tmp)) {
                fd = get_unused_fd_flags(flags);
                if (fd >= 0) {
-                       struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);
+                       struct file *f = do_filp_open(dfd, tmp, &op, lookup);
                        if (IS_ERR(f)) {
                                put_unused_fd(fd);
                                fd = PTR_ERR(f);
index e38b50a..9c75714 100644 (file)
@@ -2205,8 +2205,6 @@ extern struct file *create_read_pipe(struct file *f, int flags);
 extern struct file *create_write_pipe(int flags);
 extern void free_write_pipe(struct file *);
 
-extern struct file *do_filp_open(int dfd, const char *pathname,
-               int open_flag, int mode, int acc_mode);
 extern int may_open(struct path *, int, int);
 
 extern int kernel_read(struct file *, loff_t, char *, unsigned long);