| @@ -184,6 +184,20 @@ int vfs_fstat(int fd, struct kstat *stat) · 183 unmodified lines |
| 184 | 184 | return error; |
| 185 | 185 | } |
| 186 | 186 | |
| 187 | +int getname_statx_lookup_flags(int flags) |
| 188 | +{ |
| 189 | + int lookup_flags = 0; |
| 190 | + |
| 191 | + if (!(flags & AT_SYMLINK_NOFOLLOW)) |
| 192 | + lookup_flags |= LOOKUP_FOLLOW; |
| 193 | + if (!(flags & AT_NO_AUTOMOUNT)) |
| 194 | + lookup_flags |= LOOKUP_AUTOMOUNT; |
| 195 | + if (flags & AT_EMPTY_PATH) |
| 196 | + lookup_flags |= LOOKUP_EMPTY; |
| 197 | + |
| 198 | + return lookup_flags; |
| 199 | +} |
| 200 | + |
| 187 | 201 | /** |
| 188 | 202 | * vfs_statx - Get basic and extra attributes by filename |
| 189 | 203 | * @dfd: A file descriptor representing the base dir for a relative filename |
| @@ -199,26 +213,19 @@ int vfs_fstat(int fd, struct kstat *stat) · 9 unmodified lines |
| 199 | 213 | * |
| 200 | 214 | * 0 will be returned on success, and a -ve error code if unsuccessful. |
| 201 | 215 | */ |
| 202 | | −static int vfs_statx(int dfd, const char __user *filename, int flags, |
| 216 | +static int vfs_statx(int dfd, struct filename *filename, int flags, |
| 203 | 217 | struct kstat *stat, u32 request_mask) |
| 204 | 218 | { |
| 205 | 219 | struct path path; |
| 206 | | − unsigned lookup_flags = 0; |
| 220 | + unsigned int lookup_flags = getname_statx_lookup_flags(flags); |
| 207 | 221 | int error; |
| 208 | 222 | |
| 209 | 223 | if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH | |
| 210 | 224 | AT_STATX_SYNC_TYPE)) |
| 211 | 225 | return -EINVAL; |
| 212 | 226 | |
| 213 | | − if (!(flags & AT_SYMLINK_NOFOLLOW)) |
| 214 | | − lookup_flags |= LOOKUP_FOLLOW; |
| 215 | | − if (!(flags & AT_NO_AUTOMOUNT)) |
| 216 | | − lookup_flags |= LOOKUP_AUTOMOUNT; |
| 217 | | − if (flags & AT_EMPTY_PATH) |
| 218 | | − lookup_flags |= LOOKUP_EMPTY; |
| 219 | | − |
| 220 | 227 | retry: |
| 221 | | − error = user_path_at(dfd, filename, lookup_flags, &path); |
| 228 | + error = filename_lookup(dfd, filename, lookup_flags, &path, NULL); |
| 222 | 229 | if (error) |
| 223 | 230 | goto out; |
| 224 | 231 | |
| @@ -240,8 +247,15 @@ out: · 15 unmodified lines |
| 240 | 247 | int vfs_fstatat(int dfd, const char __user *filename, |
| 241 | 248 | struct kstat *stat, int flags) |
| 242 | 249 | { |
| 243 | | − return vfs_statx(dfd, filename, flags | AT_NO_AUTOMOUNT, |
| 244 | | − stat, STATX_BASIC_STATS); |
| 250 | + int ret; |
| 251 | + int statx_flags = flags | AT_NO_AUTOMOUNT; |
| 252 | + struct filename *name; |
| 253 | + |
| 254 | + name = getname_flags(filename, getname_statx_lookup_flags(statx_flags), NULL); |
| 255 | + ret = vfs_statx(dfd, name, statx_flags, stat, STATX_BASIC_STATS); |
| 256 | + putname(name); |
| 257 | + |
| 258 | + return ret; |
| 245 | 259 | } |
| 246 | 260 | |
| 247 | 261 | #ifdef __ARCH_WANT_OLD_STAT |
| @@ -602,7 +616,7 @@ cp_statx(const struct kstat *stat, struct statx __user *buffer) · 354 unmodified lines |
| 602 | 616 | return copy_to_user(buffer, &tmp, sizeof(tmp)) ? -EFAULT : 0; |
| 603 | 617 | } |
| 604 | 618 | |
| 605 | | −int do_statx(int dfd, const char __user *filename, unsigned flags, |
| 619 | +int do_statx(int dfd, struct filename *filename, unsigned int flags, |
| 606 | 620 | unsigned int mask, struct statx __user *buffer) |
| 607 | 621 | { |
| 608 | 622 | struct kstat stat; |
| @@ -636,7 +650,14 @@ SYSCALL_DEFINE5(statx, · 27 unmodified lines |
| 636 | 650 | unsigned int, mask, |
| 637 | 651 | struct statx __user *, buffer) |
| 638 | 652 | { |
| 639 | | − return do_statx(dfd, filename, flags, mask, buffer); |
| 653 | + int ret; |
| 654 | + struct filename *name; |
| 655 | + |
| 656 | + name = getname_flags(filename, getname_statx_lookup_flags(flags), NULL); |
| 657 | + ret = do_statx(dfd, name, flags, mask, buffer); |
| 658 | + putname(name); |
| 659 | + |
| 660 | + return ret; |
| 640 | 661 | } |
| 641 | 662 | |
| 642 | 663 | #ifdef CONFIG_COMPAT |