Skip to content

Commit 7b735ef

Browse files
nickgarliskuba-moo
authored andcommitted
rtnetlink: add missing netlink_ns_capable() check for peer netns
rtnl_newlink() lacks a CAP_NET_ADMIN capability check on the peer network namespace when creating paired devices (veth, vxcan, netkit). This allows an unprivileged user with a user namespace to create interfaces in arbitrary network namespaces, including init_net. Add a netlink_ns_capable() check for CAP_NET_ADMIN in the peer namespace before allowing device creation to proceed. Fixes: 81adee4 ("net: Support specifying the network namespace upon device creation.") Signed-off-by: Nikolaos Gkarlis <nickgarlis@gmail.com> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260402181432.4126920-1-nickgarlis@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 1979645 commit 7b735ef

1 file changed

Lines changed: 27 additions & 13 deletions

File tree

net/core/rtnetlink.c

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3894,28 +3894,42 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm,
38943894
goto out;
38953895
}
38963896

3897-
static struct net *rtnl_get_peer_net(const struct rtnl_link_ops *ops,
3897+
static struct net *rtnl_get_peer_net(struct sk_buff *skb,
3898+
const struct rtnl_link_ops *ops,
38983899
struct nlattr *tbp[],
38993900
struct nlattr *data[],
39003901
struct netlink_ext_ack *extack)
39013902
{
3902-
struct nlattr *tb[IFLA_MAX + 1];
3903+
struct nlattr *tb[IFLA_MAX + 1], **attrs;
3904+
struct net *net;
39033905
int err;
39043906

3905-
if (!data || !data[ops->peer_type])
3906-
return rtnl_link_get_net_ifla(tbp);
3907-
3908-
err = rtnl_nla_parse_ifinfomsg(tb, data[ops->peer_type], extack);
3909-
if (err < 0)
3910-
return ERR_PTR(err);
3911-
3912-
if (ops->validate) {
3913-
err = ops->validate(tb, NULL, extack);
3907+
if (!data || !data[ops->peer_type]) {
3908+
attrs = tbp;
3909+
} else {
3910+
err = rtnl_nla_parse_ifinfomsg(tb, data[ops->peer_type], extack);
39143911
if (err < 0)
39153912
return ERR_PTR(err);
3913+
3914+
if (ops->validate) {
3915+
err = ops->validate(tb, NULL, extack);
3916+
if (err < 0)
3917+
return ERR_PTR(err);
3918+
}
3919+
3920+
attrs = tb;
39163921
}
39173922

3918-
return rtnl_link_get_net_ifla(tb);
3923+
net = rtnl_link_get_net_ifla(attrs);
3924+
if (IS_ERR_OR_NULL(net))
3925+
return net;
3926+
3927+
if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
3928+
put_net(net);
3929+
return ERR_PTR(-EPERM);
3930+
}
3931+
3932+
return net;
39193933
}
39203934

39213935
static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -4054,7 +4068,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
40544068
}
40554069

40564070
if (ops->peer_type) {
4057-
peer_net = rtnl_get_peer_net(ops, tb, data, extack);
4071+
peer_net = rtnl_get_peer_net(skb, ops, tb, data, extack);
40584072
if (IS_ERR(peer_net)) {
40594073
ret = PTR_ERR(peer_net);
40604074
goto put_ops;

0 commit comments

Comments
 (0)