diff options
author | Christian Brauner <brauner@kernel.org> | 2023-11-29 12:27:15 +0100 |
---|---|---|
committer | Christian Brauner <brauner@kernel.org> | 2023-12-14 11:49:17 +0100 |
commit | 35e27a5744131996061e6e323f1bcb4c827ae867 (patch) | |
tree | b370f212ae31530a2cdc740b9899ed6613213e95 /fs/namespace.c | |
parent | wire up syscalls for statmount/listmount (diff) | |
download | linux-35e27a5744131996061e6e323f1bcb4c827ae867.tar.xz linux-35e27a5744131996061e6e323f1bcb4c827ae867.zip |
fs: keep struct mnt_id_req extensible
Make it extensible so that we have the liberty to reuse it in future
mount-id based apis. Treat zero size as the first published struct.
Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 873185b8a84b..918e8f89ce35 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -4956,6 +4956,30 @@ static int prepare_kstatmount(struct kstatmount *ks, struct mnt_id_req *kreq, return 0; } +static int copy_mnt_id_req(const struct mnt_id_req __user *req, + struct mnt_id_req *kreq) +{ + int ret; + size_t usize; + + BUILD_BUG_ON(sizeof(struct mnt_id_req) != MNT_ID_REQ_SIZE_VER0); + + ret = get_user(usize, &req->size); + if (ret) + return -EFAULT; + if (unlikely(usize > PAGE_SIZE)) + return -E2BIG; + if (unlikely(usize < MNT_ID_REQ_SIZE_VER0)) + return -EINVAL; + memset(kreq, 0, sizeof(*kreq)); + ret = copy_struct_from_user(kreq, sizeof(*kreq), req, usize); + if (ret) + return ret; + if (kreq->spare != 0) + return -EINVAL; + return 0; +} + SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req, struct statmount __user *, buf, size_t, bufsize, unsigned int, flags) @@ -4970,8 +4994,9 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req, if (flags) return -EINVAL; - if (copy_from_user(&kreq, req, sizeof(kreq))) - return -EFAULT; + ret = copy_mnt_id_req(req, &kreq); + if (ret) + return ret; retry: ret = prepare_kstatmount(&ks, &kreq, buf, bufsize, seq_size); @@ -5052,8 +5077,9 @@ SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req, if (flags) return -EINVAL; - if (copy_from_user(&kreq, req, sizeof(kreq))) - return -EFAULT; + ret = copy_mnt_id_req(req, &kreq); + if (ret) + return ret; mnt_id = kreq.mnt_id; last_mnt_id = kreq.param; |