summaryrefslogtreecommitdiff
path: root/fs/namespace.c
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2023-11-29 12:27:15 +0100
committerChristian Brauner <brauner@kernel.org>2023-12-14 11:49:17 +0100
commit35e27a5744131996061e6e323f1bcb4c827ae867 (patch)
treeb370f212ae31530a2cdc740b9899ed6613213e95 /fs/namespace.c
parentd8b0f5465012538cc4bb10ddc4affadbab73465b (diff)
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.c34
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;