aboutsummaryrefslogtreecommitdiffstats
path: root/fs/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/open.c')
-rw-r--r--fs/open.c73
1 files changed, 72 insertions, 1 deletions
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);