From patchwork Mon Feb 3 17:01:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Seiderer X-Patchwork-Id: 13957850 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 BC56F20E6F9; Mon, 3 Feb 2025 17:02:41 +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=1738602164; cv=none; b=cakQdl8usZCm+L1kZkiABwgPYAqeplWBbUBHRYreTlhIoQbNm5bcivDXBuOZS+JBgrGIRRNoauazKJ3Qlj+WLXiUAlcYA4lKwliH/rafPE/AmLErm0GbkwH4h0eHIdpuwSsCKWcw/0lT952bckCpRH9IL+YC1gm7hB9OMkFh914= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738602164; c=relaxed/simple; bh=gIsg7jK8C+197Jjkn3kn9vrIIwtpeLi9nhpytYpBq7A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GbKKzF3uIUE+SFwLNxuNZJIcOeq5KG5XasDsnIkok20otcwDT5gcI5w2pGlvMNse0dmrK+IXDQLDa1pir/Q6F9g7P4XPx1V4gf+35n+V1AJDAJt/HZpXhQF/K27m0Aktuu1A8iaXaNqJxlwk9wsjr55lvDr1VyG62x3uaGOuPvM= 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=dnaNJKJj; 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="dnaNJKJj" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmx.net; s=s31663417; t=1738602151; x=1739206951; i=ps.report@gmx.net; bh=gIsg7jK8C+197Jjkn3kn9vrIIwtpeLi9nhpytYpBq7A=; 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=dnaNJKJjPflgcIY6qPDywIX39PU7GOBkh6+wLs1qRXvto6Jw0hgonf8iSrJk79Lb FVIKr6P6AT1W06OAau0yj40EabFD/boZsqNPwJUH+lOF0XSqEtmzX5tVfiqKnHUHY JGj+nO30uW8GVY7mG93Dgcy8UN1k4KTuyoOxNWTcPYRhWNueChqFLXqGj5KC/EOhe XGSXICBwAKYWl9h8vGJpTUOEIMWlV+STSDMP4B2MawbDL+mhsy4pdvTInlGQVVPDk 0R19rIMgz6FL+5Vdh9okablmtL2VP0vyjDdrb8yvFbPhbAfqhnf6CJ+KlMoVBFJsj x5u2V8FBU8kHhkKGfw== X-UI-Sender-Class: 724b4f7f-cbec-4199-ad4e-598c01a50d3a Received: from localhost.fritz.box ([82.135.81.54]) by mail.gmx.net (mrgmx005 [212.227.17.190]) with ESMTPSA (Nemesis) id 1MBm1e-1tZSzS3WFY-008Qt2; Mon, 03 Feb 2025 18:02:30 +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 , Nam Cao , Thomas Gleixner , Frederic Weisbecker , Artem Chernyshev , Peter Seiderer Subject: [PATCH net-next v3 08/10] net: pktgen: fix access outside of user given buffer in pktgen_if_write() Date: Mon, 3 Feb 2025 18:01:59 +0100 Message-ID: <20250203170201.1661703-9-ps.report@gmx.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250203170201.1661703-1-ps.report@gmx.net> References: <20250203170201.1661703-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:TZvGL8RuRkZXzSs4WSna35w8tmgyDd7Brzv6k66bZbJpUrr05n9 gqcUOTM3x1Lfza7+sojZKEjdFfCCBUY1vQsomDigU+261m38GircsHTmUczdI4xJHOIC7Y2 L5A7mKsD4VhuH93H2TzlbSHdDs8KTLQrMfhqz+lNUXcj8Ij+y2JZbsjYIcsclqGkca86luI ZvxuLJjptHiR2nYvl+zkA== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:YputBL6VmZg=;qVYO8TSHMJ4+S0Rw/kVXCdnBu7c Nu1GhTA9dZ7tQfnfGy0Hl83LTd3t65vmMesO7jJr4E300R8Oi+KomouWLRUOKaAEY5VEm2qzz bPgrhL2kv3kPZJS+3+qazkLomBZyaK31dqQCIox4dV4YSsuIfs8Xx07eoIaRm8Xl7LcZuQSE8 QVDpquEM2ZVVC4EVsJDRCF0cxniy38m0CSqXwHATzhp9oSGTKimQBvbh+liKb+t9X03q3Uh0k s3wzfffFf0USYAGFvoPM6CZ36CsI2ZcWsKgauaDJRotg6CMu2tYVG5VLTfdrm/3Q+G1hLt63p 3s1Wxzt92UstlCXSBCYf96pD463VbLp9YUcEUYSyBy+Exop5qPxHwJ8Lvikoef2k6qhmhsI/W R2LEvtX3JcAsartFtpZ011J11I7uF++FjMyBKhqFBCgcWxC4GL018SX7ZJNkJ5LEmxDXQeP8Y FCAPmXFknQr6qYsc+G58rUI6muU0N6uHjZbkmx7knGIr+I7TF5Q46X5FNiG5hBFJieHswWvbt PYykoST5Fx3eLMwG7Y0rFWfsi4GvWi57QmHZT0ByE6C8sFvJK/XBwOj8CWAN5jO8+TUgTUOlh pf4keD4F/K0uBqqClToZEtoU4uqJyt8RnXa+bNBrI8twCQGfvbFwob6bZWq3ie2974dx3VpbS LdNJc7clObUfcyepKQGuJsHt5zQYwHv5GZcAexbrG8Z/G3S7J6Zo3dH2gG4ag879Lu1nt5wsp XVGg5VUyK5I/dhnSk1hnKSzZcW7X3FOxycZDTooYFcB+ssGiB5lwvzfJ2opOfbbrPlF5os/JV C3QoQa+829ZywQR9/Y1agx8xtR/kXFrUlTus1PZFpNgyM4CTrCVFA9+aLcSP9GYhIm9HaEDz0 E8WBqoZTdyh8PJ6F76lus5ubP6m4lDQcxUaj37xBPvbPjUKo0NgSw0CStFGBGzDr6JmdX01ue ci8a16YN41F6LsmCJisV2EF4Z/nI2JMAYyJd4A3WbS75zRxOEAx49++I8u1A7fwVixKMSMR+W GwEpyglgogCOPzFVIao1jWmcR1349bIEp+6ee98L67I2zcMTWKjv5Af2t6FbZAaBS70Ujba5p kELZCd3Xtqk6hWE4x9SpGpwFEqIhsUvlTZOxmqv80ugVvHKl7uHlheSouLmyq3ePXnDt+ACdB wZmTxZ2SnFuUuZPWCsltTP4O7iRbC+H0FJJn5xd/rnoCcpTIPZC83NArrNQPnEK3i4O7OaEOv vHWkPoGLejdYfoHktAdr9QYxbmCnDYSHi991dB8TM1MbQXT/lkyNAcVoMbUQMjsCjSmu4EuJJ aQ2Z818vRCqAmiyckfgjX5jKfIknabES+m6bMpo5TzPX80= 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). In hex32_arg(), num_arg(), strn_len() error out in case no characters are available (maxlen = 0), in num_arg() additional error out in case no valid character is parsed. In get_labels() additional enable parsing labels up to MAX_IMIX_ENTRIES instead of (MAX_IMIX_ENTRIES - 1). Additional remove some superfluous variable initializing and align some variable declarations to the most common pattern. Signed-off-by: Peter Seiderer --- Changes v2 -> v3: - no changes Changes v1 -> v2: - additional fix get_imix_entries() and get_labels() --- net/core/pktgen.c | 211 ++++++++++++++++++++++++++++++---------------- 1 file changed, 139 insertions(+), 72 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 55064713223e..6675375c052c 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -752,6 +752,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; @@ -799,6 +802,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])) @@ -806,6 +812,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; } @@ -816,6 +825,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])) @@ -842,11 +854,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; @@ -858,10 +869,13 @@ 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; + if (i >= maxlen) + return -EINVAL; if (get_user(c, &buffer[i])) return -EFAULT; /* Check for comma between size_i and weight_i */ @@ -872,7 +886,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) @@ -882,39 +897,45 @@ static ssize_t get_imix_entries(const char __user *buffer, pkt_dev->imix_entries[pkt_dev->n_imix_entries].weight = weight; i += len; + pkt_dev->n_imix_entries++; + + if (i >= maxlen) + break; if (get_user(c, &buffer[i])) return -EFAULT; - i++; - pkt_dev->n_imix_entries++; } while (c == ' '); 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 (n >= MAX_MPLS_LABELS) + return -E2BIG; + + 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) pkt_dev->flags |= F_MPLS_RND; i += len; + n++; + if (i >= maxlen) + break; if (get_user(c, &buffer[i])) return -EFAULT; i++; - n++; - if (n >= MAX_MPLS_LABELS) - return -E2BIG; } while (c == ','); pkt_dev->nr_labels = n; @@ -960,7 +981,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]); @@ -970,17 +990,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; @@ -1008,7 +1027,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; @@ -1025,7 +1045,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; @@ -1044,7 +1065,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; @@ -1064,7 +1086,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; @@ -1075,7 +1098,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; @@ -1086,7 +1110,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; @@ -1096,7 +1121,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; @@ -1111,7 +1137,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; @@ -1126,7 +1153,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; @@ -1141,7 +1169,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; @@ -1154,7 +1183,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; @@ -1167,7 +1197,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; @@ -1180,7 +1211,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; @@ -1193,7 +1225,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 @@ -1214,7 +1247,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; @@ -1225,7 +1259,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; @@ -1239,7 +1274,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; @@ -1253,7 +1289,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; @@ -1272,7 +1309,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; @@ -1293,11 +1331,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; @@ -1333,11 +1372,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; @@ -1382,7 +1422,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; @@ -1402,7 +1443,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; @@ -1422,7 +1464,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; @@ -1445,7 +1488,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; @@ -1467,7 +1511,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; @@ -1488,7 +1533,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; @@ -1511,7 +1557,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; @@ -1531,7 +1578,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; @@ -1551,7 +1599,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; @@ -1568,7 +1617,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; @@ -1592,7 +1642,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; @@ -1606,7 +1657,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; @@ -1617,7 +1669,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; @@ -1628,7 +1681,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; @@ -1639,7 +1693,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; @@ -1652,7 +1707,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; @@ -1673,7 +1729,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; @@ -1700,7 +1757,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; @@ -1715,7 +1773,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; @@ -1730,7 +1789,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; @@ -1757,7 +1817,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; @@ -1772,7 +1833,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; @@ -1787,8 +1849,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; @@ -1803,8 +1867,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; @@ -1819,7 +1885,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;