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.

Reported-by: Denis Sergeev <[email protected]>
Fixes: 364e08f2bbc0 ("af_packet: add PMD for AF_PACKET-based virtual devices")
Cc: [email protected]

Signed-off-by: Stephen Hemminger <[email protected]>
---
 drivers/net/af_packet/rte_eth_af_packet.c | 58 +++++++++++++++++++----
 1 file changed, 48 insertions(+), 10 deletions(-)

diff --git a/drivers/net/af_packet/rte_eth_af_packet.c 
b/drivers/net/af_packet/rte_eth_af_packet.c
index 8303ff5ca9..b0ff22ea55 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -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) {
-- 
2.53.0

Reply via email to