diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 45 |
1 files changed, 25 insertions, 20 deletions
diff --git a/fs/namei.c b/fs/namei.c index 4acdac043b6b..e28de846c591 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -790,7 +790,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
790 | 790 | ||
791 | inode = nd->dentry->d_inode; | 791 | inode = nd->dentry->d_inode; |
792 | if (nd->depth) | 792 | if (nd->depth) |
793 | lookup_flags = LOOKUP_FOLLOW; | 793 | lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE); |
794 | 794 | ||
795 | /* At this point we know we have a real path component. */ | 795 | /* At this point we know we have a real path component. */ |
796 | for(;;) { | 796 | for(;;) { |
@@ -885,7 +885,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
885 | last_with_slashes: | 885 | last_with_slashes: |
886 | lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; | 886 | lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; |
887 | last_component: | 887 | last_component: |
888 | nd->flags &= ~LOOKUP_CONTINUE; | 888 | /* Clear LOOKUP_CONTINUE iff it was previously unset */ |
889 | nd->flags &= lookup_flags | ~LOOKUP_CONTINUE; | ||
889 | if (lookup_flags & LOOKUP_PARENT) | 890 | if (lookup_flags & LOOKUP_PARENT) |
890 | goto lookup_parent; | 891 | goto lookup_parent; |
891 | if (this.name[0] == '.') switch (this.len) { | 892 | if (this.name[0] == '.') switch (this.len) { |
@@ -1069,6 +1070,8 @@ static int fastcall do_path_lookup(int dfd, const char *name, | |||
1069 | unsigned int flags, struct nameidata *nd) | 1070 | unsigned int flags, struct nameidata *nd) |
1070 | { | 1071 | { |
1071 | int retval = 0; | 1072 | int retval = 0; |
1073 | int fput_needed; | ||
1074 | struct file *file; | ||
1072 | 1075 | ||
1073 | nd->last_type = LAST_ROOT; /* if there are only slashes... */ | 1076 | nd->last_type = LAST_ROOT; /* if there are only slashes... */ |
1074 | nd->flags = flags; | 1077 | nd->flags = flags; |
@@ -1090,29 +1093,22 @@ static int fastcall do_path_lookup(int dfd, const char *name, | |||
1090 | nd->mnt = mntget(current->fs->pwdmnt); | 1093 | nd->mnt = mntget(current->fs->pwdmnt); |
1091 | nd->dentry = dget(current->fs->pwd); | 1094 | nd->dentry = dget(current->fs->pwd); |
1092 | } else { | 1095 | } else { |
1093 | struct file *file; | ||
1094 | int fput_needed; | ||
1095 | struct dentry *dentry; | 1096 | struct dentry *dentry; |
1096 | 1097 | ||
1097 | file = fget_light(dfd, &fput_needed); | 1098 | file = fget_light(dfd, &fput_needed); |
1098 | if (!file) { | 1099 | retval = -EBADF; |
1099 | retval = -EBADF; | 1100 | if (!file) |
1100 | goto out_fail; | 1101 | goto unlock_fail; |
1101 | } | ||
1102 | 1102 | ||
1103 | dentry = file->f_dentry; | 1103 | dentry = file->f_dentry; |
1104 | 1104 | ||
1105 | if (!S_ISDIR(dentry->d_inode->i_mode)) { | 1105 | retval = -ENOTDIR; |
1106 | retval = -ENOTDIR; | 1106 | if (!S_ISDIR(dentry->d_inode->i_mode)) |
1107 | fput_light(file, fput_needed); | 1107 | goto fput_unlock_fail; |
1108 | goto out_fail; | ||
1109 | } | ||
1110 | 1108 | ||
1111 | retval = file_permission(file, MAY_EXEC); | 1109 | retval = file_permission(file, MAY_EXEC); |
1112 | if (retval) { | 1110 | if (retval) |
1113 | fput_light(file, fput_needed); | 1111 | goto fput_unlock_fail; |
1114 | goto out_fail; | ||
1115 | } | ||
1116 | 1112 | ||
1117 | nd->mnt = mntget(file->f_vfsmnt); | 1113 | nd->mnt = mntget(file->f_vfsmnt); |
1118 | nd->dentry = dget(dentry); | 1114 | nd->dentry = dget(dentry); |
@@ -1123,10 +1119,17 @@ static int fastcall do_path_lookup(int dfd, const char *name, | |||
1123 | current->total_link_count = 0; | 1119 | current->total_link_count = 0; |
1124 | retval = link_path_walk(name, nd); | 1120 | retval = link_path_walk(name, nd); |
1125 | out: | 1121 | out: |
1126 | if (unlikely(current->audit_context | 1122 | if (likely(retval == 0)) { |
1127 | && nd && nd->dentry && nd->dentry->d_inode)) | 1123 | if (unlikely(current->audit_context && nd && nd->dentry && |
1124 | nd->dentry->d_inode)) | ||
1128 | audit_inode(name, nd->dentry->d_inode, flags); | 1125 | audit_inode(name, nd->dentry->d_inode, flags); |
1129 | out_fail: | 1126 | } |
1127 | return retval; | ||
1128 | |||
1129 | fput_unlock_fail: | ||
1130 | fput_light(file, fput_needed); | ||
1131 | unlock_fail: | ||
1132 | read_unlock(¤t->fs->lock); | ||
1130 | return retval; | 1133 | return retval; |
1131 | } | 1134 | } |
1132 | 1135 | ||
@@ -1161,6 +1164,7 @@ static int __path_lookup_intent_open(int dfd, const char *name, | |||
1161 | 1164 | ||
1162 | /** | 1165 | /** |
1163 | * path_lookup_open - lookup a file path with open intent | 1166 | * path_lookup_open - lookup a file path with open intent |
1167 | * @dfd: the directory to use as base, or AT_FDCWD | ||
1164 | * @name: pointer to file name | 1168 | * @name: pointer to file name |
1165 | * @lookup_flags: lookup intent flags | 1169 | * @lookup_flags: lookup intent flags |
1166 | * @nd: pointer to nameidata | 1170 | * @nd: pointer to nameidata |
@@ -1175,6 +1179,7 @@ int path_lookup_open(int dfd, const char *name, unsigned int lookup_flags, | |||
1175 | 1179 | ||
1176 | /** | 1180 | /** |
1177 | * path_lookup_create - lookup a file path with open + create intent | 1181 | * path_lookup_create - lookup a file path with open + create intent |
1182 | * @dfd: the directory to use as base, or AT_FDCWD | ||
1178 | * @name: pointer to file name | 1183 | * @name: pointer to file name |
1179 | * @lookup_flags: lookup intent flags | 1184 | * @lookup_flags: lookup intent flags |
1180 | * @nd: pointer to nameidata | 1185 | * @nd: pointer to nameidata |