mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
ipv6: Restore fib6_config validation for SIOCADDRT.
syzkaller reported out-of-bounds read in ipv6_addr_prefix(),
where the prefix length was over 128.
The cited commit accidentally removed some fib6_config
validation from the ioctl path.
Let's restore the validation.
[0]:
BUG: KASAN: slab-out-of-bounds in ip6_route_info_create (./include/net/ipv6.h:616 net/ipv6/route.c:3814)
Read of size 1 at addr ff11000138020ad4 by task repro/261
CPU: 3 UID: 0 PID: 261 Comm: repro Not tainted 6.15.0-rc3-00614-g0d15a26b247d #87 PREEMPT(voluntary)
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl (lib/dump_stack.c:123)
print_report (mm/kasan/report.c:409 mm/kasan/report.c:521)
kasan_report (mm/kasan/report.c:636)
ip6_route_info_create (./include/net/ipv6.h:616 net/ipv6/route.c:3814)
ip6_route_add (net/ipv6/route.c:3902)
ipv6_route_ioctl (net/ipv6/route.c:4523)
inet6_ioctl (net/ipv6/af_inet6.c:577)
sock_do_ioctl (net/socket.c:1190)
sock_ioctl (net/socket.c:1314)
__x64_sys_ioctl (fs/ioctl.c:51 fs/ioctl.c:906 fs/ioctl.c:892 fs/ioctl.c:892)
do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
RIP: 0033:0x7f518fb2de5d
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 73 9f 1b 00 f7 d8 64 89 01 48
RSP: 002b:00007fff14f38d18 EFLAGS: 00000202 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f518fb2de5d
RDX: 00000000200015c0 RSI: 000000000000890b RDI: 0000000000000003
RBP: 00007fff14f38d30 R08: 0000000000000800 R09: 0000000000000800
R10: 0000000000000000 R11: 0000000000000202 R12: 00007fff14f38e48
R13: 0000000000401136 R14: 0000000000403df0 R15: 00007f518fd3c000
</TASK>
Fixes: fa76c1674f
("ipv6: Move some validation from ip6_route_info_create() to rtm_to_fib6_config().")
Reported-by: syzkaller <syzkaller@googlegroups.com>
Reported-by: Yi Lai <yi1.lai@linux.intel.com>
Closes: https://lore.kernel.org/netdev/aBAcKDEFoN%2FLntBF@ly-workstation/
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20250501005335.53683-1-kuniyu@amazon.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
a2f6476ed1
commit
586ceac9ac
1 changed files with 55 additions and 42 deletions
|
@ -4503,6 +4503,53 @@ void rt6_purge_dflt_routers(struct net *net)
|
|||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int fib6_config_validate(struct fib6_config *cfg,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
/* RTF_PCPU is an internal flag; can not be set by userspace */
|
||||
if (cfg->fc_flags & RTF_PCPU) {
|
||||
NL_SET_ERR_MSG(extack, "Userspace can not set RTF_PCPU");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* RTF_CACHE is an internal flag; can not be set by userspace */
|
||||
if (cfg->fc_flags & RTF_CACHE) {
|
||||
NL_SET_ERR_MSG(extack, "Userspace can not set RTF_CACHE");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (cfg->fc_type > RTN_MAX) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid route type");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (cfg->fc_dst_len > 128) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid prefix length");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6_SUBTREES
|
||||
if (cfg->fc_src_len > 128) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid source address length");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (cfg->fc_nh_id && cfg->fc_src_len) {
|
||||
NL_SET_ERR_MSG(extack, "Nexthops can not be used with source routing");
|
||||
goto errout;
|
||||
}
|
||||
#else
|
||||
if (cfg->fc_src_len) {
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"Specifying source address requires IPV6_SUBTREES to be enabled");
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
errout:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void rtmsg_to_fib6_config(struct net *net,
|
||||
struct in6_rtmsg *rtmsg,
|
||||
struct fib6_config *cfg)
|
||||
|
@ -4540,6 +4587,10 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, struct in6_rtmsg *rtmsg)
|
|||
|
||||
switch (cmd) {
|
||||
case SIOCADDRT:
|
||||
err = fib6_config_validate(&cfg, NULL);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
/* Only do the default setting of fc_metric in route adding */
|
||||
if (cfg.fc_metric == 0)
|
||||
cfg.fc_metric = IP6_RT_PRIO_USER;
|
||||
|
@ -5274,48 +5325,6 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
}
|
||||
}
|
||||
|
||||
if (newroute) {
|
||||
/* RTF_PCPU is an internal flag; can not be set by userspace */
|
||||
if (cfg->fc_flags & RTF_PCPU) {
|
||||
NL_SET_ERR_MSG(extack, "Userspace can not set RTF_PCPU");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* RTF_CACHE is an internal flag; can not be set by userspace */
|
||||
if (cfg->fc_flags & RTF_CACHE) {
|
||||
NL_SET_ERR_MSG(extack, "Userspace can not set RTF_CACHE");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (cfg->fc_type > RTN_MAX) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid route type");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (cfg->fc_dst_len > 128) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid prefix length");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6_SUBTREES
|
||||
if (cfg->fc_src_len > 128) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid source address length");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (cfg->fc_nh_id && cfg->fc_src_len) {
|
||||
NL_SET_ERR_MSG(extack, "Nexthops can not be used with source routing");
|
||||
goto errout;
|
||||
}
|
||||
#else
|
||||
if (cfg->fc_src_len) {
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"Specifying source address requires IPV6_SUBTREES to be enabled");
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
err = 0;
|
||||
errout:
|
||||
return err;
|
||||
|
@ -5710,6 +5719,10 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = fib6_config_validate(&cfg, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (cfg.fc_metric == 0)
|
||||
cfg.fc_metric = IP6_RT_PRIO_USER;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue