aboutsummaryrefslogtreecommitdiffstats
path: root/fs/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/open.c')
-rw-r--r--fs/open.c67
1 files changed, 40 insertions, 27 deletions
diff --git a/fs/open.c b/fs/open.c
index 8c741002f947..7931f76acc2b 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -823,7 +823,7 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
823 int lookup_flags = 0; 823 int lookup_flags = 0;
824 int acc_mode; 824 int acc_mode;
825 825
826 if (flags & O_CREAT) 826 if (flags & (O_CREAT | __O_TMPFILE))
827 op->mode = (mode & S_IALLUGO) | S_IFREG; 827 op->mode = (mode & S_IALLUGO) | S_IFREG;
828 else 828 else
829 op->mode = 0; 829 op->mode = 0;
@@ -840,11 +840,17 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
840 if (flags & __O_SYNC) 840 if (flags & __O_SYNC)
841 flags |= O_DSYNC; 841 flags |= O_DSYNC;
842 842
843 /* 843 if (flags & __O_TMPFILE) {
844 * If we have O_PATH in the open flag. Then we 844 if ((flags & O_TMPFILE_MASK) != O_TMPFILE)
845 * cannot have anything other than the below set of flags 845 return -EINVAL;
846 */ 846 acc_mode = MAY_OPEN | ACC_MODE(flags);
847 if (flags & O_PATH) { 847 if (!(acc_mode & MAY_WRITE))
848 return -EINVAL;
849 } else if (flags & O_PATH) {
850 /*
851 * If we have O_PATH in the open flag. Then we
852 * cannot have anything other than the below set of flags
853 */
848 flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH; 854 flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;
849 acc_mode = 0; 855 acc_mode = 0;
850 } else { 856 } else {
@@ -876,7 +882,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
876 lookup_flags |= LOOKUP_DIRECTORY; 882 lookup_flags |= LOOKUP_DIRECTORY;
877 if (!(flags & O_NOFOLLOW)) 883 if (!(flags & O_NOFOLLOW))
878 lookup_flags |= LOOKUP_FOLLOW; 884 lookup_flags |= LOOKUP_FOLLOW;
879 return lookup_flags; 885 op->lookup_flags = lookup_flags;
886 return 0;
880} 887}
881 888
882/** 889/**
@@ -893,8 +900,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) 900struct file *file_open_name(struct filename *name, int flags, umode_t mode)
894{ 901{
895 struct open_flags op; 902 struct open_flags op;
896 int lookup = build_open_flags(flags, mode, &op); 903 int err = build_open_flags(flags, mode, &op);
897 return do_filp_open(AT_FDCWD, name, &op, lookup); 904 return err ? ERR_PTR(err) : do_filp_open(AT_FDCWD, name, &op);
898} 905}
899 906
900/** 907/**
@@ -919,37 +926,43 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
919 const char *filename, int flags) 926 const char *filename, int flags)
920{ 927{
921 struct open_flags op; 928 struct open_flags op;
922 int lookup = build_open_flags(flags, 0, &op); 929 int err = build_open_flags(flags, 0, &op);
930 if (err)
931 return ERR_PTR(err);
923 if (flags & O_CREAT) 932 if (flags & O_CREAT)
924 return ERR_PTR(-EINVAL); 933 return ERR_PTR(-EINVAL);
925 if (!filename && (flags & O_DIRECTORY)) 934 if (!filename && (flags & O_DIRECTORY))
926 if (!dentry->d_inode->i_op->lookup) 935 if (!dentry->d_inode->i_op->lookup)
927 return ERR_PTR(-ENOTDIR); 936 return ERR_PTR(-ENOTDIR);
928 return do_file_open_root(dentry, mnt, filename, &op, lookup); 937 return do_file_open_root(dentry, mnt, filename, &op);
929} 938}
930EXPORT_SYMBOL(file_open_root); 939EXPORT_SYMBOL(file_open_root);
931 940
932long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) 941long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
933{ 942{
934 struct open_flags op; 943 struct open_flags op;
935 int lookup = build_open_flags(flags, mode, &op); 944 int fd = build_open_flags(flags, mode, &op);
936 struct filename *tmp = getname(filename); 945 struct filename *tmp;
937 int fd = PTR_ERR(tmp); 946
938 947 if (fd)
939 if (!IS_ERR(tmp)) { 948 return fd;
940 fd = get_unused_fd_flags(flags); 949
941 if (fd >= 0) { 950 tmp = getname(filename);
942 struct file *f = do_filp_open(dfd, tmp, &op, lookup); 951 if (IS_ERR(tmp))
943 if (IS_ERR(f)) { 952 return PTR_ERR(tmp);
944 put_unused_fd(fd); 953
945 fd = PTR_ERR(f); 954 fd = get_unused_fd_flags(flags);
946 } else { 955 if (fd >= 0) {
947 fsnotify_open(f); 956 struct file *f = do_filp_open(dfd, tmp, &op);
948 fd_install(fd, f); 957 if (IS_ERR(f)) {
949 } 958 put_unused_fd(fd);
959 fd = PTR_ERR(f);
960 } else {
961 fsnotify_open(f);
962 fd_install(fd, f);
950 } 963 }
951 putname(tmp);
952 } 964 }
965 putname(tmp);
953 return fd; 966 return fd;
954} 967}
955 968