mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
can: replace ARPHRD_CAN type checks with can_get_ml_priv()
Commit4e096a1886("net: introduce CAN specific pointer in the struct net_device") introduced an explicit way to assign the midlayer private pointer (dev->ml_priv) to named users like ML_PRIV_CAN. A valid pointer returned by can_get_ml_priv() therefore identifies a real CAN device. The referenced commit only converted the j1939 and proc code to this check, while the other parts of the CAN subsystem still rely on dev->type == ARPHRD_CAN. The TUNSETLINK ioctl allows a down TUN/TAP device to set its hardware type to ARPHRD_CAN while dev->ml_priv remains NULL. Such a repurposed netdevice passes the ARPHRD_CAN checks. Commit8aa59e3559("can: af_can: fix NULL pointer dereference in can_rx_register()") already made can_rx_register() reject such devices. But can_rx_unregister() still only checks dev->type and dereferences the NULL ml_priv when it walks the receive lists of the device. CAN_ISOTP reaches this path: isotp_bind() ignores the return values of can_rx_register() and binds the socket anyway. When the socket is released or the device is unregistered, isotp_release() and isotp_notify() remove the filters that have never been registered and trigger the NULL pointer dereference in can_rx_unregister(). This only requires owning a TUN/TAP device or CAP_NET_ADMIN in an unprivileged user namespace. Convert the remaining ARPHRD_CAN checks in af_can, bcm, gw, isotp and raw to can_get_ml_priv(). Fixes:4e096a1886("net: introduce CAN specific pointer in the struct net_device") Cc: stable@vger.kernel.org Cc: Oleksij Rempel <o.rempel@pengutronix.de> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> Link: https://patch.msgid.link/20261027-can-rx-lock-v12-1-eb5afc2d8b9b@hartkopp.net Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
parent
d3592ab8a1
commit
962947b695
|
|
@ -226,7 +226,7 @@ int can_send(struct sk_buff *skb, int loop)
|
|||
goto inval_skb;
|
||||
}
|
||||
|
||||
if (unlikely(skb->dev->type != ARPHRD_CAN)) {
|
||||
if (unlikely(!can_get_ml_priv(skb->dev))) {
|
||||
err = -EPERM;
|
||||
goto inval_skb;
|
||||
}
|
||||
|
|
@ -452,7 +452,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,
|
|||
|
||||
/* insert new receiver (dev,canid,mask) -> (func,data) */
|
||||
|
||||
if (dev && (dev->type != ARPHRD_CAN || !can_get_ml_priv(dev)))
|
||||
if (dev && !can_get_ml_priv(dev))
|
||||
return -ENODEV;
|
||||
|
||||
if (dev && !net_eq(net, dev_net(dev)))
|
||||
|
|
@ -519,7 +519,7 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
|
|||
struct can_rcv_lists_stats *rcv_lists_stats = net->can.rcv_lists_stats;
|
||||
struct can_dev_rcv_lists *dev_rcv_lists;
|
||||
|
||||
if (dev && dev->type != ARPHRD_CAN)
|
||||
if (dev && !can_get_ml_priv(dev))
|
||||
return;
|
||||
|
||||
if (dev && !net_eq(net, dev_net(dev)))
|
||||
|
|
@ -684,8 +684,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||
{
|
||||
struct can_skb_ext *csx = can_skb_ext_find(skb);
|
||||
|
||||
if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) ||
|
||||
!csx || !can_is_can_skb(skb))) {
|
||||
if (unlikely(!can_get_ml_priv(dev) || !csx || !can_is_can_skb(skb))) {
|
||||
pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\n",
|
||||
dev->type, skb->len);
|
||||
|
||||
|
|
@ -710,8 +709,7 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||
{
|
||||
struct can_skb_ext *csx = can_skb_ext_find(skb);
|
||||
|
||||
if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) ||
|
||||
!csx || !can_is_canfd_skb(skb))) {
|
||||
if (unlikely(!can_get_ml_priv(dev) || !csx || !can_is_canfd_skb(skb))) {
|
||||
pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\n",
|
||||
dev->type, skb->len);
|
||||
|
||||
|
|
@ -736,8 +734,7 @@ static int canxl_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||
{
|
||||
struct can_skb_ext *csx = can_skb_ext_find(skb);
|
||||
|
||||
if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) ||
|
||||
!csx || !can_is_canxl_skb(skb))) {
|
||||
if (unlikely(!can_get_ml_priv(dev) || !csx || !can_is_canxl_skb(skb))) {
|
||||
pr_warn_once("PF_CAN: dropped non conform CAN XL skbuff: dev type %d, len %d\n",
|
||||
dev->type, skb->len);
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
#include <linux/if_arp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/can/can-ml.h>
|
||||
#include <linux/can/core.h>
|
||||
#include <linux/can/skb.h>
|
||||
#include <linux/can/bcm.h>
|
||||
|
|
@ -1719,7 +1720,7 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
|||
goto out_release;
|
||||
}
|
||||
|
||||
if (dev->type != ARPHRD_CAN) {
|
||||
if (!can_get_ml_priv(dev)) {
|
||||
dev_put(dev);
|
||||
ret = -ENODEV;
|
||||
goto out_release;
|
||||
|
|
@ -1867,7 +1868,7 @@ static int bcm_notifier(struct notifier_block *nb, unsigned long msg,
|
|||
{
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
|
||||
if (dev->type != ARPHRD_CAN)
|
||||
if (!can_get_ml_priv(dev))
|
||||
return NOTIFY_DONE;
|
||||
if (msg != NETDEV_UNREGISTER && msg != NETDEV_DOWN)
|
||||
return NOTIFY_DONE;
|
||||
|
|
@ -2024,7 +2025,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int
|
|||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
if (dev->type != ARPHRD_CAN) {
|
||||
if (!can_get_ml_priv(dev)) {
|
||||
dev_put(dev);
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
#include <linux/if_arp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/can/can-ml.h>
|
||||
#include <linux/can/core.h>
|
||||
#include <linux/can/skb.h>
|
||||
#include <linux/can/gw.h>
|
||||
|
|
@ -612,7 +613,7 @@ static int cgw_notifier(struct notifier_block *nb,
|
|||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
struct net *net = dev_net(dev);
|
||||
|
||||
if (dev->type != ARPHRD_CAN)
|
||||
if (!can_get_ml_priv(dev))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (msg == NETDEV_UNREGISTER) {
|
||||
|
|
@ -1163,7 +1164,7 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
if (!gwj->src.dev)
|
||||
goto out;
|
||||
|
||||
if (gwj->src.dev->type != ARPHRD_CAN)
|
||||
if (!can_get_ml_priv(gwj->src.dev))
|
||||
goto out;
|
||||
|
||||
gwj->dst.dev = __dev_get_by_index(net, gwj->ccgw.dst_idx);
|
||||
|
|
@ -1171,7 +1172,7 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
if (!gwj->dst.dev)
|
||||
goto out;
|
||||
|
||||
if (gwj->dst.dev->type != ARPHRD_CAN)
|
||||
if (!can_get_ml_priv(gwj->dst.dev))
|
||||
goto out;
|
||||
|
||||
/* is sending the skb back to the incoming interface intended? */
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@
|
|||
#include <linux/if_arp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/can/can-ml.h>
|
||||
#include <linux/can/core.h>
|
||||
#include <linux/can/skb.h>
|
||||
#include <linux/can/isotp.h>
|
||||
|
|
@ -1618,7 +1619,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int l
|
|||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
if (dev->type != ARPHRD_CAN) {
|
||||
if (!can_get_ml_priv(dev)) {
|
||||
err = -ENODEV;
|
||||
goto out_put_dev;
|
||||
}
|
||||
|
|
@ -1905,7 +1906,7 @@ static int isotp_notifier(struct notifier_block *nb, unsigned long msg,
|
|||
{
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
|
||||
if (dev->type != ARPHRD_CAN)
|
||||
if (!can_get_ml_priv(dev))
|
||||
return NOTIFY_DONE;
|
||||
if (msg != NETDEV_UNREGISTER && msg != NETDEV_DOWN)
|
||||
return NOTIFY_DONE;
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ static int raw_notifier(struct notifier_block *nb, unsigned long msg,
|
|||
{
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
|
||||
if (dev->type != ARPHRD_CAN)
|
||||
if (!can_get_ml_priv(dev))
|
||||
return NOTIFY_DONE;
|
||||
if (msg != NETDEV_UNREGISTER && msg != NETDEV_DOWN)
|
||||
return NOTIFY_DONE;
|
||||
|
|
@ -491,7 +491,7 @@ static int raw_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int len
|
|||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
if (dev->type != ARPHRD_CAN) {
|
||||
if (!can_get_ml_priv(dev)) {
|
||||
err = -ENODEV;
|
||||
goto out_put_dev;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user