diff options
| -rw-r--r-- | fs/stat.c | 74 |
1 files changed, 32 insertions, 42 deletions
| @@ -510,46 +510,37 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename, | |||
| 510 | } | 510 | } |
| 511 | #endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */ | 511 | #endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */ |
| 512 | 512 | ||
| 513 | static inline int __put_timestamp(struct timespec *kts, | 513 | static noinline_for_stack int |
| 514 | struct statx_timestamp __user *uts) | 514 | cp_statx(const struct kstat *stat, struct statx __user *buffer) |
| 515 | { | 515 | { |
| 516 | return (__put_user(kts->tv_sec, &uts->tv_sec ) || | 516 | struct statx tmp; |
| 517 | __put_user(kts->tv_nsec, &uts->tv_nsec ) || | 517 | |
| 518 | __put_user(0, &uts->__reserved )); | 518 | memset(&tmp, 0, sizeof(tmp)); |
| 519 | } | 519 | |
| 520 | 520 | tmp.stx_mask = stat->result_mask; | |
| 521 | /* | 521 | tmp.stx_blksize = stat->blksize; |
| 522 | * Set the statx results. | 522 | tmp.stx_attributes = stat->attributes; |
| 523 | */ | 523 | tmp.stx_nlink = stat->nlink; |
| 524 | static long statx_set_result(struct kstat *stat, struct statx __user *buffer) | 524 | tmp.stx_uid = from_kuid_munged(current_user_ns(), stat->uid); |
| 525 | { | 525 | tmp.stx_gid = from_kgid_munged(current_user_ns(), stat->gid); |
| 526 | uid_t uid = from_kuid_munged(current_user_ns(), stat->uid); | 526 | tmp.stx_mode = stat->mode; |
| 527 | gid_t gid = from_kgid_munged(current_user_ns(), stat->gid); | 527 | tmp.stx_ino = stat->ino; |
| 528 | 528 | tmp.stx_size = stat->size; | |
| 529 | if (__put_user(stat->result_mask, &buffer->stx_mask ) || | 529 | tmp.stx_blocks = stat->blocks; |
| 530 | __put_user(stat->mode, &buffer->stx_mode ) || | 530 | tmp.stx_atime.tv_sec = stat->atime.tv_sec; |
| 531 | __clear_user(&buffer->__spare0, sizeof(buffer->__spare0)) || | 531 | tmp.stx_atime.tv_nsec = stat->atime.tv_nsec; |
| 532 | __put_user(stat->nlink, &buffer->stx_nlink ) || | 532 | tmp.stx_btime.tv_sec = stat->btime.tv_sec; |
| 533 | __put_user(uid, &buffer->stx_uid ) || | 533 | tmp.stx_btime.tv_nsec = stat->btime.tv_nsec; |
| 534 | __put_user(gid, &buffer->stx_gid ) || | 534 | tmp.stx_ctime.tv_sec = stat->ctime.tv_sec; |
| 535 | __put_user(stat->attributes, &buffer->stx_attributes ) || | 535 | tmp.stx_ctime.tv_nsec = stat->ctime.tv_nsec; |
| 536 | __put_user(stat->blksize, &buffer->stx_blksize ) || | 536 | tmp.stx_mtime.tv_sec = stat->mtime.tv_sec; |
| 537 | __put_user(MAJOR(stat->rdev), &buffer->stx_rdev_major ) || | 537 | tmp.stx_mtime.tv_nsec = stat->mtime.tv_nsec; |
| 538 | __put_user(MINOR(stat->rdev), &buffer->stx_rdev_minor ) || | 538 | tmp.stx_rdev_major = MAJOR(stat->rdev); |
| 539 | __put_user(MAJOR(stat->dev), &buffer->stx_dev_major ) || | 539 | tmp.stx_rdev_minor = MINOR(stat->rdev); |
| 540 | __put_user(MINOR(stat->dev), &buffer->stx_dev_minor ) || | 540 | tmp.stx_dev_major = MAJOR(stat->dev); |
| 541 | __put_timestamp(&stat->atime, &buffer->stx_atime ) || | 541 | tmp.stx_dev_minor = MINOR(stat->dev); |
| 542 | __put_timestamp(&stat->btime, &buffer->stx_btime ) || | 542 | |
| 543 | __put_timestamp(&stat->ctime, &buffer->stx_ctime ) || | 543 | return copy_to_user(buffer, &tmp, sizeof(tmp)) ? -EFAULT : 0; |
| 544 | __put_timestamp(&stat->mtime, &buffer->stx_mtime ) || | ||
| 545 | __put_user(stat->ino, &buffer->stx_ino ) || | ||
| 546 | __put_user(stat->size, &buffer->stx_size ) || | ||
| 547 | __put_user(stat->blocks, &buffer->stx_blocks ) || | ||
| 548 | __clear_user(&buffer->__spare1, sizeof(buffer->__spare1)) || | ||
| 549 | __clear_user(&buffer->__spare2, sizeof(buffer->__spare2))) | ||
| 550 | return -EFAULT; | ||
| 551 | |||
| 552 | return 0; | ||
| 553 | } | 544 | } |
| 554 | 545 | ||
| 555 | /** | 546 | /** |
| @@ -573,8 +564,6 @@ SYSCALL_DEFINE5(statx, | |||
| 573 | 564 | ||
| 574 | if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE) | 565 | if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE) |
| 575 | return -EINVAL; | 566 | return -EINVAL; |
| 576 | if (!access_ok(VERIFY_WRITE, buffer, sizeof(*buffer))) | ||
| 577 | return -EFAULT; | ||
| 578 | 567 | ||
| 579 | if (filename) | 568 | if (filename) |
| 580 | error = vfs_statx(dfd, filename, flags, &stat, mask); | 569 | error = vfs_statx(dfd, filename, flags, &stat, mask); |
| @@ -582,7 +571,8 @@ SYSCALL_DEFINE5(statx, | |||
| 582 | error = vfs_statx_fd(dfd, &stat, mask, flags); | 571 | error = vfs_statx_fd(dfd, &stat, mask, flags); |
| 583 | if (error) | 572 | if (error) |
| 584 | return error; | 573 | return error; |
| 585 | return statx_set_result(&stat, buffer); | 574 | |
| 575 | return cp_statx(&stat, buffer); | ||
| 586 | } | 576 | } |
| 587 | 577 | ||
| 588 | /* Caller is here responsible for sufficient locking (ie. inode->i_lock) */ | 578 | /* Caller is here responsible for sufficient locking (ie. inode->i_lock) */ |
