]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
netfilter: flowtable: avoid num_encaps underflow on bridge VLAN untag
authorDavid Carlier <devnexen@gmail.com>
Sat, 23 May 2026 15:26:21 +0000 (16:26 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sun, 7 Jun 2026 08:53:46 +0000 (10:53 +0200)
The DEV_PATH_BR_VLAN_UNTAG case post-decrements info->num_encaps
inside WARN_ON_ONCE(). num_encaps is u8, so if it's already 0 the
decrement still happens and wraps it to 255. The break only leaves
the inner switch -- a later path entry can set info->indev back to
a real device, and we end up returning with num_encaps == 255.

nft_dev_forward_path() then walks info.encap[] (size 2) up to
num_encaps, which means an OOB stack read and a bogus count copied
into the route descriptor.

Should only happen on a malformed bridge path stack, hence the WARN,
but worth handling sanely. Move the decrement out of the WARN.

[ While at this, remove the WARN_ON_ONCE since this can only happen
  with a buggy bridge path stack --pablo ].

Fixes: e990cef6516d ("netfilter: flowtable: add bridge vlan filtering support")
Signed-off-by: David Carlier <devnexen@gmail.com>
Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nf_flow_table_path.c

index 9e88ea6a2eef78077182d473c4d68709942bc0cc..a3e6b82f2f8e9523f280ff47a4b3b39a223f4078 100644 (file)
@@ -163,10 +163,11 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
                                info->num_encaps++;
                                break;
                        case DEV_PATH_BR_VLAN_UNTAG:
-                               if (WARN_ON_ONCE(info->num_encaps-- == 0)) {
+                               if (info->num_encaps == 0) {
                                        info->indev = NULL;
                                        break;
                                }
+                               info->num_encaps--;
                                break;
                        case DEV_PATH_BR_VLAN_KEEP:
                                break;