diff options
Diffstat (limited to 'fs/open.c')
-rw-r--r-- | fs/open.c | 67 |
1 files changed, 40 insertions, 27 deletions
@@ -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 | |||
893 | struct file *file_open_name(struct filename *name, int flags, umode_t mode) | 900 | struct 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 | } |
930 | EXPORT_SYMBOL(file_open_root); | 939 | EXPORT_SYMBOL(file_open_root); |
931 | 940 | ||
932 | long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) | 941 | long 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 | ||