From patchwork Wed Feb 5 13:11:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Seiderer X-Patchwork-Id: 13961030 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 C22A21DDA15; Wed, 5 Feb 2025 13:12:16 +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=1738761142; cv=none; b=YyFIrLp4AzFM2Uiqsh96+FvgEeiAM0fEPn0bqzGkK1ilyNWOFAf8XSeFy0nSWvLBzlZjYe90gplBY4NLyvMQpo6N+0HVsDr+9OZiJKVZHEBTn17jK5uE+iv83Z+UEqIqmb7NRfetJD4t8q+wiOTHG8XKP0XZ3L6GxLQIlzSqjqY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738761142; c=relaxed/simple; bh=Y/3V+emCRXVxI/5pFQD5uxe35BuduQQqfM0vaJoQW90=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZVx8P1yJCAuxpj9bIAAxHQIGQiOFYOJXy9mrRM20nqnO4ReLrRuw/N1UxE5hN/yOPSSuaK1NAfe+edv+5+u0MqGLeIVoirpbkozxyMK1+3n+5hDGEnVknfO2f/FaVydjkdbkawhOnaWURhCN/UPAcinjxo2ImYELjCf23GsNVGk= 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=mh+Ix1Fb; 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="mh+Ix1Fb" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmx.net; s=s31663417; t=1738761124; x=1739365924; i=ps.report@gmx.net; bh=Y/3V+emCRXVxI/5pFQD5uxe35BuduQQqfM0vaJoQW90=; 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=mh+Ix1FbB/p91J/9vI+m2gz4NsMZFxcSRtf1jbWfgxUWnIQC/kjReXg9JAh11Ey7 DA+apPKK/yru2tjaKlAOAcRJKQaTZUPtcKQYvBAxQDZAePsGo2WAk5JNTsE42ePeA 8595IaaJ19It5kTT4r8o6kJcrQ3SoHM/bnL/8H9WeMsDdOVYM7G1tqvpPrgR7hAeE 2NisdBY61iS/wyLJ2llh2vWz0FtMpX/iGq8BHXeoTEC4jMi0Lv8KfU5Otwt5YkdXZ YJT/nReTViwi3oR+1j+LZDsDjS1V2Za7eZ+5cJN+sTU6/L/HAyYSV0HM3aKQQStGb i7QFA8Wv9DU7YrwgwA== X-UI-Sender-Class: 724b4f7f-cbec-4199-ad4e-598c01a50d3a Received: from localhost.fritz.box ([82.135.81.162]) by mail.gmx.net (mrgmx004 [212.227.17.190]) with ESMTPSA (Nemesis) id 1Mt79P-1tQ47h2J6P-00yWWR; Wed, 05 Feb 2025 14:12:04 +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 Subject: [PATCH net-next v4 13/17] net: pktgen: fix access outside of user given buffer in pktgen_if_write() Date: Wed, 5 Feb 2025 14:11:49 +0100 Message-ID: <20250205131153.476278-14-ps.report@gmx.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250205131153.476278-1-ps.report@gmx.net> References: <20250205131153.476278-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:SmkqQ3zrOpXc+8olEgHqm882SrpP7wQOkYP4tkkHNS4GgN9NNgC hQ4NbxBwIrCi+iEJ1x+9Ab+s0K8wkAmEvyX+wELNuFojCdCQXj+Vdh91nwTvDYhoP5eov1x t1OgWgqIAMbBPiC2onED7ZyhpteW5dF5HY173D6ZRJj8pv9xu07txLw7DHhrHp3QISEaBrQ 5lQW/tM3r3ezt+9wij2pQ== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:sUX6qc/EFzs=;VqfxuZkf1FybBx6O1B649Mk7Po8 VooJmF9N6pD5vrd1XeM7MKtgnSuNZPsBuyLpo4As6u0xHcOXGVM+OqW9AVr6gefYAzo26w+VO Kuh1UwmqnRhDPofP4RcPqnW+8MIBgblhI67lEskLb7I8ggqtmenv7tPy76VyeRtijDV6GS0qU jKZ0w70/SibJHgaDbyT505RCShQEvX4pfqCYu6u6saEejZxvg6iA0x9zotXyrKBMvCxC1Qdaa 6NozZqAP+3wAoEPI5h+lJbvOINWOYC5oiAhvVFGm1TxmXMEuRRkRHp5FyD61hrdVdGwY/7H3P GGEIf8NMsLJmjd3viJGVwpiE0PnMQlp00ZXdXT+DHj83n0l+hxEmQ54BFHdnyf4hB9l2ry8DK 1gVse58xVBELdMNS8DvRZzDXAXIcjMuUW+kBlIhooUGH0nbUcawCwW+/pWKMj1qQ/SfnDKiqk Ec3hOV2V3xKE5e53xvehBQtrCuuxP0mCiM6Ux5DGZHFaKD+IoJVn6WNUP6scwcsIR1cyyQZV6 YseCZATiCK0HgTvxjSk2jSPA2HlU0Jvz2kVC3rBmT7dhmSpfI1NSotB1yUHB4nyxNLq/1wdEv rlPrRad5DcD0Cs4AQhq8a7NPBuVv6GmWcJHCCCKtwi/eDqLdc1mD7KZgbH7bzFO0143rsdT1b Iiz9izFVZ6aRIeN3eHyJ1qfdtNAGj023+JvYnU7NAjZKdVqpjN1XDcWOHtmsOv38/ITXKuNnv JxZGekCwsbRsx34EU3fsBaFuM/y+w9/iwufoyWrjKRp/Ph6aWxCFqmkfoCTdjCx3MPm1of8y4 0DZ3I8bmNtogz5LE7mFkiaal4woU9Hr2BU/fRfF5fYdhKmRDvAGKNLaeoq4f7zbbzmNFPa4Ze 7p6rA1XppOSGZvyGQ1bKr3JmH6RW1tU8dsBWPHEhkvc3WT/6mz/2ONmbPyIw7L/jnAQ9QgBiZ iyvJfsXB5wNgMfKcYcpPxGGrWCNQSvHKFWfoiwcY2ixZJPI/Co8bPUMWnyE84GBsrFNn0rtdR MFlBU/cOZKfEwOArLSg8ay8EPHtojMVswb/lCanqUP8uaVMH/HU3s7ZTJB+ldgvRpgl8gu992 Rano5MTixRawad90YgauydiWOKAsL2qvVIGA6BxAfS8BTP/EzRqqTFCmiCuwVd3w4/2IZFwHs /G912xDFlYrfQ9s02rTDm200i6K1VTaHQo0N02dz+LDLSW/eSzOBAyjbw4Gzb4a2+Wk/XmSXs bBwPjzrkHqNolltUxwksQOgxX8GTahyAGWVRP61d2DZ2HjdiIK7unlIyn3UEmok3aWk9qQvNs FnZ7twIvNO7FwPI0rEB5FNgHGSVOGDz8acob2C0zwPxBkM= 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 --- 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 | 176 ++++++++++++++++++++++++++++++---------------- 1 file changed, 117 insertions(+), 59 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 0fd15f21119b..3c42ecf17ba2 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -851,10 +851,11 @@ 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 int get_imix_entries(const char __user *buffer, + unsigned int maxlen, struct pktgen_dev *pkt_dev) { char c; - int i = 0, len; + int i = 0, max, len; pkt_dev->n_imix_entries = 0; @@ -865,10 +866,13 @@ static int get_imix_entries(const char __user *buffer, if (pkt_dev->n_imix_entries >= MAX_IMIX_ENTRIES) return -E2BIG; - len = num_arg(&buffer[i], DEC_10_DIGITS, &size); + max = min(DEC_10_DIGITS, 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 */ @@ -879,7 +883,8 @@ static int get_imix_entries(const char __user *buffer, if (size < 14 + 20 + 8) size = 14 + 20 + 8; - len = num_arg(&buffer[i], DEC_10_DIGITS, &weight); + max = min(DEC_10_DIGITS, maxlen - i); + len = num_arg(&buffer[i], max, &weight); if (len < 0) return len; if (weight <= 0) @@ -889,21 +894,23 @@ static int 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 int get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev) +static int get_labels(const char __user *buffer, int maxlen, struct pktgen_dev *pkt_dev) { char c; - int i = 0, len; unsigned int n = 0; + int i = 0, max, len; pkt_dev->nr_labels = 0; do { @@ -912,17 +919,20 @@ static int get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev) if (n >= MAX_MPLS_LABELS) return -E2BIG; - len = hex32_arg(&buffer[i], HEX_8_DIGITS, &tmp); + max = min(HEX_8_DIGITS, 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++; } while (c == ','); pkt_dev->nr_labels = n; @@ -986,8 +996,8 @@ static ssize_t pktgen_if_write(struct file *file, 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; @@ -1015,7 +1025,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "min_pkt_size")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1032,7 +1043,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "max_pkt_size")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1051,7 +1063,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], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1071,7 +1084,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; @@ -1082,7 +1096,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "debug")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1093,7 +1108,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "frags")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1103,7 +1119,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "delay")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1118,7 +1135,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "rate")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1133,7 +1151,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "ratep")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1148,7 +1167,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "udp_src_min")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1161,7 +1181,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "udp_dst_min")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1174,7 +1195,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "udp_src_max")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1187,7 +1209,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "udp_dst_max")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1200,7 +1223,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "clone_skb")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, 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 @@ -1221,7 +1245,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "count")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1232,7 +1257,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "src_mac_count")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1246,7 +1272,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst_mac_count")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1260,7 +1287,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "burst")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1279,7 +1307,8 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "node")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1300,11 +1329,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; @@ -1340,11 +1370,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; @@ -1389,7 +1420,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; @@ -1409,7 +1441,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; @@ -1429,7 +1462,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; @@ -1452,7 +1486,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; @@ -1474,7 +1509,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; @@ -1495,7 +1531,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; @@ -1518,7 +1555,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; @@ -1538,7 +1576,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; @@ -1558,7 +1597,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; @@ -1575,7 +1615,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; @@ -1599,7 +1640,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "flows")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1613,7 +1655,8 @@ static ssize_t pktgen_if_write(struct file *file, } #ifdef CONFIG_XFRM if (!strcmp(name, "spi")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1624,7 +1667,8 @@ static ssize_t pktgen_if_write(struct file *file, } #endif if (!strcmp(name, "flowlen")) { - len = num_arg(&user_buffer[i], DEC_10_DIGITS, &value); + max = min(DEC_10_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1635,7 +1679,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "queue_map_min")) { - len = num_arg(&user_buffer[i], DEC_5_DIGITS, &value); + max = min(DEC_5_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1646,7 +1691,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "queue_map_max")) { - len = num_arg(&user_buffer[i], DEC_5_DIGITS, &value); + max = min(DEC_5_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1659,7 +1705,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; @@ -1680,7 +1727,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "vlan_id")) { - len = num_arg(&user_buffer[i], DEC_4_DIGITS, &value); + max = min(DEC_4_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1707,7 +1755,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "vlan_p")) { - len = num_arg(&user_buffer[i], DEC_1_DIGITS, &value); + max = min(DEC_1_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1722,7 +1771,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "vlan_cfi")) { - len = num_arg(&user_buffer[i], DEC_1_DIGITS, &value); + max = min(DEC_1_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1737,7 +1787,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "svlan_id")) { - len = num_arg(&user_buffer[i], DEC_4_DIGITS, &value); + max = min(DEC_4_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1764,7 +1815,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "svlan_p")) { - len = num_arg(&user_buffer[i], DEC_1_DIGITS, &value); + max = min(DEC_1_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1779,7 +1831,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "svlan_cfi")) { - len = num_arg(&user_buffer[i], DEC_1_DIGITS, &value); + max = min(DEC_1_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len; @@ -1795,7 +1848,9 @@ static ssize_t pktgen_if_write(struct file *file, if (!strcmp(name, "tos")) { __u32 tmp_value; - len = hex32_arg(&user_buffer[i], HEX_2_DIGITS, &tmp_value); + + max = min(HEX_2_DIGITS, count - i); + len = hex32_arg(&user_buffer[i], max, &tmp_value); if (len < 0) return len; @@ -1811,7 +1866,9 @@ static ssize_t pktgen_if_write(struct file *file, if (!strcmp(name, "traffic_class")) { __u32 tmp_value; - len = hex32_arg(&user_buffer[i], HEX_2_DIGITS, &tmp_value); + + max = min(HEX_2_DIGITS, count - i); + len = hex32_arg(&user_buffer[i], max, &tmp_value); if (len < 0) return len; @@ -1826,7 +1883,8 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "skb_priority")) { - len = num_arg(&user_buffer[i], DEC_9_DIGITS, &value); + max = min(DEC_9_DIGITS, count - i); + len = num_arg(&user_buffer[i], max, &value); if (len < 0) return len;