nfsd: enforce upper limit for namelen in __cld_pipe_inprogress_downcall()
authorScott Mayhew <smayhew@redhat.com>
Mon, 9 Sep 2024 20:28:54 +0000 (16:28 -0400)
committerChuck Lever <chuck.lever@oracle.com>
Fri, 20 Sep 2024 23:31:35 +0000 (19:31 -0400)
This patch is intended to go on top of "nfsd: return -EINVAL when
namelen is 0" from Li Lingfeng.  Li's patch checks for 0, but we should
be enforcing an upper bound as well.

Note that if nfsdcld somehow gets an id > NFS4_OPAQUE_LIMIT in its
database, it'll truncate it to NFS4_OPAQUE_LIMIT when it does the
downcall anyway.

Signed-off-by: Scott Mayhew <smayhew@redhat.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfs4recover.c

index 530686f..b7d61eb 100644 (file)
@@ -809,8 +809,8 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg,
                        ci = &cmsg->cm_u.cm_clntinfo;
                        if (get_user(namelen, &ci->cc_name.cn_len))
                                return -EFAULT;
-                       if (!namelen) {
-                               dprintk("%s: namelen should not be zero", __func__);
+                       if (namelen == 0 || namelen > NFS4_OPAQUE_LIMIT) {
+                               dprintk("%s: invalid namelen (%u)", __func__, namelen);
                                return -EINVAL;
                        }
                        name.data = memdup_user(&ci->cc_name.cn_id, namelen);
@@ -835,8 +835,8 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg,
                        cnm = &cmsg->cm_u.cm_name;
                        if (get_user(namelen, &cnm->cn_len))
                                return -EFAULT;
-                       if (!namelen) {
-                               dprintk("%s: namelen should not be zero", __func__);
+                       if (namelen == 0 || namelen > NFS4_OPAQUE_LIMIT) {
+                               dprintk("%s: invalid namelen (%u)", __func__, namelen);
                                return -EINVAL;
                        }
                        name.data = memdup_user(&cnm->cn_id, namelen);