mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
rds: Fix inet6_addr_lst NULL dereference when IPv6 is disabled
When booting with the 'ipv6.disable=1' parameter, inet6_addr_lst is never initialized because inet6_init() exits before addrconf_init() is called to initialize it. An attempt to bind an RDS socket to an ipv6 address results in a crash in __ipv6_chk_addr_and_flags() KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] RIP: 0010:__ipv6_chk_addr_and_flags+0x1df/0x7e0 Call Trace: <TASK> ipv6_chk_addr+0x3b/0x50 rds_tcp_laddr_check+0x155/0x3b0 [rds_tcp] rds_trans_get_preferred+0x15d/0x2d0 [rds] ? trace_hardirqs_on+0x2d/0x110 rds_bind+0x1433/0x1d60 [rds] ? rds_remove_bound+0xd50/0xd50 [rds] ? aa_af_perm+0x250/0x250 ? __might_fault+0xde/0x190 ? __sys_bind+0x1dc/0x210 __sys_bind+0x1dc/0x210 ? __ia32_sys_socketpair+0x100/0x100 ? restore_fpregs_from_fpstate+0x53/0x100 __x64_sys_bind+0x73/0xb0 ? syscall_enter_from_user_mode+0x1c/0x50 do_syscall_64+0x34/0x80 entry_SYSCALL_64_after_hwframe+0x6e/0xd8 RIP: 0033:0x7f47f8269ea9 </TASK> The following code reproduces the issue: struct sockaddr_in6 addr; s = socket(PF_RDS, SOCK_SEQPACKET, 0); memset(&addr, 0, sizeof(addr)); inet_pton(AF_INET6, ADDRESS, &addr.sin6_addr); addr.sin6_family = AF_INET6; addr.sin6_port = htons(PORT); bind(s, &addr, sizeof(addr)); Found by InfoTeCS on behalf of Linux Verification Center (linuxtesting.org) with Syzkaller. Fixes:eee2fa6ab3("rds: Changing IP address internal representation to struct in6_addr") Fixes:1e2b44e78e("rds: Enable RDS IPv6 support") Signed-off-by: Ilia Gavrilov <Ilia.Gavrilov@infotecs.ru> Reviewed-by: Allison Henderson <achender@kernel.org> Link: https://patch.msgid.link/20260709162723.367523-1-Ilia.Gavrilov@infotecs.ru Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
6a905a71fd
commit
9c805e592a
|
|
@ -429,6 +429,10 @@ static int rds_ib_laddr_check_cm(struct net *net, const struct in6_addr *addr,
|
|||
sa = (struct sockaddr *)&sin;
|
||||
} else {
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (!ipv6_mod_enabled()) {
|
||||
ret = -EADDRNOTAVAIL;
|
||||
goto out;
|
||||
}
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_addr = *addr;
|
||||
|
|
|
|||
|
|
@ -810,6 +810,10 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
|
|||
dp = event->param.conn.private_data;
|
||||
if (isv6) {
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (!ipv6_mod_enabled()) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
dp_cmn = &dp->ricp_v6.dp_cmn;
|
||||
saddr6 = &dp->ricp_v6.dp_saddr;
|
||||
daddr6 = &dp->ricp_v6.dp_daddr;
|
||||
|
|
|
|||
|
|
@ -366,9 +366,11 @@ int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr,
|
|||
rcu_read_unlock();
|
||||
}
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
ret = ipv6_chk_addr(net, addr, dev, 0);
|
||||
if (ret)
|
||||
return 0;
|
||||
if (ipv6_mod_enabled()) {
|
||||
ret = ipv6_chk_addr(net, addr, dev, 0);
|
||||
if (ret)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user