aboutsummaryrefslogtreecommitdiffstats
path: root/fs/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/open.c')
-rw-r--r--fs/open.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/fs/open.c b/fs/open.c
index 48afc5c139d2..14a51de01f54 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -669,11 +669,16 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
669 int (*open)(struct inode *, struct file *), 669 int (*open)(struct inode *, struct file *),
670 const struct cred *cred) 670 const struct cred *cred)
671{ 671{
672 static const struct file_operations empty_fops = {};
672 struct inode *inode; 673 struct inode *inode;
673 int error; 674 int error;
674 675
675 f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK | 676 f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
676 FMODE_PREAD | FMODE_PWRITE; 677 FMODE_PREAD | FMODE_PWRITE;
678
679 if (unlikely(f->f_flags & O_PATH))
680 f->f_mode = FMODE_PATH;
681
677 inode = dentry->d_inode; 682 inode = dentry->d_inode;
678 if (f->f_mode & FMODE_WRITE) { 683 if (f->f_mode & FMODE_WRITE) {
679 error = __get_file_write_access(inode, mnt); 684 error = __get_file_write_access(inode, mnt);
@@ -687,9 +692,15 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
687 f->f_path.dentry = dentry; 692 f->f_path.dentry = dentry;
688 f->f_path.mnt = mnt; 693 f->f_path.mnt = mnt;
689 f->f_pos = 0; 694 f->f_pos = 0;
690 f->f_op = fops_get(inode->i_fop);
691 file_sb_list_add(f, inode->i_sb); 695 file_sb_list_add(f, inode->i_sb);
692 696
697 if (unlikely(f->f_mode & FMODE_PATH)) {
698 f->f_op = &empty_fops;
699 return f;
700 }
701
702 f->f_op = fops_get(inode->i_fop);
703
693 error = security_dentry_open(f, cred); 704 error = security_dentry_open(f, cred);
694 if (error) 705 if (error)
695 goto cleanup_all; 706 goto cleanup_all;
@@ -911,9 +922,18 @@ static inline int build_open_flags(int flags, int mode, struct open_flags *op)
911 if (flags & __O_SYNC) 922 if (flags & __O_SYNC)
912 flags |= O_DSYNC; 923 flags |= O_DSYNC;
913 924
914 op->open_flag = flags; 925 /*
926 * If we have O_PATH in the open flag. Then we
927 * cannot have anything other than the below set of flags
928 */
929 if (flags & O_PATH) {
930 flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;
931 acc_mode = 0;
932 } else {
933 acc_mode = MAY_OPEN | ACC_MODE(flags);
934 }
915 935
916 acc_mode = MAY_OPEN | ACC_MODE(flags); 936 op->open_flag = flags;
917 937
918 /* O_TRUNC implies we need access checks for write permissions */ 938 /* O_TRUNC implies we need access checks for write permissions */
919 if (flags & O_TRUNC) 939 if (flags & O_TRUNC)
@@ -926,7 +946,8 @@ static inline int build_open_flags(int flags, int mode, struct open_flags *op)
926 946
927 op->acc_mode = acc_mode; 947 op->acc_mode = acc_mode;
928 948
929 op->intent = LOOKUP_OPEN; 949 op->intent = flags & O_PATH ? 0 : LOOKUP_OPEN;
950
930 if (flags & O_CREAT) { 951 if (flags & O_CREAT) {
931 op->intent |= LOOKUP_CREATE; 952 op->intent |= LOOKUP_CREATE;
932 if (flags & O_EXCL) 953 if (flags & O_EXCL)
@@ -1053,8 +1074,10 @@ int filp_close(struct file *filp, fl_owner_t id)
1053 if (filp->f_op && filp->f_op->flush) 1074 if (filp->f_op && filp->f_op->flush)
1054 retval = filp->f_op->flush(filp, id); 1075 retval = filp->f_op->flush(filp, id);
1055 1076
1056 dnotify_flush(filp, id); 1077 if (likely(!(filp->f_mode & FMODE_PATH))) {
1057 locks_remove_posix(filp, id); 1078 dnotify_flush(filp, id);
1079 locks_remove_posix(filp, id);
1080 }
1058 fput(filp); 1081 fput(filp);
1059 return retval; 1082 return retval;
1060} 1083}