Skip to content

Commit a36f9c2

Browse files
committed
netfilter: ebtables: reject blobs that don't provide all entry points
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2121393 Upstream Status: commit 7997eff commit 7997eff Author: Florian Westphal <fw@strlen.de> Date: Sat Aug 20 17:38:37 2022 +0200 netfilter: ebtables: reject blobs that don't provide all entry points Harshit Mogalapalli says: In ebt_do_table() function dereferencing 'private->hook_entry[hook]' can lead to NULL pointer dereference. [..] Kernel panic: general protection fault, probably for non-canonical address 0xdffffc0000000005: 0000 [#1] PREEMPT SMP KASAN KASAN: null-ptr-deref in range [0x0000000000000028-0x000000000000002f] [..] RIP: 0010:ebt_do_table+0x1dc/0x1ce0 Code: 89 fa 48 c1 ea 03 80 3c 02 00 0f 85 5c 16 00 00 48 b8 00 00 00 00 00 fc ff df 49 8b 6c df 08 48 8d 7d 2c 48 89 fa 48 c1 ea 03 <0f> b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 88 [..] Call Trace: nf_hook_slow+0xb1/0x170 __br_forward+0x289/0x730 maybe_deliver+0x24b/0x380 br_flood+0xc6/0x390 br_dev_xmit+0xa2e/0x12c0 For some reason ebtables rejects blobs that provide entry points that are not supported by the table, but what it should instead reject is the opposite: blobs that DO NOT provide an entry point supported by the table. t->valid_hooks is the bitmask of hooks (input, forward ...) that will see packets. Providing an entry point that is not support is harmless (never called/used), but the inverse isn't: it results in a crash because the ebtables traverser doesn't expect a NULL blob for a location its receiving packets for. Instead of fixing all the individual checks, do what iptables is doing and reject all blobs that differ from the expected hooks. Fixes: 1da177e ("Linux-2.6.12-rc2") Reported-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com> Reported-by: syzkaller <syzkaller@googlegroups.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Florian Westphal <fwestpha@redhat.com>
1 parent c9ff03c commit a36f9c2

File tree

5 files changed

+1
-35
lines changed

5 files changed

+1
-35
lines changed

include/linux/netfilter_bridge/ebtables.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,6 @@ struct ebt_table {
9494
struct ebt_replace_kernel *table;
9595
unsigned int valid_hooks;
9696
rwlock_t lock;
97-
/* e.g. could be the table explicitly only allows certain
98-
* matches, targets, ... 0 == let it in */
99-
int (*check)(const struct ebt_table_info *info,
100-
unsigned int valid_hooks);
10197
/* the data used by the kernel */
10298
struct ebt_table_info *private;
10399
struct nf_hook_ops *ops;

net/bridge/netfilter/ebtable_broute.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,10 @@ static struct ebt_replace_kernel initial_table = {
3636
.entries = (char *)&initial_chain,
3737
};
3838

39-
static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
40-
{
41-
if (valid_hooks & ~(1 << NF_BR_BROUTING))
42-
return -EINVAL;
43-
return 0;
44-
}
45-
4639
static const struct ebt_table broute_table = {
4740
.name = "broute",
4841
.table = &initial_table,
4942
.valid_hooks = 1 << NF_BR_BROUTING,
50-
.check = check,
5143
.me = THIS_MODULE,
5244
};
5345

net/bridge/netfilter/ebtable_filter.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,10 @@ static struct ebt_replace_kernel initial_table = {
4343
.entries = (char *)initial_chains,
4444
};
4545

46-
static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
47-
{
48-
if (valid_hooks & ~FILTER_VALID_HOOKS)
49-
return -EINVAL;
50-
return 0;
51-
}
52-
5346
static const struct ebt_table frame_filter = {
5447
.name = "filter",
5548
.table = &initial_table,
5649
.valid_hooks = FILTER_VALID_HOOKS,
57-
.check = check,
5850
.me = THIS_MODULE,
5951
};
6052

net/bridge/netfilter/ebtable_nat.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,10 @@ static struct ebt_replace_kernel initial_table = {
4343
.entries = (char *)initial_chains,
4444
};
4545

46-
static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
47-
{
48-
if (valid_hooks & ~NAT_VALID_HOOKS)
49-
return -EINVAL;
50-
return 0;
51-
}
52-
5346
static const struct ebt_table frame_nat = {
5447
.name = "nat",
5548
.table = &initial_table,
5649
.valid_hooks = NAT_VALID_HOOKS,
57-
.check = check,
5850
.me = THIS_MODULE,
5951
};
6052

net/bridge/netfilter/ebtables.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,8 +1005,7 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl,
10051005
goto free_iterate;
10061006
}
10071007

1008-
/* the table doesn't like it */
1009-
if (t->check && (ret = t->check(newinfo, repl->valid_hooks)))
1008+
if (repl->valid_hooks != t->valid_hooks)
10101009
goto free_unlock;
10111010

10121011
if (repl->num_counters && repl->num_counters != t->private->nentries) {
@@ -1196,11 +1195,6 @@ int ebt_register_table(struct net *net, const struct ebt_table *input_table,
11961195
if (ret != 0)
11971196
goto free_chainstack;
11981197

1199-
if (table->check && table->check(newinfo, table->valid_hooks)) {
1200-
ret = -EINVAL;
1201-
goto free_chainstack;
1202-
}
1203-
12041198
table->private = newinfo;
12051199
rwlock_init(&table->lock);
12061200
mutex_lock(&ebt_mutex);

0 commit comments

Comments
 (0)