]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
mnl: handle singleton element in netdevice set
authorPablo Neira Ayuso <pablo@netfilter.org>
Tue, 25 Apr 2023 09:48:52 +0000 (11:48 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 13 Aug 2025 17:51:19 +0000 (19:51 +0200)
commit 89b60bc18ca76e45b1682d8c56a0d01fffedebad upstream.

expr_evaluate_set() turns sets with singleton element into value,
nft_dev_add() expects a list of expression, so it crashes.

Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1676
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/mnl.c

index 80ab1a17bb5e039152093ba4c54048b9016c7266..731426da8fddd9bc623807fced9a5bd09b87831c 100644 (file)
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -698,31 +698,49 @@ err:
  */
 
 struct nft_dev {
-       const char      *ifname;
-       struct location *location;
+       const char              *ifname;
+       const struct location   *location;
 };
 
-static struct nft_dev *nft_dev_array(const struct expr *dev_expr, int *num_devs)
+static void nft_dev_add(struct nft_dev *dev_array, const struct expr *expr, int i)
 {
-       struct nft_dev *dev_array;
        unsigned int ifname_len;
        char ifname[IFNAMSIZ];
+
+       ifname_len = div_round_up(expr->len, BITS_PER_BYTE);
+       memset(ifname, 0, sizeof(ifname));
+       mpz_export_data(ifname, expr->value, BYTEORDER_HOST_ENDIAN, ifname_len);
+       dev_array[i].ifname = xstrdup(ifname);
+       dev_array[i].location = &expr->location;
+}
+
+static struct nft_dev *nft_dev_array(const struct expr *dev_expr, int *num_devs)
+{
+       struct nft_dev *dev_array;
        int i = 0, len = 1;
        struct expr *expr;
 
-       list_for_each_entry(expr, &dev_expr->expressions, list)
-               len++;
+       switch (dev_expr->etype) {
+       case EXPR_SET:
+       case EXPR_LIST:
+               list_for_each_entry(expr, &dev_expr->expressions, list)
+                       len++;
 
-       dev_array = xmalloc(sizeof(struct nft_dev) * len);
+               dev_array = xmalloc(sizeof(struct nft_dev) * len);
 
-       list_for_each_entry(expr, &dev_expr->expressions, list) {
-               ifname_len = div_round_up(expr->len, BITS_PER_BYTE);
-               memset(ifname, 0, sizeof(ifname));
-               mpz_export_data(ifname, expr->value, BYTEORDER_HOST_ENDIAN,
-                               ifname_len);
-               dev_array[i].ifname = xstrdup(ifname);
-               dev_array[i].location = &expr->location;
+               list_for_each_entry(expr, &dev_expr->expressions, list) {
+                       nft_dev_add(dev_array, expr, i);
+                       i++;
+               }
+               break;
+       case EXPR_VALUE:
+               len++;
+               dev_array = xmalloc(sizeof(struct nft_dev) * len);
+               nft_dev_add(dev_array, dev_expr, i);
                i++;
+               break;
+       default:
+               assert(0);
        }
 
        dev_array[i].ifname = NULL;