Skip to content

Commit 7bbfe00

Browse files
tracywwnjdavem330
authored andcommitted
ipv6: fix general protection fault in fib6_add()
In fib6_add(), pn could be NULL if fib6_add_1() failed to return a fib6 node. Checking pn != fn before accessing pn->leaf makes sure pn is not NULL. This fixes the following GPF reported by syzkaller: general protection fault: 0000 [#1] SMP KASAN Dumping ftrace buffer: (ftrace buffer empty) Modules linked in: CPU: 0 PID: 3201 Comm: syzkaller001778 Not tainted 4.15.0-rc5+ #151 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:fib6_add+0x736/0x15a0 net/ipv6/ip6_fib.c:1244 RSP: 0018:ffff8801c7626a70 EFLAGS: 00010202 RAX: dffffc0000000000 RBX: 0000000000000020 RCX: ffffffff84794465 RDX: 0000000000000004 RSI: ffff8801d38935f0 RDI: 0000000000000282 RBP: ffff8801c7626da0 R08: 1ffff10038ec4c35 R09: 0000000000000000 R10: ffff8801c7626c68 R11: 0000000000000000 R12: 00000000fffffffe R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000009 FS: 0000000000000000(0000) GS:ffff8801db200000(0063) knlGS:0000000009b70840 CS: 0010 DS: 002b ES: 002b CR0: 0000000080050033 CR2: 0000000020be1000 CR3: 00000001d585a006 CR4: 00000000001606f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: __ip6_ins_rt+0x6c/0x90 net/ipv6/route.c:1006 ip6_route_multipath_add+0xd14/0x16c0 net/ipv6/route.c:3833 inet6_rtm_newroute+0xdc/0x160 net/ipv6/route.c:3957 rtnetlink_rcv_msg+0x733/0x1020 net/core/rtnetlink.c:4411 netlink_rcv_skb+0x21e/0x460 net/netlink/af_netlink.c:2408 rtnetlink_rcv+0x1c/0x20 net/core/rtnetlink.c:4423 netlink_unicast_kernel net/netlink/af_netlink.c:1275 [inline] netlink_unicast+0x4e8/0x6f0 net/netlink/af_netlink.c:1301 netlink_sendmsg+0xa4a/0xe60 net/netlink/af_netlink.c:1864 sock_sendmsg_nosec net/socket.c:636 [inline] sock_sendmsg+0xca/0x110 net/socket.c:646 sock_write_iter+0x31a/0x5d0 net/socket.c:915 call_write_iter include/linux/fs.h:1772 [inline] do_iter_readv_writev+0x525/0x7f0 fs/read_write.c:653 do_iter_write+0x154/0x540 fs/read_write.c:932 compat_writev+0x225/0x420 fs/read_write.c:1246 do_compat_writev+0x115/0x220 fs/read_write.c:1267 C_SYSC_writev fs/read_write.c:1278 [inline] compat_SyS_writev+0x26/0x30 fs/read_write.c:1274 do_syscall_32_irqs_on arch/x86/entry/common.c:327 [inline] do_fast_syscall_32+0x3ee/0xf9d arch/x86/entry/common.c:389 entry_SYSENTER_compat+0x54/0x63 arch/x86/entry/entry_64_compat.S:125 Reported-by: syzbot <[email protected]> Fixes: 66f5d6c ("ipv6: replace rwlock with rcu and spinlock in fib6_table") Signed-off-by: Wei Wang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7d11f77 commit 7bbfe00

File tree

1 file changed

+20
-15
lines changed

1 file changed

+20
-15
lines changed

net/ipv6/ip6_fib.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,23 +1241,28 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
12411241
* If fib6_add_1 has cleared the old leaf pointer in the
12421242
* super-tree leaf node we have to find a new one for it.
12431243
*/
1244-
struct rt6_info *pn_leaf = rcu_dereference_protected(pn->leaf,
1245-
lockdep_is_held(&table->tb6_lock));
1246-
if (pn != fn && pn_leaf == rt) {
1247-
pn_leaf = NULL;
1248-
RCU_INIT_POINTER(pn->leaf, NULL);
1249-
atomic_dec(&rt->rt6i_ref);
1250-
}
1251-
if (pn != fn && !pn_leaf && !(pn->fn_flags & RTN_RTINFO)) {
1252-
pn_leaf = fib6_find_prefix(info->nl_net, table, pn);
1253-
#if RT6_DEBUG >= 2
1254-
if (!pn_leaf) {
1255-
WARN_ON(!pn_leaf);
1256-
pn_leaf = info->nl_net->ipv6.ip6_null_entry;
1244+
if (pn != fn) {
1245+
struct rt6_info *pn_leaf =
1246+
rcu_dereference_protected(pn->leaf,
1247+
lockdep_is_held(&table->tb6_lock));
1248+
if (pn_leaf == rt) {
1249+
pn_leaf = NULL;
1250+
RCU_INIT_POINTER(pn->leaf, NULL);
1251+
atomic_dec(&rt->rt6i_ref);
12571252
}
1253+
if (!pn_leaf && !(pn->fn_flags & RTN_RTINFO)) {
1254+
pn_leaf = fib6_find_prefix(info->nl_net, table,
1255+
pn);
1256+
#if RT6_DEBUG >= 2
1257+
if (!pn_leaf) {
1258+
WARN_ON(!pn_leaf);
1259+
pn_leaf =
1260+
info->nl_net->ipv6.ip6_null_entry;
1261+
}
12581262
#endif
1259-
atomic_inc(&pn_leaf->rt6i_ref);
1260-
rcu_assign_pointer(pn->leaf, pn_leaf);
1263+
atomic_inc(&pn_leaf->rt6i_ref);
1264+
rcu_assign_pointer(pn->leaf, pn_leaf);
1265+
}
12611266
}
12621267
#endif
12631268
goto failure;

0 commit comments

Comments
 (0)