diff options
Diffstat (limited to 'fs/open.c')
-rw-r--r-- | fs/open.c | 73 |
1 files changed, 72 insertions, 1 deletions
@@ -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); |