]> 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>
Tue, 25 Apr 2023 14:53:22 +0000 (16:53 +0200)
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
tests/shell/testcases/chains/0042chain_variable_0
tests/shell/testcases/chains/dumps/0042chain_variable_0.nft

index c590c9554e0cf4b2fbcf66050617fb9f8c4dde5c..5dcfd9a04c4bf38478c23c947de91adad989dd81 100644 (file)
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -720,31 +720,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;
index 58535f76cc329a564485f24b763e2f91fd966230..f71b04155e444c4a41112bb92a26c300bf650a84 100755 (executable)
@@ -25,11 +25,15 @@ table netdev filter2 {
 $NFT -f - <<< $EXPECTED
 
 EXPECTED="define if_main = { lo, dummy0 }
+define lan_interfaces = { lo }
 
 table netdev filter3 {
        chain Main_Ingress3 {
                type filter hook ingress devices = \$if_main priority -500; policy accept;
        }
+       chain Main_Egress3 {
+               type filter hook egress devices = \$lan_interfaces priority -500; policy accept;
+       }
 }"
 
 $NFT -f - <<< $EXPECTED
index 12931aadb39fa197fb0695987747e8718fb9b638..5ec230d0bcfa8277c277c78ef0e34d9338b25b55 100644 (file)
@@ -12,4 +12,8 @@ table netdev filter3 {
        chain Main_Ingress3 {
                type filter hook ingress devices = { dummy0, lo } priority -500; policy accept;
        }
+
+       chain Main_Egress3 {
+               type filter hook egress device "lo" priority -500; policy accept;
+       }
 }