From patchwork Fri Jan 17 14:16:12 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Seiderer X-Patchwork-Id: 13943396 Received: from mout.gmx.net (mout.gmx.net [212.227.17.20]) (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 CCCFB347CC; Fri, 17 Jan 2025 14:16:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.227.17.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737123397; cv=none; b=KVjZaKpHw90aM4/RyeMKkPUMhF6+4ab3I0bsGGfff62vbNhdAitARNGil6uq/g93dMF+e/ImXsquL6QpxSOQOMQMuOqOMoYDRBMkkiXZx9LO0P/SMBjeboK1S00pQya7qNkxTvrdoxa7ZrNWg7TgXCWH2VF7m0zC7wT47GGboQc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737123397; c=relaxed/simple; bh=cT+Ulo1/Xar64Mj2jDeX4PDN1R8bjGBg3hh1V8lSTv4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cXdoSuQt1gVESVS8Qy5nHKA6Y8OCMfEJUqfyS4oyefHIAZk2lFlv36Y4hCHS7mZTuD6EBDDUwKBeI40k6VNT+oxyCR/qZQfV4ZmdbwzQk0w3XbK6/UGD+RmCNKDBw3HTZOB3Lq9KdYqRHTZ7x7NrxL/bt0w/qMC5X+LVtu4b8ks= 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=FcMcZteg; arc=none smtp.client-ip=212.227.17.20 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="FcMcZteg" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmx.net; s=s31663417; t=1737123382; x=1737728182; i=ps.report@gmx.net; bh=cT+Ulo1/Xar64Mj2jDeX4PDN1R8bjGBg3hh1V8lSTv4=; 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=FcMcZtegApGR8taobktXfUnObEJzNZza436Ek/rkHRfLyQxsKs9KvVEo7UxqzJAO 7vxlDL1FrMaQurilezIgx2dfPyW6UbzdgeKh4wL60TK+lkyHZFoWFMN6BIphayj2O bp57G8bPc0Ee9uk+yjuytg8PgoPc3mcc+6dfAZxim54zITrkfXuyWEErAby6GMtAI kGQiQRMf6TnOrGws133kiu+d+tZW/XcUGMxjHXKuVVdGoodTOzbKJLY5jvvxwm7xE fuaztKHHUpPgOwecH6pGycsUFAEy1LSixur0VihJLDar96iJ3XnA3mJjSBxvNbPnA vPocdxkgdcXOVlwyig== X-UI-Sender-Class: 724b4f7f-cbec-4199-ad4e-598c01a50d3a Received: from localhost.fritz.box ([82.135.81.138]) by mail.gmx.net (mrgmx104 [212.227.17.168]) with ESMTPSA (Nemesis) id 1MAwbp-1tfdpX39TN-0075zW; Fri, 17 Jan 2025 15:16:22 +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 , =?utf-8?q?T?= =?utf-8?q?oke_H=C3=B8iland-J=C3=B8rgensen?= , Frederic Weisbecker , Artem Chernyshev , Nam Cao , Peter Seiderer Subject: [PATCH net-next v1 4/5] net: pktgen: fix access outside of user given buffer in pktgen_if_write() Date: Fri, 17 Jan 2025 15:16:12 +0100 Message-ID: <20250117141613.691452-5-ps.report@gmx.net> X-Mailer: git-send-email 2.48.0 In-Reply-To: <20250117141613.691452-1-ps.report@gmx.net> References: <20250117141613.691452-1-ps.report@gmx.net> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Provags-ID: V03:K1:c1KGeR0MUtlmrc5YvOoEc15EahOuqq4XgfYWa8rkKl42Fw5m+Be TWBzh+HQ+fioNQVJymwugc9qvNHvLeixncVOdyD3W49IKVL5J+7+6EkZJyHShSpkK9hprGu w1bXJ3BTj3Skq4jLH/Fgw2u0Y3Joyjg5XnIMhvVB319bpYj4wmwqlmwRGhMlwf1K7jlrnfD 4qDxoEsSTeyb8NEoRADpQ== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:HT+kgfTzmrM=;dIEVUmMlMg4wbC6jrt4nGrUHkfN KTHWytsVrY3UNlrg8iIsL2RDdxuhF4xZr0U+tgZSc+N9owZC3hVLXyVPC5opDzAWOckBSk9wo 1LQfXNfYETLr200tvrELCQapL+SgB/w+ql6mRxUMZe9Xem6w5Ut3ESEiJWpXT5Le/dulW0laZ 2QbIBhy1lwZQ4Bc9+Q5l1XaJvXdafxIPLAD8+3sbDH/ZK+4q4UIKdzwfFPxbmxKNMBmvXeBfa gM3caErpfQUWArXDwMaXngk0YA0zHypeKvwO4DTfX0qwbzbLGMh0a3AsVyvuU4zgcGduAFogP GK8YYw9VTNa/4yzVWWfuwPqGMQj+Z64ymqzzdWgIAecHQFGPv86c8yiVyjgjj27gsNssCXTHU 21iT3FL4hQJTJ00HNTI/OrU6UqGiWV5Waak9GRcsjKxFV59uTbpPXNtP+FbZHcLMs5Zy0OW9D 1biZQuRBrGgeDO5WMu8oOgLp2LEd44LTV7ren8ljFze6afngxa9nPit9wgv31pW50WY7HU6Aq GymLpMbx2My+tee0JrTTMyUnJP/Q1UKVNX0ahzvtYeKZxZLee3+LI6toX2s8omiaeZ1yhKm5F KgjDA9JvmdEG2EIbejBIzjUdX9l+4/nI8cYmFHBxlWh7RNa1GiXAmYy4Lxh8AWgURf9FwfHmN mcwBv4aaDV6IZh7KSS2U5QCPs2UBhOGM4MahUMoChnsu2tCaowI7V0XRscrKnVCMuU9qtgFhk NuAjUexZfyxURvKep/UKob6CVNGFQqiWVCJNgcUCVomQ+yXFEJf8gR+3Xq7Zif/EB9Z04z4b8 KD01YPt4pyZH5VY6gjhjOPnJWqWpOKipwh7WzHKAN+XXYtcYSIzFh4L+ppnpF1WfVWAIYX72N tbEHQNKj015jE444gLmWpa4v+Rcm6Zu+trNG6fGgCw+gXXdAb5Ks+E48b8uX49sigWeosA6CI 2LJr63J+JEEZYrxjdAyBmmjEjOUXE/Mcen4Ed/H6osq0/KhFRrIzEcNtIvl/5SvRLn8h8Px+m /GNQUSsEG9sOBD4UJLNrZ99WRj7EHjH+cyFGY5WERrF1ddv2DVWat6k3+u/Kor9f5pA8x5rAc ydx7xGKr2d12Nlwn9vg/l42y9tajLcSAXjIvMaLwRQAdlK7aNY6wevhBcqydZipdj8oH+lWtV ptrK6npj3RaEysnfv6158wHOfxtUyNT3anNfa/6mBaA== Honour the user given buffer size for the hex32_arg(), num_arg() and strn_len() calls (otherwise they will access memory outside of the user given buffer). In all three functions error out in case no characters a available (maxlen = 0), in num_arg() additional error out in case no valid character is parsed. Additional remove some superfluous variable initializing and align some variable declarations to the most common pattern. Signed-off-by: Peter Seiderer --- net/core/pktgen.c | 196 ++++++++++++++++++++++++++++++---------------- 1 file changed, 128 insertions(+), 68 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 9536f9c4d9ef..5f54a056fa7c 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -750,6 +750,9 @@ static int hex32_arg(const char __user *user_buffer, unsigned long maxlen, int i = 0; *num = 0; + if (!maxlen) + return -EINVAL; + for (; i < maxlen; i++) { int value; char c; @@ -796,6 +799,9 @@ static long num_arg(const char __user *user_buffer, unsigned long maxlen, int i; *num = 0; + if (!maxlen) + return -EINVAL; + for (i = 0; i < maxlen; i++) { char c; if (get_user(c, &user_buffer[i])) @@ -803,6 +809,9 @@ static long num_arg(const char __user *user_buffer, unsigned long maxlen, if ((c >= '0') && (c <= '9')) { *num *= 10; *num += c - '0'; + } else if (i == 0) { + // no valid character parsed, error out + return -EINVAL; } else break; } @@ -813,6 +822,9 @@ static int strn_len(const char __user * user_buffer, unsigned int maxlen) { int i; + if (!maxlen) + return -EINVAL; + for (i = 0; i < maxlen; i++) { char c; if (get_user(c, &user_buffer[i])) @@ -839,11 +851,10 @@ static int strn_len(const char __user * user_buffer, unsigned int maxlen) * "size1,weight_1 size2,weight_2 ... size_n,weight_n" for example. */ static ssize_t get_imix_entries(const char __user *buffer, + unsigned int maxlen, struct pktgen_dev *pkt_dev) { - const int max_digits = 10; - int i = 0; - long len; + int i = 0, max, len; char c; pkt_dev->n_imix_entries = 0; @@ -855,7 +866,8 @@ static ssize_t get_imix_entries(const char __user *buffer, if (pkt_dev->n_imix_entries >= MAX_IMIX_ENTRIES) return -E2BIG; - len = num_arg(&buffer[i], max_digits, &size); + max = min(10, maxlen - i); + len = num_arg(&buffer[i], max, &size); if (len < 0) return len; i += len; @@ -869,7 +881,8 @@ static ssize_t get_imix_entries(const char __user *buffer, if (size < 14 + 20 + 8) size = 14 + 20 + 8; - len = num_arg(&buffer[i], max_digits, &weight); + max = min(10, maxlen - i); + len = num_arg(&buffer[i], max, &weight); if (len < 0) return len; if (weight <= 0) @@ -889,18 +902,19 @@ static ssize_t get_imix_entries(const char __user *buffer, return i; } -static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev) +static ssize_t get_labels(const char __user *buffer, int maxlen, struct pktgen_dev *pkt_dev) { unsigned int n = 0; char c; - ssize_t i = 0; - int len; + int i = 0, max, len; pkt_dev->nr_labels = 0; do { __u32 tmp; - len = hex32_arg(&buffer[i], 8, &tmp); - if (len <= 0) + + max = min(8, maxlen - i); + len = hex32_arg(&buffer[i], max, &tmp); + if (len < 0) return len; pkt_dev->labels[n] = htonl(tmp); if (pkt_dev->labels[n] & MPLS_STACK_BOTTOM) @@ -957,7 +971,6 @@ static ssize_t pktgen_if_write(struct file *file, char name[16], valstr[32]; unsigned long value = 0; char *pg_result = NULL; - int tmp = 0; char buf[128]; pg_result = &(pkt_dev->result[0]); @@ -967,17 +980,16 @@ static ssize_t pktgen_if_write(struct file *file, return -EINVAL; } - max = count; - tmp = count_trail_chars(user_buffer, max); - if (tmp < 0) { + len = count_trail_chars(user_buffer, count); + if (len < 0) { pr_warn("illegal format\n"); - return tmp; + return len; } - i = tmp; + i = len; /* Read variable name */ - - len = strn_len(&user_buffer[i], sizeof(name) - 1); + max = min(sizeof(name) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; @@ -1005,7 +1017,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "min_pkt_size")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1022,7 +1035,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "max_pkt_size")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1041,7 +1055,8 @@ static ssize_t pktgen_if_write(struct file *file, /* Shortcut for min = max */ if (!strcmp(name, "pkt_size")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1061,7 +1076,8 @@ static ssize_t pktgen_if_write(struct file *file, if (pkt_dev->clone_skb > 0) return -EINVAL; - len = get_imix_entries(&user_buffer[i], pkt_dev); + max = count - i; + len = get_imix_entries(&user_buffer[i], max, pkt_dev); if (len < 0) return len; @@ -1072,7 +1088,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "debug")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1083,7 +1100,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "frags")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1093,7 +1111,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "delay")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1108,7 +1127,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "rate")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1123,7 +1143,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "ratep")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1138,7 +1159,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "udp_src_min")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1151,7 +1173,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "udp_dst_min")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1164,7 +1187,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "udp_src_max")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1177,7 +1201,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "udp_dst_max")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1190,7 +1215,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "clone_skb")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; /* clone_skb is not supported for netif_receive xmit_mode and @@ -1211,7 +1237,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "count")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1222,7 +1249,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "src_mac_count")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1236,7 +1264,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst_mac_count")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1250,7 +1279,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "burst")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1269,7 +1299,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "node")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1290,11 +1321,12 @@ static ssize_t pktgen_if_write(struct file *file, if (!strcmp(name, "xmit_mode")) { char f[32]; - memset(f, 0, 32); - len = strn_len(&user_buffer[i], sizeof(f) - 1); + max = min(sizeof(f) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; + memset(f, 0, sizeof(f)); if (copy_from_user(f, &user_buffer[i], len)) return -EFAULT; i += len; @@ -1330,11 +1362,12 @@ static ssize_t pktgen_if_write(struct file *file, char f[32]; char *end; - memset(f, 0, 32); - len = strn_len(&user_buffer[i], sizeof(f) - 1); + max = min(sizeof(f) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; + memset(f, 0, 32); if (copy_from_user(f, &user_buffer[i], len)) return -EFAULT; i += len; @@ -1379,7 +1412,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst_min") || !strcmp(name, "dst")) { - len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_min) - 1); + max = min(sizeof(pkt_dev->dst_min) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; @@ -1399,7 +1433,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst_max")) { - len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_max) - 1); + max = min(sizeof(pkt_dev->dst_max) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; @@ -1419,7 +1454,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst6")) { - len = strn_len(&user_buffer[i], sizeof(buf) - 1); + max = min(sizeof(buf) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; @@ -1442,7 +1478,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst6_min")) { - len = strn_len(&user_buffer[i], sizeof(buf) - 1); + max = min(sizeof(buf) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; @@ -1464,7 +1501,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst6_max")) { - len = strn_len(&user_buffer[i], sizeof(buf) - 1); + max = min(sizeof(buf) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; @@ -1485,7 +1523,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "src6")) { - len = strn_len(&user_buffer[i], sizeof(buf) - 1); + max = min(sizeof(buf) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; @@ -1508,7 +1547,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "src_min")) { - len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_min) - 1); + max = min(sizeof(pkt_dev->src_min) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; @@ -1528,7 +1568,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "src_max")) { - len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_max) - 1); + max = min(sizeof(pkt_dev->src_max) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; @@ -1548,7 +1589,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst_mac")) { - len = strn_len(&user_buffer[i], sizeof(valstr) - 1); + max = min(sizeof(valstr) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; @@ -1565,7 +1607,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "src_mac")) { - len = strn_len(&user_buffer[i], sizeof(valstr) - 1); + max = min(sizeof(valstr) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; @@ -1589,7 +1632,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "flows")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1603,7 +1647,8 @@ static ssize_t pktgen_if_write(struct file *file, } #ifdef CONFIG_XFRM if (!strcmp(name, "spi")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1614,7 +1659,8 @@ static ssize_t pktgen_if_write(struct file *file, } #endif if (!strcmp(name, "flowlen")) { - len = num_arg(&user_buffer[i], 10, &value); + max = min(10, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1625,7 +1671,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "queue_map_min")) { - len = num_arg(&user_buffer[i], 5, &value); + max = min(5, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1636,7 +1683,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "queue_map_max")) { - len = num_arg(&user_buffer[i], 5, &value); + max = min(5, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1649,7 +1697,8 @@ static ssize_t pktgen_if_write(struct file *file, if (!strcmp(name, "mpls")) { unsigned int n, cnt; - len = get_labels(&user_buffer[i], pkt_dev); + max = count - i; + len = get_labels(&user_buffer[i], max, pkt_dev); if (len < 0) return len; i += len; @@ -1670,7 +1719,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "vlan_id")) { - len = num_arg(&user_buffer[i], 4, &value); + max = min(4, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1697,7 +1747,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "vlan_p")) { - len = num_arg(&user_buffer[i], 1, &value); + max = min(1, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1712,7 +1763,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "vlan_cfi")) { - len = num_arg(&user_buffer[i], 1, &value); + max = min(1, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1727,7 +1779,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "svlan_id")) { - len = num_arg(&user_buffer[i], 4, &value); + max = min(4, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1754,7 +1807,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "svlan_p")) { - len = num_arg(&user_buffer[i], 1, &value); + max = min(1, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1769,7 +1823,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "svlan_cfi")) { - len = num_arg(&user_buffer[i], 1, &value); + max = min(1, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1784,8 +1839,10 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "tos")) { - __u32 tmp_value = 0; - len = hex32_arg(&user_buffer[i], 2, &tmp_value); + __u32 tmp_value; + + max = min(2, count - i); + len = hex32_arg(&user_buffer[i], max, &tmp_value); if (len < 0) return len; @@ -1800,8 +1857,10 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "traffic_class")) { - __u32 tmp_value = 0; - len = hex32_arg(&user_buffer[i], 2, &tmp_value); + __u32 tmp_value; + + max = min(2, count - i); + len = hex32_arg(&user_buffer[i], max, &tmp_value); if (len < 0) return len; @@ -1816,7 +1875,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "skb_priority")) { - len = num_arg(&user_buffer[i], 9, &value); + max = min(9, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len;