]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/qeth: validate user buffer length in SNMP and ARP query ioctls
authorHidayath Khan <hidayath@linux.ibm.com>
Thu, 30 Jul 2026 14:22:16 +0000 (16:22 +0200)
committerJakub Kicinski <kuba@kernel.org>
Tue, 4 Aug 2026 01:31:05 +0000 (18:31 -0700)
qeth_snmp_command() and qeth_l3_arp_query() allocate a buffer sized by
a user-supplied length (udata_len) without checking a lower bound, then
set udata_offset to a fixed non-zero value and pass both to a reply
callback. The callback bounds-checks the copy with

        if ((udata_len - udata_offset) < len)

Both fields are u32, so a udata_len smaller than udata_offset makes the
subtraction wrap and the check pass, and the following memcpy() writes
past the allocation. A udata_len of 0 also yields ZERO_SIZE_PTR from
kzalloc(), which the existing NULL check does not catch.

Reject buffers smaller than udata_offset before allocating, so the
callback subtraction can no longer underflow.

Fixes: 4a71df50047f ("qeth: new qeth device driver")
Cc: stable@vger.kernel.org
Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
Signed-off-by: Hidayath Khan <hidayath@linux.ibm.com>
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260730142216.218309-1-hidayath@linux.ibm.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l3_main.c

index f18eed9df3c7a85f692fb6708c83c1cbf23e6acf..c3257b213360cc8d52d0d533f14e87b4f94455c4 100644 (file)
@@ -4710,6 +4710,9 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata)
        if (req_len > QETH_BUFSIZE)
                return -EINVAL;
 
+       if (qinfo.udata_len < sizeof(struct qeth_snmp_ureq_hdr))
+               return -EINVAL;
+
        iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL, req_len);
        if (!iob)
                return -ENOMEM;
index 1542bfc9f561bfaa82640089f3b72cc3fc83c2ed..f1ac9950dcb4eb2fa0447788ecd47a75bd4ac8df 100644 (file)
@@ -1415,6 +1415,11 @@ static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata)
                rc = -EFAULT;
                goto out;
        }
+
+       if (qinfo.udata_len < QETH_QARP_ENTRIES_OFFSET) {
+               rc = -EINVAL;
+               goto out;
+       }
        qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL);
        if (!qinfo.udata) {
                rc = -ENOMEM;