From nobody Mon Feb 9 18:21:21 2026 Received: from mout.gmx.net (mout.gmx.net [212.227.15.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2A82121D3E5; Thu, 13 Feb 2025 11:19:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.227.15.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739445583; cv=none; b=Mm7wzgpB8M1cLXSgM+BPRKxrh7xcKkxPiBaY0BlSOydGIvdD5Qryp9HxUlF9VkfFNmmG+Q8+S4bX3XiNqWrw8YC9cUKUnzN+Sel33ewdnwMe3fkEsWLVE2cjDFjcIUGDruLo0QDlZm0YQIUcEekFxrMoXuIFRoO90H2rKNvfJr0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739445583; c=relaxed/simple; bh=86qnJMX4eYbIgz0G92K/vkcN5G9fIRjY34mBXNoAZS4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ij1gswinD6x4KO0pLUnopXzoT2ItogqV9Qzn8wN3ZSuX0SqOSDb2CK1VuYIl5LvF9PRe+6wwjEYHUuqMkqouUXqQ8xA7sPA0AJuo32b+kAJY5j3cZAHXMgLn6AGWu49JKC4VND0J+e0iOZknPYYuCkYMS/cJn7G4xJOoIBgcAyk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=gmx.net; spf=pass smtp.mailfrom=gmx.net; dkim=pass (2048-bit key) header.d=gmx.net header.i=ps.report@gmx.net header.b=SjR12EMw; arc=none smtp.client-ip=212.227.15.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=gmx.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmx.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmx.net header.i=ps.report@gmx.net header.b="SjR12EMw" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmx.net; s=s31663417; t=1739445567; x=1740050367; i=ps.report@gmx.net; bh=86qnJMX4eYbIgz0G92K/vkcN5G9fIRjY34mBXNoAZS4=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:Message-ID:In-Reply-To: References:MIME-Version:Content-Transfer-Encoding:cc: content-transfer-encoding:content-type:date:from:message-id: mime-version:reply-to:subject:to; b=SjR12EMwBdIn1hCWSXGsT8QeQ+n48S83v1L++3SyGeZzL0dbsXAFnHm6f46zJFb3 GO/J0ZweAKmNclbjN7oBxkBW4zG7Pkoj2PctgbyYXDnX49+1t41tP+kPsaBzeoT7X QzqPY/9hLOQS7fn9hSO3sgWyOW5vxOMoLhwT+oyyU+vYQfhQimdBntSLEfgQYey3t hF0zL83HQRe2wYw/km3rM5LoePuD1t8jengrQArMzBAYEbM95vgZYI90vqvsH0NG6 mKMpZIuB6vVwjdVC7/a1SevGl2RqC0gQy0Z5ODmlAWqVAWN5jukSu8xFIGjNEUpgZ RWUboun3eWqr91mJ2Q== X-UI-Sender-Class: 724b4f7f-cbec-4199-ad4e-598c01a50d3a Received: from localhost.fritz.box ([82.135.81.197]) by mail.gmx.net (mrgmx004 [212.227.17.190]) with ESMTPSA (Nemesis) id 1MWzk3-1ttDQl3g7t-00TiP4; Thu, 13 Feb 2025 12:19:26 +0100 From: Peter Seiderer To: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Shuah Khan , Peter Seiderer , Thomas Gleixner , Artem Chernyshev , Nam Cao , Frederic Weisbecker Subject: [PATCH net-next v5 5/8] net: pktgen: fix access outside of user given buffer in pktgen_if_write() Date: Thu, 13 Feb 2025 12:19:17 +0100 Message-ID: <20250213111920.1439021-6-ps.report@gmx.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250213111920.1439021-1-ps.report@gmx.net> References: <20250213111920.1439021-1-ps.report@gmx.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:KAInXvzwf9tEbBu5iLA0XxDch3RxKmp+yLgaXMUF4wWwIf4vJPC s/9iVWk8jrQgzkAEcSQjVqR8AtMznTICb2IWE6xR3H3Q1Y2GsAczlZJUPXl5fQOcqa1rS0Y g66br2P/lJcmeQzXoIKkdrJ7sk3bBUEBvujBi5gvFjj7lEOS1FRBoIC1kpUZkraV4xTZXR3 RQwc1LjlnibxU96Q3upyg== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:AzbfCAwQTMg=;WVwwiffUNUi2V4V/LB6EuC+E6+L FNVedy+nSQBSpcFBZf155kydtB3IQua/vcl8njnxNwIXGo4W66pC21WoVHLKSU0+d2nHIvM4E WR3MOCJWhOBjmtE0NMVKyk0G2ljA+GdLmzZTvPD9aCw8yKHXpkLPTlsBps5aaCkRYFPu0WoDM 7ZsOQXBIQ/Um4veljMs2XH7KVUMOq2hBCPywlY3rifl4JzweUZm/97I6j8wV4ZPOcN2PGoBCb dJ3X6BUADENBzlpd6JGKHnTGC3MByAMdwi+MG/540g2oC9v1QowRdRNirsMbPIqBRVl4ybxS3 AXipU3cE4W0V89Xl3gUVtejjD0hKDUX0SiE9J82nnqjRuCNZHfaEgU43Jurk3Ry1T9ZTkTrYy 9P7LKMCcPxO9Uwl35RcTqZhDlqpE75G96EcmRUyT7/m3MAGvzzEfx5tMqb65kJSvVfyprGdeu ShIU1Jfhf97Cw1HAaGp0cv0fSBAGpYgOS/BecjTWvCEBbWWjL7N+tFV9qemtgU94bKFwODsQB hdrEnysm8wjbw0UhNhxEGEO8VeTvEb5a6CytHL5mLGvUoK7KutxTPzsVOS9/O8z1bYe4dg2qd gpDO/iJn90LY/j/FcTa5UqbWvFFcV7qia0Iyp445CruDGW3nbICd4lDmgs/VJe/bcUv7C4Y8i 0I7fzKJH0wGiLxiwDOSww7mhT2hSuEemmmlaASi5dAxIgG5dKA9pVzPfWHnQy3vmjJW7adnv1 u9EOzZslmJLahd9O6gy9Rx9yAGHva2QIAsmwxGYc72OHWdU3km4H7TMra6Q9FJwite7Txsl5j fXb7dCGSoqjVdwYDdM15mKIhD8jafnQ1Fosho7Rt4ZaoFfCVRMn1algmyrRUcqiTU2iswif7z /0OtwnU5g0x3To69Zsb/qeREiLp8d0TjwKbCNHZXfAf087vBW0xx/tLgkAAEeKQPK5F/oGljK J+DEiQ7qNSZg2HzHcUBWSqTqeCCDK/LVFcAz9esuC4JHbY5HL4uE7cddKnK0IJp4VRfpk/A/g n+PErj71L25Q/KlYlkcL1zj4zVfFUoGm8ojT2QgnVblDlVojZcsX7un2+0O7LB2RICDNvMDE2 8gxl6e+xCfAf5cHerwMLaHmHgvnnlWnL0RPTDqxKKiaTsSw+qQLYZvUEsiQ9IxuEo4wRzRcLL pyDNVWiDOhl4oWwvXawV4MwWj9sUa4R3iz+qNn0rQMlgXW8odH8yl6iJ6t3+FahwLPrkTiAIy vUBdL3dVaa3uaEQ3soJGcu3x/GTgHYd2kWVLdxLZaSYDI1RRm8qBga+r7cKKu+w7L12WX92FH SQiOuiSYjOvZS5ubQf7MYQy0ScEgF5LseVlJs37ooAr+ayj5p1FtDTbWTvh4DeyImq7EdcK5b vt57oOXGcbhtk8P4XpFi2Rp4X22Q/0nghTmM17bQY4WDjeNbPwP2oCH/+4Om/MpZclLLr1Dxg n86pECg== Content-Type: text/plain; charset="utf-8" Honour the user given buffer size for the hex32_arg(), num_arg(), strn_len(), get_imix_entries() and get_labels() calls (otherwise they will access memory outside of the user given buffer). Signed-off-by: Peter Seiderer Reviewed-by: Simon Horman --- Changes v4 -> v5 - split up patchset into part i/ii (suggested by Simon Horman) - add rev-by Simon Horman Changes v3 -> v4: - replace C99 comment (suggested by Paolo Abeni) - drop available characters check in strn_len() (suggested by Paolo Abeni) - factored out patch 'net: pktgen: align some variable declarations to the most common pattern' (suggested by Paolo Abeni) - factored out patch 'net: pktgen: remove extra tmp variable (re-use len instead)' (suggested by Paolo Abeni) - factored out patch 'net: pktgen: remove some superfluous variable initializing' (suggested by Paolo Abeni) - factored out patch 'net: pktgen: fix mpls maximum labels list parsing' (suggested by Paolo Abeni) - factored out 'net: pktgen: hex32_arg/num_arg error out in case no characters are available' (suggested by Paolo Abeni) - factored out 'net: pktgen: num_arg error out in case no valid character is parsed' (suggested by Paolo Abeni) Changes v2 -> v3: - no changes Changes v1 -> v2: - additional fix get_imix_entries() and get_labels() --- net/core/pktgen.c | 177 ++++++++++++++++++++++++++++++---------------- 1 file changed, 118 insertions(+), 59 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 9b63feb8a33e..780435a8e605 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -852,9 +852,10 @@ static ssize_t strn_len(const char __user *user_buffer= , size_t maxlen) * "size1,weight_1 size2,weight_2 ... size_n,weight_n" for example. */ static ssize_t get_imix_entries(const char __user *buffer, + size_t maxlen, struct pktgen_dev *pkt_dev) { - size_t i =3D 0; + size_t i =3D 0, max; ssize_t len; char c; =20 @@ -867,10 +868,13 @@ static ssize_t get_imix_entries(const char __user *bu= ffer, if (pkt_dev->n_imix_entries >=3D MAX_IMIX_ENTRIES) return -E2BIG; =20 - len =3D num_arg(&buffer[i], DEC_10_DIGITS, &size); + max =3D min(DEC_10_DIGITS, maxlen - i); + len =3D num_arg(&buffer[i], max, &size); if (len < 0) return len; i +=3D len; + if (i >=3D maxlen) + return -EINVAL; if (get_user(c, &buffer[i])) return -EFAULT; /* Check for comma between size_i and weight_i */ @@ -881,7 +885,8 @@ static ssize_t get_imix_entries(const char __user *buff= er, if (size < 14 + 20 + 8) size =3D 14 + 20 + 8; =20 - len =3D num_arg(&buffer[i], DEC_10_DIGITS, &weight); + max =3D min(DEC_10_DIGITS, maxlen - i); + len =3D num_arg(&buffer[i], max, &weight); if (len < 0) return len; if (weight <=3D 0) @@ -891,20 +896,23 @@ static ssize_t get_imix_entries(const char __user *bu= ffer, pkt_dev->imix_entries[pkt_dev->n_imix_entries].weight =3D weight; =20 i +=3D len; + pkt_dev->n_imix_entries++; + + if (i >=3D maxlen) + break; if (get_user(c, &buffer[i])) return -EFAULT; - i++; - pkt_dev->n_imix_entries++; } while (c =3D=3D ' '); =20 return i; } =20 -static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pk= t_dev) +static ssize_t get_labels(const char __user *buffer, + size_t maxlen, struct pktgen_dev *pkt_dev) { unsigned int n =3D 0; - size_t i =3D 0; + size_t i =3D 0, max; ssize_t len; char c; =20 @@ -915,17 +923,20 @@ static ssize_t get_labels(const char __user *buffer, = struct pktgen_dev *pkt_dev) if (n >=3D MAX_MPLS_LABELS) return -E2BIG; =20 - len =3D hex32_arg(&buffer[i], HEX_8_DIGITS, &tmp); + max =3D min(HEX_8_DIGITS, maxlen - i); + len =3D hex32_arg(&buffer[i], max, &tmp); if (len <=3D 0) return len; pkt_dev->labels[n] =3D htonl(tmp); if (pkt_dev->labels[n] & MPLS_STACK_BOTTOM) pkt_dev->flags |=3D F_MPLS_RND; i +=3D len; + n++; + if (i >=3D maxlen) + break; if (get_user(c, &buffer[i])) return -EFAULT; i++; - n++; } while (c =3D=3D ','); =20 pkt_dev->nr_labels =3D n; @@ -990,8 +1001,8 @@ static ssize_t pktgen_if_write(struct file *file, i =3D len; =20 /* Read variable name */ - - len =3D strn_len(&user_buffer[i], sizeof(name) - 1); + max =3D min(sizeof(name) - 1, count - i); + len =3D strn_len(&user_buffer[i], max); if (len < 0) return len; =20 @@ -1019,7 +1030,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "min_pkt_size")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1036,7 +1048,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "max_pkt_size")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1055,7 +1068,8 @@ static ssize_t pktgen_if_write(struct file *file, /* Shortcut for min =3D max */ =20 if (!strcmp(name, "pkt_size")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1075,7 +1089,8 @@ static ssize_t pktgen_if_write(struct file *file, if (pkt_dev->clone_skb > 0) return -EINVAL; =20 - len =3D get_imix_entries(&user_buffer[i], pkt_dev); + max =3D count - i; + len =3D get_imix_entries(&user_buffer[i], max, pkt_dev); if (len < 0) return len; =20 @@ -1086,7 +1101,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "debug")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1097,7 +1113,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "frags")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1107,7 +1124,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "delay")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1122,7 +1140,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "rate")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1137,7 +1156,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "ratep")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1152,7 +1172,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "udp_src_min")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1165,7 +1186,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "udp_dst_min")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1178,7 +1200,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "udp_src_max")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1191,7 +1214,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "udp_dst_max")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1204,7 +1228,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "clone_skb")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; /* clone_skb is not supported for netif_receive xmit_mode and @@ -1225,7 +1250,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "count")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1236,7 +1262,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "src_mac_count")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1250,7 +1277,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst_mac_count")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1264,7 +1292,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "burst")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1283,7 +1312,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "node")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1304,11 +1334,12 @@ static ssize_t pktgen_if_write(struct file *file, if (!strcmp(name, "xmit_mode")) { char f[32]; =20 - memset(f, 0, 32); - len =3D strn_len(&user_buffer[i], sizeof(f) - 1); + max =3D min(sizeof(f) - 1, count - i); + len =3D strn_len(&user_buffer[i], max); if (len < 0) return len; =20 + memset(f, 0, sizeof(f)); if (copy_from_user(f, &user_buffer[i], len)) return -EFAULT; i +=3D len; @@ -1344,11 +1375,12 @@ static ssize_t pktgen_if_write(struct file *file, char f[32]; char *end; =20 - memset(f, 0, 32); - len =3D strn_len(&user_buffer[i], sizeof(f) - 1); + max =3D min(sizeof(f) - 1, count - i); + len =3D strn_len(&user_buffer[i], max); if (len < 0) return len; =20 + memset(f, 0, 32); if (copy_from_user(f, &user_buffer[i], len)) return -EFAULT; i +=3D len; @@ -1393,7 +1425,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst_min") || !strcmp(name, "dst")) { - len =3D strn_len(&user_buffer[i], sizeof(pkt_dev->dst_min) - 1); + max =3D min(sizeof(pkt_dev->dst_min) - 1, count - i); + len =3D strn_len(&user_buffer[i], max); if (len < 0) return len; =20 @@ -1413,7 +1446,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst_max")) { - len =3D strn_len(&user_buffer[i], sizeof(pkt_dev->dst_max) - 1); + max =3D min(sizeof(pkt_dev->dst_max) - 1, count - i); + len =3D strn_len(&user_buffer[i], max); if (len < 0) return len; =20 @@ -1433,7 +1467,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst6")) { - len =3D strn_len(&user_buffer[i], sizeof(buf) - 1); + max =3D min(sizeof(buf) - 1, count - i); + len =3D strn_len(&user_buffer[i], max); if (len < 0) return len; =20 @@ -1456,7 +1491,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst6_min")) { - len =3D strn_len(&user_buffer[i], sizeof(buf) - 1); + max =3D min(sizeof(buf) - 1, count - i); + len =3D strn_len(&user_buffer[i], max); if (len < 0) return len; =20 @@ -1478,7 +1514,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst6_max")) { - len =3D strn_len(&user_buffer[i], sizeof(buf) - 1); + max =3D min(sizeof(buf) - 1, count - i); + len =3D strn_len(&user_buffer[i], max); if (len < 0) return len; =20 @@ -1499,7 +1536,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "src6")) { - len =3D strn_len(&user_buffer[i], sizeof(buf) - 1); + max =3D min(sizeof(buf) - 1, count - i); + len =3D strn_len(&user_buffer[i], max); if (len < 0) return len; =20 @@ -1522,7 +1560,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "src_min")) { - len =3D strn_len(&user_buffer[i], sizeof(pkt_dev->src_min) - 1); + max =3D min(sizeof(pkt_dev->src_min) - 1, count - i); + len =3D strn_len(&user_buffer[i], max); if (len < 0) return len; =20 @@ -1542,7 +1581,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "src_max")) { - len =3D strn_len(&user_buffer[i], sizeof(pkt_dev->src_max) - 1); + max =3D min(sizeof(pkt_dev->src_max) - 1, count - i); + len =3D strn_len(&user_buffer[i], max); if (len < 0) return len; =20 @@ -1562,7 +1602,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst_mac")) { - len =3D strn_len(&user_buffer[i], sizeof(valstr) - 1); + max =3D min(sizeof(valstr) - 1, count - i); + len =3D strn_len(&user_buffer[i], max); if (len < 0) return len; =20 @@ -1579,7 +1620,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "src_mac")) { - len =3D strn_len(&user_buffer[i], sizeof(valstr) - 1); + max =3D min(sizeof(valstr) - 1, count - i); + len =3D strn_len(&user_buffer[i], max); if (len < 0) return len; =20 @@ -1603,7 +1645,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "flows")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1617,7 +1660,8 @@ static ssize_t pktgen_if_write(struct file *file, } #ifdef CONFIG_XFRM if (!strcmp(name, "spi")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1628,7 +1672,8 @@ static ssize_t pktgen_if_write(struct file *file, } #endif if (!strcmp(name, "flowlen")) { - len =3D num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max =3D min(DEC_10_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1639,7 +1684,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "queue_map_min")) { - len =3D num_arg(&user_buffer[i], DEC_5_DIGITS, &value); + max =3D min(DEC_5_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1650,7 +1696,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "queue_map_max")) { - len =3D num_arg(&user_buffer[i], DEC_5_DIGITS, &value); + max =3D min(DEC_5_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1663,7 +1710,8 @@ static ssize_t pktgen_if_write(struct file *file, if (!strcmp(name, "mpls")) { unsigned int n, cnt; =20 - len =3D get_labels(&user_buffer[i], pkt_dev); + max =3D count - i; + len =3D get_labels(&user_buffer[i], max, pkt_dev); if (len < 0) return len; i +=3D len; @@ -1684,7 +1732,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "vlan_id")) { - len =3D num_arg(&user_buffer[i], DEC_4_DIGITS, &value); + max =3D min(DEC_4_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1711,7 +1760,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "vlan_p")) { - len =3D num_arg(&user_buffer[i], DEC_1_DIGITS, &value); + max =3D min(DEC_1_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1726,7 +1776,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "vlan_cfi")) { - len =3D num_arg(&user_buffer[i], DEC_1_DIGITS, &value); + max =3D min(DEC_1_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1741,7 +1792,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "svlan_id")) { - len =3D num_arg(&user_buffer[i], DEC_4_DIGITS, &value); + max =3D min(DEC_4_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1768,7 +1820,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "svlan_p")) { - len =3D num_arg(&user_buffer[i], DEC_1_DIGITS, &value); + max =3D min(DEC_1_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1783,7 +1836,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "svlan_cfi")) { - len =3D num_arg(&user_buffer[i], DEC_1_DIGITS, &value); + max =3D min(DEC_1_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 @@ -1799,7 +1853,9 @@ static ssize_t pktgen_if_write(struct file *file, =20 if (!strcmp(name, "tos")) { __u32 tmp_value; - len =3D hex32_arg(&user_buffer[i], HEX_2_DIGITS, &tmp_value); + + max =3D min(HEX_2_DIGITS, count - i); + len =3D hex32_arg(&user_buffer[i], max, &tmp_value); if (len < 0) return len; =20 @@ -1815,7 +1871,9 @@ static ssize_t pktgen_if_write(struct file *file, =20 if (!strcmp(name, "traffic_class")) { __u32 tmp_value; - len =3D hex32_arg(&user_buffer[i], HEX_2_DIGITS, &tmp_value); + + max =3D min(HEX_2_DIGITS, count - i); + len =3D hex32_arg(&user_buffer[i], max, &tmp_value); if (len < 0) return len; =20 @@ -1830,7 +1888,8 @@ static ssize_t pktgen_if_write(struct file *file, } =20 if (!strcmp(name, "skb_priority")) { - len =3D num_arg(&user_buffer[i], DEC_9_DIGITS, &value); + max =3D min(DEC_9_DIGITS, count - i); + len =3D num_arg(&user_buffer[i], max, &value); if (len < 0) return len; =20 --=20 2.48.1