[PATCH] netfilter: ebtables: fix a NULL pointer dereference in ebt_do_table()

From: Harshit Mogalapalli
Date: Sat Aug 20 2022 - 03:14:01 EST


In ebt_do_table() function dereferencing 'private->hook_entry[hook]'
can lead to NULL pointer dereference. So add a check to prevent that.

Kernel panic:

[ 119.229105][ T31] general protection fault, probably for
non-canonical address 0xdffffc0000000005: 0000 [#1] PREEMPT SMP KASAN
[ 119.230280][ T31] KASAN: null-ptr-deref in range
[0x0000000000000028-0x000000000000002f]
[ 119.231043][ T31] CPU: 3 PID: 31 Comm: kworker/3:0 Not tainted
6.0.0-rc1 #1
[ 119.231652][ T31] Hardware name: QEMU Standard PC (i440FX + PIIX,
1996), BIOS 1.11.0-2.el7 04/01/2014
[ 119.232440][ T31] Workqueue: mld mld_ifc_work
[ 119.232846][ T31] RIP: 0010:ebt_do_table+0x1dc/0x1ce0
[ 119.233291][ T31] 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
[ 119.234920][ T31] RSP: 0018:ffffc90000347178 EFLAGS: 00010217
[ 119.235425][ T31] RAX: dffffc0000000000 RBX: 0000000000000003 RCX:
ffffffff8158677b
[ 119.236097][ T31] RDX: 0000000000000005 RSI: ffffffff889a7b80 RDI:
000000000000002c
[ 119.236764][ T31] RBP: 0000000000000000 R08: 0000000000000001 R09:
ffff888101a78443
[ 119.237425][ T31] R10: ffffed102034f088 R11: 000200100040dd86 R12:
ffffc90001111018
[ 119.238100][ T31] R13: ffffc90001103080 R14: ffffc90001111000 R15:
ffffc90001103000
[ 119.238769][ T31] FS: 0000000000000000(0000)
GS:ffff88811a380000(0000) knlGS:0000000000000000
[ 119.239592][ T31] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 119.240221][ T31] CR2: 00007f6a9adda000 CR3: 0000000100be3000 CR4:
00000000000006e0
[ 119.240970][ T31] Call Trace:
[ 119.241253][ T31] <TASK>
[ 119.241495][ T31] ? ip6_output+0x1f4/0x6e0
[ 119.241877][ T31] ? NF_HOOK.constprop.0+0xe6/0x5f0
[ 119.242309][ T31] ? mld_ifc_work+0x564/0xaa0
[ 119.242708][ T31] ? kthread+0x297/0x340
[ 119.243060][ T31] ? ret_from_fork+0x22/0x30
[ 119.243454][ T31] ? br_multicast_count+0xbf/0x8d0
[ 119.243896][ T31] ? rcu_read_lock_sched_held+0xd/0xa0
[ 119.244356][ T31] ? compat_copy_ebt_replace_from_user+0x380/0x380
[ 119.244907][ T31] ? compat_copy_ebt_replace_from_user+0x380/0x380
[ 119.245454][ T31] nf_hook_slow+0xb1/0x170
[ 119.245835][ T31] __br_forward+0x289/0x730
[ 119.246219][ T31] ? br_forward_finish+0x320/0x320
[ 119.246656][ T31] ? br_dev_queue_push_xmit+0x650/0x650
[ 119.247118][ T31] ? memcpy+0x39/0x60
[ 119.247444][ T31] ? __skb_clone+0x56c/0x750
[ 119.247845][ T31] maybe_deliver+0x24b/0x380
[ 119.248234][ T31] br_flood+0xc6/0x390
[ 119.248577][ T31] br_dev_xmit+0xa2e/0x12c0
[ 119.248975][ T31] ? rcu_read_lock_sched_held+0xd/0xa0
[ 119.249498][ T31] ? br_netpoll_setup+0x170/0x170
[ 119.249987][ T31] ? fib_rules_lookup+0x2eb/0x9d0
[ 119.250462][ T31] ? lock_repin_lock+0x30/0x420
[ 119.250922][ T31] ? rcu_read_lock_sched_held+0xd/0xa0
[ 119.251376][ T31] ? lock_acquire+0x510/0x630
[ 119.251773][ T31] ? netif_inherit_tso_max+0x1e0/0x1e0
[ 119.252228][ T31] dev_hard_start_xmit+0x151/0x660
[ 119.252663][ T31] __dev_queue_xmit+0x240e/0x3200
[ 119.253080][ T31] ? ip6mr_rtm_dumproute+0x530/0x530
[ 119.253522][ T31] ? netdev_core_pick_tx+0x2a0/0x2a0
[ 119.253968][ T31] ? unwind_next_frame+0x3de/0x1c90
[ 119.254403][ T31] ? rcu_read_lock_sched_held+0xd/0xa0
[ 119.254872][ T31] ? lock_acquire+0x510/0x630
[ 119.255266][ T31] ? rcu_read_lock_sched_held+0xd/0xa0
[ 119.255724][ T31] ? lock_release+0x5a2/0x840
[ 119.256119][ T31] ? mroute6_is_socket+0x14d/0x220
[ 119.256549][ T31] ? rcu_read_lock_sched_held+0xd/0xa0
[ 119.257064][ T31] ? lock_acquire+0x510/0x630
[ 119.257507][ T31] ? rcu_read_lock_sched_held+0xd/0xa0
[ 119.258016][ T31] ? lock_release+0x5a2/0x840
[ 119.258410][ T31] ? lock_release+0x840/0x840
[ 119.258812][ T31] ? ip6_finish_output+0x779/0x1190
[ 119.259304][ T31] ? lock_downgrade+0x7b0/0x7b0
[ 119.259778][ T31] ? rcu_read_lock_bh_held+0xd/0x90
[ 119.260275][ T31] ? ___neigh_lookup_noref.constprop.0+0x266/0x6d0
[ 119.260896][ T31] ? ip6_finish_output2+0x861/0x1690
[ 119.261343][ T31] ip6_finish_output2+0x861/0x1690
[ 119.261776][ T31] ? lock_release+0x5a2/0x840
[ 119.262176][ T31] ? __kasan_kmalloc+0x7f/0xa0
[ 119.262574][ T31] ? ip6_mtu+0x139/0x320
[ 119.262942][ T31] ? ip6_frag_next+0xcc0/0xcc0
[ 119.263341][ T31] ? rcu_read_lock_sched_held+0xd/0xa0
[ 119.263816][ T31] ? nf_ct_netns_get+0xe0/0xe0
[ 119.264214][ T31] ? rcu_read_lock_sched_held+0xd/0xa0
[ 119.264679][ T31] ? lock_release+0x5a2/0x840
[ 119.265066][ T31] ? nf_conntrack_in.cold+0x9b/0xe2
[ 119.265504][ T31] ? ip6_output+0x4c9/0x6e0
[ 119.265891][ T31] ip6_finish_output+0x779/0x1190
[ 119.266315][ T31] ? nf_hook_slow+0xb1/0x170
[ 119.266711][ T31] ip6_output+0x1f4/0x6e0
[ 119.267069][ T31] ? rcu_read_lock_sched_held+0xd/0xa0
[ 119.267520][ T31] ? ip6_finish_output+0x1190/0x1190
[ 119.267969][ T31] ? NF_HOOK.constprop.0+0x1b3/0x5f0
[ 119.268415][ T31] ? lock_pin_lock+0x184/0x380
[ 119.268817][ T31] ? ip6_fragment+0x2910/0x2910
[ 119.269269][ T31] ? nf_ct_netns_do_get+0x6c0/0x6c0
[ 119.269773][ T31] ? nf_hook_slow+0xb1/0x170
[ 119.270211][ T31] NF_HOOK.constprop.0+0xe6/0x5f0
[ 119.270697][ T31] ? igmp6_mcf_seq_next+0x460/0x460
[ 119.271159][ T31] ? igmp6_mcf_seq_stop+0x130/0x130
[ 119.271600][ T31] ? icmp6_dst_alloc+0x3dc/0x610
[ 119.272030][ T31] mld_sendpack+0x619/0xb50
[ 119.272413][ T31] ? NF_HOOK.constprop.0+0x5f0/0x5f0
[ 119.272867][ T31] ? lock_release+0x840/0x840
[ 119.273254][ T31] mld_ifc_work+0x564/0xaa0
[ 119.273642][ T31] ? pwq_activate_inactive_work+0xb2/0x190
[ 119.274126][ T31] process_one_work+0x875/0x1440
[ 119.274543][ T31] ? lock_release+0x840/0x840
[ 119.274936][ T31] ? pwq_dec_nr_in_flight+0x230/0x230
[ 119.275381][ T31] ? rwlock_bug.part.0+0x90/0x90
[ 119.275801][ T31] worker_thread+0x598/0xec0
[ 119.276187][ T31] ? process_one_work+0x1440/0x1440
[ 119.276613][ T31] kthread+0x297/0x340
[ 119.276958][ T31] ? kthread_complete_and_exit+0x20/0x20
[ 119.277422][ T31] ret_from_fork+0x22/0x30
[ 119.277796][ T31] </TASK>
[ 119.278048][ T31] Modules linked in:
[ 119.278377][ T31] Dumping ftrace buffer:
[ 119.278733][ T31] (ftrace buffer empty)
[ 119.279151][ T31] ---[ end trace 0000000000000000 ]---
[ 119.279679][ T31] RIP: 0010:ebt_do_table+0x1dc/0x1ce0
[ 119.280187][ T31] 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
[ 119.282006][ T31] RSP: 0018:ffffc90000347178 EFLAGS: 00010217
[ 119.282569][ T31] RAX: dffffc0000000000 RBX: 0000000000000003 RCX:
ffffffff8158677b
[ 119.283308][ T31] RDX: 0000000000000005 RSI: ffffffff889a7b80 RDI:
000000000000002c
[ 119.284056][ T31] RBP: 0000000000000000 R08: 0000000000000001 R09:
ffff888101a78443
[ 119.284811][ T31] R10: ffffed102034f088 R11: 000200100040dd86 R12:
ffffc90001111018
[ 119.285549][ T31] R13: ffffc90001103080 R14: ffffc90001111000 R15:
ffffc90001103000
[ 119.286284][ T31] FS: 0000000000000000(0000)
GS:ffff88811a380000(0000) knlGS:0000000000000000
[ 119.287119][ T31] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 119.287741][ T31] CR2: 00007f6a9adda000 CR3: 0000000100be3000 CR4:
00000000000006e0
[ 119.288489][ T31] Kernel panic - not syncing: Fatal exception in
interrupt
[ 119.298556][ T31] Dumping ftrace buffer:
[ 119.298974][ T31] (ftrace buffer empty)
[ 119.299399][ T31] Kernel Offset: disabled
[ 119.299823][ T31] Rebooting in 86400 seconds..

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: syzkaller <syzkaller@xxxxxxxxxxxxxxxx>
Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@xxxxxxxxxx>
---
Testing is only done with reproducer.

net/bridge/netfilter/ebtables.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index f2dbefb61ce8..d19d439a66c5 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -217,6 +217,11 @@ unsigned int ebt_do_table(void *priv, struct sk_buff *skb,
else
cs = NULL;
chaininfo = private->hook_entry[hook];
+ if (!chaininfo) {
+ read_unlock_bh(&table->lock);
+ return NF_DROP;
+ }
+
nentries = private->hook_entry[hook]->nentries;
point = (struct ebt_entry *)(private->hook_entry[hook]->data);
counter_base = cb_base + private->hook_entry[hook]->counter_offset;
--
2.31.1