mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 22:21:42 +00:00
rtnetlink: give a user socket to get_target_net()
This function is used from two places: rtnl_dump_ifinfo and
rtnl_getlink. In rtnl_getlink(), we give a request skb into
get_target_net(), but in rtnl_dump_ifinfo, we give a response skb
into get_target_net().
The problem here is that NETLINK_CB() isn't initialized for the response
skb. In both cases we can get a user socket and give it instead of skb
into get_target_net().
This bug was found by syzkaller with this call-trace:
kasan: GPF could be caused by NULL-ptr deref or user memory access
general protection fault: 0000 [#1] SMP KASAN
Modules linked in:
CPU: 1 PID: 3149 Comm: syzkaller140561 Not tainted 4.15.0-rc4-mm1+ #47
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
RIP: 0010:__netlink_ns_capable+0x8b/0x120 net/netlink/af_netlink.c:868
RSP: 0018:ffff8801c880f348 EFLAGS: 00010206
RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffffff8443f900
RDX: 000000000000007b RSI: ffffffff86510f40 RDI: 00000000000003d8
RBP: ffff8801c880f360 R08: 0000000000000000 R09: 1ffff10039101e4f
R10: 0000000000000000 R11: 0000000000000001 R12: ffffffff86510f40
R13: 000000000000000c R14: 0000000000000004 R15: 0000000000000011
FS: 0000000001a1a880(0000) GS:ffff8801db300000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000020151000 CR3: 00000001c9511005 CR4: 00000000001606e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
netlink_ns_capable+0x26/0x30 net/netlink/af_netlink.c:886
get_target_net+0x9d/0x120 net/core/rtnetlink.c:1765
rtnl_dump_ifinfo+0x2e5/0xee0 net/core/rtnetlink.c:1806
netlink_dump+0x48c/0xce0 net/netlink/af_netlink.c:2222
__netlink_dump_start+0x4f0/0x6d0 net/netlink/af_netlink.c:2319
netlink_dump_start include/linux/netlink.h:214 [inline]
rtnetlink_rcv_msg+0x7f0/0xb10 net/core/rtnetlink.c:4485
netlink_rcv_skb+0x21e/0x460 net/netlink/af_netlink.c:2441
rtnetlink_rcv+0x1c/0x20 net/core/rtnetlink.c:4540
netlink_unicast_kernel net/netlink/af_netlink.c:1308 [inline]
netlink_unicast+0x4be/0x6a0 net/netlink/af_netlink.c:1334
netlink_sendmsg+0xa4a/0xe60 net/netlink/af_netlink.c:1897
Cc: Jiri Benc <jbenc@redhat.com>
Fixes: 79e1ad148c
("rtnetlink: use netnsid to query interface")
Signed-off-by: Andrei Vagin <avagin@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
fb32dd3abf
commit
f428fe4a04
@ -1681,18 +1681,18 @@ static bool link_dump_filtered(struct net_device *dev,
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct net *get_target_net(struct sk_buff *skb, int netnsid)
|
||||
static struct net *get_target_net(struct sock *sk, int netnsid)
|
||||
{
|
||||
struct net *net;
|
||||
|
||||
net = get_net_ns_by_id(sock_net(skb->sk), netnsid);
|
||||
net = get_net_ns_by_id(sock_net(sk), netnsid);
|
||||
if (!net)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* For now, the caller is required to have CAP_NET_ADMIN in
|
||||
* the user namespace owning the target net ns.
|
||||
*/
|
||||
if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
|
||||
if (!sk_ns_capable(sk, net->user_ns, CAP_NET_ADMIN)) {
|
||||
put_net(net);
|
||||
return ERR_PTR(-EACCES);
|
||||
}
|
||||
@ -1733,7 +1733,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
ifla_policy, NULL) >= 0) {
|
||||
if (tb[IFLA_IF_NETNSID]) {
|
||||
netnsid = nla_get_s32(tb[IFLA_IF_NETNSID]);
|
||||
tgt_net = get_target_net(skb, netnsid);
|
||||
tgt_net = get_target_net(skb->sk, netnsid);
|
||||
if (IS_ERR(tgt_net)) {
|
||||
tgt_net = net;
|
||||
netnsid = -1;
|
||||
@ -2883,7 +2883,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
|
||||
if (tb[IFLA_IF_NETNSID]) {
|
||||
netnsid = nla_get_s32(tb[IFLA_IF_NETNSID]);
|
||||
tgt_net = get_target_net(skb, netnsid);
|
||||
tgt_net = get_target_net(NETLINK_CB(skb).sk, netnsid);
|
||||
if (IS_ERR(tgt_net))
|
||||
return PTR_ERR(tgt_net);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user