net/af_packet: fix qpairs argument upper bound check
PATCH 1/1 net/af_packet: fix qpairs argument upper bound check
The qpairs vdev argument parsed via atoi() is stored in an unsigned int. A negative input such as "-1" wraps to UINT_MAX, passes the existing "< 1" check, and reaches rte_pmd_init_internals() as nb_queues. This causes excessive socket and memory allocation in the per-queue loop.
Add an upper bound check against RTE_MAX_QUEUES_PER_PORT.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/net/af_packet/rte_eth_af_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/af_packet/rte_eth_af_packet.c +1 -1
@@ -1169,7 +1169,7 @@ rte_eth_from_packet(struct rte_vdev_device *dev, pair = &kvlist->pairs[k_idx];if (strstr (pair->key,ETH_AF_PACKET_NUM_Q_ARG ) !=NULL ) { qpairs =atoi (pair->value); -if (qpairs <1 ) { +if (qpairs <1 || qpairs >RTE_MAX_QUEUES_PER_PORT ) {PMD_LOG (ERR ,"%s: invalid qpairs value" , name);
Signature · 1 line
2.50.1
Quoted 6 lines · On Wed, 3 Jun 2026 07:42:18 +0300 Denis Sergeev <[email protected]> wrote:
drivers/net/af_packet/rte_eth_af_packet.c +0
-0
drivers/net/af_packet/rte_eth_af_packet.c rte_eth_from_packet(struct rte_vdev_device *dev, · line 1175
Quoted 8 lines
drivers/net/af_packet/rte_eth_af_packet.c +1
-1@@ -1169,7 +1169,7 @@ rte_eth_from_packet(struct rte_vdev_device *dev, pair = &kvlist->pairs[k_idx];if (strstr (pair->key,ETH_AF_PACKET_NUM_Q_ARG ) !=NULL ) { qpairs =atoi (pair->value); -if (qpairs <1 ) { +if (qpairs <1 || qpairs >RTE_MAX_QUEUES_PER_PORT ) {PMD_LOG (ERR ,"%s: invalid qpairs value" , name);
I would rather see atoi() not used in DPDK, it accepts too much and does not do enough validation. Replace with strtoul() instead.
PATCH v2 1/1 net/af_packet: fix qpairs argument upper bound check
In reply to Denis SergeevThe qpairs vdev argument was parsed with atoi(), which does no
validation: trailing garbage is ignored and a negative input such as "-1" wraps to UINT_MAX when stored in the unsigned qpairs field, passing the existing "< 1" check and reaching rte_pmd_init_internals() as nb_queues. This causes excessive socket and memory allocation in the per-queue loop.
Parse the value with strtoul() and reject non-numeric input, trailing characters, negative values and values outside the
[1, RTE_MAX_QUEUES_PER_PORT] range.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
---
v2:
* Replace atoi() with strtoul() and validate the parsed value
drivers/net/af_packet/rte_eth_af_packet.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/net/af_packet/rte_eth_af_packet.c +9 -2
@@ -1168,13 +1168,20 @@ rte_eth_from_packet(struct rte_vdev_device *dev,for (k_idx =0 ; k_idx < kvlist->count; k_idx++) { pair = &kvlist->pairs[k_idx];if (strstr (pair->key,ETH_AF_PACKET_NUM_Q_ARG ) !=NULL ) { - qpairs =atoi (pair->value); -if (qpairs <1 ) { +char *endptr; +unsigned long num; + + errno =0 ; + num =strtoul (pair->value, &endptr,10 ); +if (errno !=0 || endptr == pair->value || + *endptr !='\0' || pair->value[0 ] =='-' || + num <1 || num >RTE_MAX_QUEUES_PER_PORT ) {PMD_LOG (ERR ,"%s: invalid qpairs value" , name);return -1 ; } + qpairs = num;continue ; }if (strstr (pair->key,ETH_AF_PACKET_BLOCKSIZE_ARG ) !=NULL ) {
Signature · 1 line
2.50.1
PATCH 1/1 net/af_packet: fix parsing of numeric device args
This driver has several numeric arguments but it was using atoi() which allows garbage and negative values. Convert to a helper using strtoul() with upper bound.
First found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/net/af_packet/rte_eth_af_packet.c | 58 +++++++++++++++++++---- 1 file changed, 48 insertions(+), 10 deletions(-)
drivers/net/af_packet/rte_eth_af_packet.c +48 -10
@@ -15,7 +15,9 @@#include <rte_kvargs.h> #include <bus_vdev_driver.h> +#include <ctype.h> #include <errno.h> +#include <limits.h> #include <linux/if_ether.h> #include <linux/if_packet.h> #include <arpa/inet.h>
@@ -1138,6 +1140,42 @@ rte_pmd_init_internals(struct rte_vdev_device *dev,return -1 ; } +/* Parse an unsigned integer device argument. */ +static int +parse_uint (const char *key,const char *value, +unsigned int *out,unsigned long limit) +{ +unsigned long val; +char *endptr; + +if (value ==NULL ) { +PMD_LOG (ERR ,"no value for argument \"%s\"" , key); +return -1 ; + } + +/* Skip leading whitespace so a leading sign can be detected. */ +while (isspace ((unsigned char )*value)) + value++; + +/* strtoul() silently accepts and negates a leading '-'. */ +if (*value =='\0' || *value =='-' ) { +PMD_LOG (ERR ,"invalid value \"%s\" for argument \"%s\"" , + value, key); +return -1 ; + } + + errno =0 ; + val =strtoul (value, &endptr,10 ); +if (errno !=0 || *endptr !='\0' || val > limit) { +PMD_LOG (ERR ,"invalid value \"%s\" for argument \"%s\"" , + value, key); +return -1 ; + } + + *out = (unsigned int )val; +return 0 ; +} + static int rte_eth_from_packet(struct rte_vdev_device *dev, int const *sockfd,
@@ -1168,7 +1206,9 @@ rte_eth_from_packet(struct rte_vdev_device *dev,for (k_idx =0 ; k_idx < kvlist->count; k_idx++) { pair = &kvlist->pairs[k_idx];if (strstr (pair->key,ETH_AF_PACKET_NUM_Q_ARG ) !=NULL ) { - qpairs =atoi (pair->value); +if (parse_uint (pair->key, pair->value, + &qpairs,RTE_MAX_QUEUES_PER_PORT ) <0 ) +return -1 ;if (qpairs <1 ) { PMD_LOG(ERR, "%s: invalid qpairs value",
@@ -1178,7 +1218,8 @@ rte_eth_from_packet(struct rte_vdev_device *dev,continue ; }if (strstr (pair->key,ETH_AF_PACKET_BLOCKSIZE_ARG ) !=NULL ) { - blocksize =atoi (pair->value); +if (parse_uint (pair->key, pair->value, &blocksize,UINT_MAX ) <0 ) +return -1 ;if (!blocksize) { PMD_LOG(ERR, "%s: invalid blocksize value",
@@ -1188,7 +1229,8 @@ rte_eth_from_packet(struct rte_vdev_device *dev,continue ; }if (strstr (pair->key,ETH_AF_PACKET_FRAMESIZE_ARG ) !=NULL ) { - framesize =atoi (pair->value); +if (parse_uint (pair->key, pair->value, &framesize,UINT_MAX ) <0 ) +return -1 ;if (!framesize) { PMD_LOG(ERR, "%s: invalid framesize value",
@@ -1198,7 +1240,8 @@ rte_eth_from_packet(struct rte_vdev_device *dev,continue ; }if (strstr (pair->key,ETH_AF_PACKET_FRAMECOUNT_ARG ) !=NULL ) { - framecount =atoi (pair->value); +if (parse_uint (pair->key, pair->value, &framecount,UINT_MAX ) <0 ) +return -1 ;if (!framecount) { PMD_LOG(ERR, "%s: invalid framecount value",
@@ -1208,13 +1251,8 @@ rte_eth_from_packet(struct rte_vdev_device *dev,continue ; }if (strstr (pair->key,ETH_AF_PACKET_QDISC_BYPASS_ARG ) !=NULL ) { - qdisc_bypass =atoi (pair->value); -if (qdisc_bypass >1 ) { -PMD_LOG (ERR , -"%s: invalid bypass value" , - name); +if (parse_uint (pair->key, pair->value, &qdisc_bypass,1 ) <0 )return -1 ; - }continue ; }if (strstr (pair->key,ETH_AF_PACKET_FANOUT_MODE_ARG ) !=NULL ) {
Signature · 1 line
2.53.0
Re: [PATCH] net/af_packet: fix parsing of numeric device args
Quoted 11 lines · Stephen Hemminger
This driver has several numeric arguments but it was using
atoi()which allows garbage and negative values. Convert to a helper usingstrtoul()with upper bound.First found by Linux Verification Center (linuxtesting.org) with SVACE.
Reported-by Denis Sergeev <[email protected]>Fixes 364e08f2bbc0 ("af_packet: add PMD for AF_PACKET-based virtual devices")Signed-off-by Stephen Hemminger <[email protected]>