net: validate veth and vxcan peer ifindexes
[ Upstream commitf534f6581e
] veth and vxcan need to make sure the ifindexes of the peer are not negative, core does not validate this. Using iproute2 with user-space-level checking removed: Before: # ./ip link add index 10 type veth peer index -1 # ip link show 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 52:54:00:74:b2:03 brd ff:ff:ff:ff:ff:ff 10: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 8a:90:ff:57:6d:5d brd ff:ff:ff:ff:ff:ff -1: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether ae:ed:18:e6:fa:7f brd ff:ff:ff:ff:ff:ff Now: $ ./ip link add index 10 type veth peer index -1 Error: ifindex can't be negative. This problem surfaced in net-next because an explicit WARN() was added, the root cause is older. Fixes:e6f8f1a739
("veth: Allow to create peer link with given ifindex") Fixes:a8f820a380
("can: add Virtual CAN Tunnel driver (vxcan)") Reported-by: syzbot+5ba06978f34abb058571@syzkaller.appspotmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Reviewed-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Родитель
335be58541
Коммит
ace1b0ae30
|
@ -179,12 +179,7 @@ static int vxcan_newlink(struct net *net, struct net_device *dev,
|
||||||
|
|
||||||
nla_peer = data[VXCAN_INFO_PEER];
|
nla_peer = data[VXCAN_INFO_PEER];
|
||||||
ifmp = nla_data(nla_peer);
|
ifmp = nla_data(nla_peer);
|
||||||
err = rtnl_nla_parse_ifla(peer_tb,
|
err = rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
|
||||||
nla_data(nla_peer) +
|
|
||||||
sizeof(struct ifinfomsg),
|
|
||||||
nla_len(nla_peer) -
|
|
||||||
sizeof(struct ifinfomsg),
|
|
||||||
NULL);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|
|
@ -1654,10 +1654,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
|
||||||
|
|
||||||
nla_peer = data[VETH_INFO_PEER];
|
nla_peer = data[VETH_INFO_PEER];
|
||||||
ifmp = nla_data(nla_peer);
|
ifmp = nla_data(nla_peer);
|
||||||
err = rtnl_nla_parse_ifla(peer_tb,
|
err = rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
|
||||||
nla_data(nla_peer) + sizeof(struct ifinfomsg),
|
|
||||||
nla_len(nla_peer) - sizeof(struct ifinfomsg),
|
|
||||||
NULL);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|
|
@ -175,8 +175,8 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname,
|
||||||
int rtnl_delete_link(struct net_device *dev);
|
int rtnl_delete_link(struct net_device *dev);
|
||||||
int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm);
|
int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm);
|
||||||
|
|
||||||
int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len,
|
int rtnl_nla_parse_ifinfomsg(struct nlattr **tb, const struct nlattr *nla_peer,
|
||||||
struct netlink_ext_ack *exterr);
|
struct netlink_ext_ack *exterr);
|
||||||
struct net *rtnl_get_net_ns_capable(struct sock *sk, int netnsid);
|
struct net *rtnl_get_net_ns_capable(struct sock *sk, int netnsid);
|
||||||
|
|
||||||
#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
|
#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
|
||||||
|
|
|
@ -2173,13 +2173,27 @@ out_err:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len,
|
int rtnl_nla_parse_ifinfomsg(struct nlattr **tb, const struct nlattr *nla_peer,
|
||||||
struct netlink_ext_ack *exterr)
|
struct netlink_ext_ack *exterr)
|
||||||
{
|
{
|
||||||
return nla_parse_deprecated(tb, IFLA_MAX, head, len, ifla_policy,
|
const struct ifinfomsg *ifmp;
|
||||||
|
const struct nlattr *attrs;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
ifmp = nla_data(nla_peer);
|
||||||
|
attrs = nla_data(nla_peer) + sizeof(struct ifinfomsg);
|
||||||
|
len = nla_len(nla_peer) - sizeof(struct ifinfomsg);
|
||||||
|
|
||||||
|
if (ifmp->ifi_index < 0) {
|
||||||
|
NL_SET_ERR_MSG_ATTR(exterr, nla_peer,
|
||||||
|
"ifindex can't be negative");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nla_parse_deprecated(tb, IFLA_MAX, attrs, len, ifla_policy,
|
||||||
exterr);
|
exterr);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(rtnl_nla_parse_ifla);
|
EXPORT_SYMBOL(rtnl_nla_parse_ifinfomsg);
|
||||||
|
|
||||||
struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
|
struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче