Skip to content

Commit b3979e3

Browse files
q2venkuba-moo
authored andcommitted
ipv6: Move fib6_config_validate() to ip6_route_add().
syzkaller created an IPv6 route from a malformed packet, which has a prefix len > 128, triggering the splat below. [0] This is a similar issue fixed by commit 586ceac ("ipv6: Restore fib6_config validation for SIOCADDRT."). The cited commit removed fib6_config validation from some callers of ip6_add_route(). Let's move the validation back to ip6_route_add() and ip6_route_multipath_add(). [0]: UBSAN: array-index-out-of-bounds in ./include/net/ipv6.h:616:34 index 20 is out of range for type '__u8 [16]' CPU: 1 UID: 0 PID: 7444 Comm: syz.0.708 Not tainted 6.16.0-rc1-syzkaller-g19272b37aa4f #0 PREEMPT Hardware name: riscv-virtio,qemu (DT) Call Trace: [<ffffffff80078a80>] dump_backtrace+0x2e/0x3c arch/riscv/kernel/stacktrace.c:132 [<ffffffff8000327a>] show_stack+0x30/0x3c arch/riscv/kernel/stacktrace.c:138 [<ffffffff80061012>] __dump_stack lib/dump_stack.c:94 [inline] [<ffffffff80061012>] dump_stack_lvl+0x12e/0x1a6 lib/dump_stack.c:120 [<ffffffff800610a6>] dump_stack+0x1c/0x24 lib/dump_stack.c:129 [<ffffffff8001c0ea>] ubsan_epilogue+0x14/0x46 lib/ubsan.c:233 [<ffffffff819ba290>] __ubsan_handle_out_of_bounds+0xf6/0xf8 lib/ubsan.c:455 [<ffffffff85b363a4>] ipv6_addr_prefix include/net/ipv6.h:616 [inline] [<ffffffff85b363a4>] ip6_route_info_create+0x8f8/0x96e net/ipv6/route.c:3793 [<ffffffff85b635da>] ip6_route_add+0x2a/0x1aa net/ipv6/route.c:3889 [<ffffffff85b02e08>] addrconf_prefix_route+0x2c4/0x4e8 net/ipv6/addrconf.c:2487 [<ffffffff85b23bb2>] addrconf_prefix_rcv+0x1720/0x1e62 net/ipv6/addrconf.c:2878 [<ffffffff85b92664>] ndisc_router_discovery+0x1a06/0x3504 net/ipv6/ndisc.c:1570 [<ffffffff85b99038>] ndisc_rcv+0x500/0x600 net/ipv6/ndisc.c:1874 [<ffffffff85bc2c18>] icmpv6_rcv+0x145e/0x1e0a net/ipv6/icmp.c:988 [<ffffffff85af6798>] ip6_protocol_deliver_rcu+0x18a/0x1976 net/ipv6/ip6_input.c:436 [<ffffffff85af8078>] ip6_input_finish+0xf4/0x174 net/ipv6/ip6_input.c:480 [<ffffffff85af8262>] NF_HOOK include/linux/netfilter.h:317 [inline] [<ffffffff85af8262>] NF_HOOK include/linux/netfilter.h:311 [inline] [<ffffffff85af8262>] ip6_input+0x16a/0x70c net/ipv6/ip6_input.c:491 [<ffffffff85af8dcc>] ip6_mc_input+0x5c8/0x1268 net/ipv6/ip6_input.c:588 [<ffffffff85af6112>] dst_input include/net/dst.h:469 [inline] [<ffffffff85af6112>] ip6_rcv_finish net/ipv6/ip6_input.c:79 [inline] [<ffffffff85af6112>] NF_HOOK include/linux/netfilter.h:317 [inline] [<ffffffff85af6112>] NF_HOOK include/linux/netfilter.h:311 [inline] [<ffffffff85af6112>] ipv6_rcv+0x5ae/0x6e0 net/ipv6/ip6_input.c:309 [<ffffffff85087e84>] __netif_receive_skb_one_core+0x106/0x16e net/core/dev.c:5977 [<ffffffff85088104>] __netif_receive_skb+0x2c/0x144 net/core/dev.c:6090 [<ffffffff850883c6>] netif_receive_skb_internal net/core/dev.c:6176 [inline] [<ffffffff850883c6>] netif_receive_skb+0x1aa/0xbf2 net/core/dev.c:6235 [<ffffffff8328656e>] tun_rx_batched.isra.0+0x430/0x686 drivers/net/tun.c:1485 [<ffffffff8329ed3a>] tun_get_user+0x2952/0x3d6c drivers/net/tun.c:1938 [<ffffffff832a21e0>] tun_chr_write_iter+0xc4/0x21c drivers/net/tun.c:1984 [<ffffffff80b9b9ae>] new_sync_write fs/read_write.c:593 [inline] [<ffffffff80b9b9ae>] vfs_write+0x56c/0xa9a fs/read_write.c:686 [<ffffffff80b9c2be>] ksys_write+0x126/0x228 fs/read_write.c:738 [<ffffffff80b9c42e>] __do_sys_write fs/read_write.c:749 [inline] [<ffffffff80b9c42e>] __se_sys_write fs/read_write.c:746 [inline] [<ffffffff80b9c42e>] __riscv_sys_write+0x6e/0x94 fs/read_write.c:746 [<ffffffff80076912>] syscall_handler+0x94/0x118 arch/riscv/include/asm/syscall.h:112 [<ffffffff8637e31e>] do_trap_ecall_u+0x396/0x530 arch/riscv/kernel/traps.c:341 [<ffffffff863a69e2>] handle_exception+0x146/0x152 arch/riscv/kernel/entry.S:197 Fixes: fa76c16 ("ipv6: Move some validation from ip6_route_info_create() to rtm_to_fib6_config().") Reported-by: [email protected] Closes: https://lore.kernel.org/netdev/[email protected]/ Signed-off-by: Kuniyuki Iwashima <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 1264971 commit b3979e3

File tree

1 file changed

+55
-55
lines changed

1 file changed

+55
-55
lines changed

net/ipv6/route.c

Lines changed: 55 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3737,6 +3737,53 @@ void fib6_nh_release_dsts(struct fib6_nh *fib6_nh)
37373737
}
37383738
}
37393739

3740+
static int fib6_config_validate(struct fib6_config *cfg,
3741+
struct netlink_ext_ack *extack)
3742+
{
3743+
/* RTF_PCPU is an internal flag; can not be set by userspace */
3744+
if (cfg->fc_flags & RTF_PCPU) {
3745+
NL_SET_ERR_MSG(extack, "Userspace can not set RTF_PCPU");
3746+
goto errout;
3747+
}
3748+
3749+
/* RTF_CACHE is an internal flag; can not be set by userspace */
3750+
if (cfg->fc_flags & RTF_CACHE) {
3751+
NL_SET_ERR_MSG(extack, "Userspace can not set RTF_CACHE");
3752+
goto errout;
3753+
}
3754+
3755+
if (cfg->fc_type > RTN_MAX) {
3756+
NL_SET_ERR_MSG(extack, "Invalid route type");
3757+
goto errout;
3758+
}
3759+
3760+
if (cfg->fc_dst_len > 128) {
3761+
NL_SET_ERR_MSG(extack, "Invalid prefix length");
3762+
goto errout;
3763+
}
3764+
3765+
#ifdef CONFIG_IPV6_SUBTREES
3766+
if (cfg->fc_src_len > 128) {
3767+
NL_SET_ERR_MSG(extack, "Invalid source address length");
3768+
goto errout;
3769+
}
3770+
3771+
if (cfg->fc_nh_id && cfg->fc_src_len) {
3772+
NL_SET_ERR_MSG(extack, "Nexthops can not be used with source routing");
3773+
goto errout;
3774+
}
3775+
#else
3776+
if (cfg->fc_src_len) {
3777+
NL_SET_ERR_MSG(extack,
3778+
"Specifying source address requires IPV6_SUBTREES to be enabled");
3779+
goto errout;
3780+
}
3781+
#endif
3782+
return 0;
3783+
errout:
3784+
return -EINVAL;
3785+
}
3786+
37403787
static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
37413788
gfp_t gfp_flags,
37423789
struct netlink_ext_ack *extack)
@@ -3886,6 +3933,10 @@ int ip6_route_add(struct fib6_config *cfg, gfp_t gfp_flags,
38863933
struct fib6_info *rt;
38873934
int err;
38883935

3936+
err = fib6_config_validate(cfg, extack);
3937+
if (err)
3938+
return err;
3939+
38893940
rt = ip6_route_info_create(cfg, gfp_flags, extack);
38903941
if (IS_ERR(rt))
38913942
return PTR_ERR(rt);
@@ -4479,53 +4530,6 @@ void rt6_purge_dflt_routers(struct net *net)
44794530
rcu_read_unlock();
44804531
}
44814532

4482-
static int fib6_config_validate(struct fib6_config *cfg,
4483-
struct netlink_ext_ack *extack)
4484-
{
4485-
/* RTF_PCPU is an internal flag; can not be set by userspace */
4486-
if (cfg->fc_flags & RTF_PCPU) {
4487-
NL_SET_ERR_MSG(extack, "Userspace can not set RTF_PCPU");
4488-
goto errout;
4489-
}
4490-
4491-
/* RTF_CACHE is an internal flag; can not be set by userspace */
4492-
if (cfg->fc_flags & RTF_CACHE) {
4493-
NL_SET_ERR_MSG(extack, "Userspace can not set RTF_CACHE");
4494-
goto errout;
4495-
}
4496-
4497-
if (cfg->fc_type > RTN_MAX) {
4498-
NL_SET_ERR_MSG(extack, "Invalid route type");
4499-
goto errout;
4500-
}
4501-
4502-
if (cfg->fc_dst_len > 128) {
4503-
NL_SET_ERR_MSG(extack, "Invalid prefix length");
4504-
goto errout;
4505-
}
4506-
4507-
#ifdef CONFIG_IPV6_SUBTREES
4508-
if (cfg->fc_src_len > 128) {
4509-
NL_SET_ERR_MSG(extack, "Invalid source address length");
4510-
goto errout;
4511-
}
4512-
4513-
if (cfg->fc_nh_id && cfg->fc_src_len) {
4514-
NL_SET_ERR_MSG(extack, "Nexthops can not be used with source routing");
4515-
goto errout;
4516-
}
4517-
#else
4518-
if (cfg->fc_src_len) {
4519-
NL_SET_ERR_MSG(extack,
4520-
"Specifying source address requires IPV6_SUBTREES to be enabled");
4521-
goto errout;
4522-
}
4523-
#endif
4524-
return 0;
4525-
errout:
4526-
return -EINVAL;
4527-
}
4528-
45294533
static void rtmsg_to_fib6_config(struct net *net,
45304534
struct in6_rtmsg *rtmsg,
45314535
struct fib6_config *cfg)
@@ -4563,10 +4567,6 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, struct in6_rtmsg *rtmsg)
45634567

45644568
switch (cmd) {
45654569
case SIOCADDRT:
4566-
err = fib6_config_validate(&cfg, NULL);
4567-
if (err)
4568-
break;
4569-
45704570
/* Only do the default setting of fc_metric in route adding */
45714571
if (cfg.fc_metric == 0)
45724572
cfg.fc_metric = IP6_RT_PRIO_USER;
@@ -5402,6 +5402,10 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
54025402
int nhn = 0;
54035403
int err;
54045404

5405+
err = fib6_config_validate(cfg, extack);
5406+
if (err)
5407+
return err;
5408+
54055409
replace = (cfg->fc_nlinfo.nlh &&
54065410
(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_REPLACE));
54075411

@@ -5636,10 +5640,6 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh,
56365640
if (err < 0)
56375641
return err;
56385642

5639-
err = fib6_config_validate(&cfg, extack);
5640-
if (err)
5641-
return err;
5642-
56435643
if (cfg.fc_metric == 0)
56445644
cfg.fc_metric = IP6_RT_PRIO_USER;
56455645

0 commit comments

Comments
 (0)