]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
fs: keep struct mnt_id_req extensible
authorChristian Brauner <brauner@kernel.org>
Wed, 29 Nov 2023 11:27:15 +0000 (12:27 +0100)
committerChristian Brauner <brauner@kernel.org>
Thu, 14 Dec 2023 10:49:17 +0000 (11:49 +0100)
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>
fs/namespace.c
include/uapi/linux/mount.h

index 873185b8a84bea47ad1bc5dd1733fbc1f1fd4431..918e8f89ce3559b1adb0c6c2089e98959a052b17 100644 (file)
@@ -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;
 
index dc9a0112d81918b377b02a25249a33188d3e6f7c..ad5478dbad007341f70a8816aa506216ffea89ec 100644 (file)
@@ -184,10 +184,15 @@ struct statmount {
  * For listmount(2) @param represents the last listed mount id (or zero).
  */
 struct mnt_id_req {
+       __u32 size;
+       __u32 spare;
        __u64 mnt_id;
        __u64 param;
 };
 
+/* List of all mnt_id_req versions. */
+#define MNT_ID_REQ_SIZE_VER0   24 /* sizeof first published struct */
+
 /*
  * @mask bits for statmount(2)
  */