]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
can: isotp: sanitize CAN ID checks in isotp_bind()
authorOliver Hartkopp <socketcan@hartkopp.net>
Wed, 16 Mar 2022 16:42:56 +0000 (17:42 +0100)
committerStefan Bader <stefan.bader@canonical.com>
Fri, 20 May 2022 12:39:13 +0000 (14:39 +0200)
BugLink: https://bugs.launchpad.net/bugs/1969110
commit 3ea566422cbde9610c2734980d1286ab681bb40e upstream.

Syzbot created an environment that lead to a state machine status that
can not be reached with a compliant CAN ID address configuration.
The provided address information consisted of CAN ID 0x6000001 and 0xC28001
which both boil down to 11 bit CAN IDs 0x001 in sending and receiving.

Sanitize the SFF/EFF CAN ID values before performing the address checks.

Fixes: e057dd3fc20f ("can: add ISO 15765-2:2016 transport protocol")
Link: https://lore.kernel.org/all/20220316164258.54155-1-socketcan@hartkopp.net
Reported-by: syzbot+2339c27f5c66c652843e@syzkaller.appspotmail.com
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit f343dbe82314ab457153c9afd970be4e9e553020)
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
net/can/isotp.c

index d2a430b6a13bd2974adf02be1fe14e1886db7439..f8e3aeb79e3fb127b5edeb84164215916d3d3b96 100644 (file)
@@ -1104,6 +1104,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
        struct net *net = sock_net(sk);
        int ifindex;
        struct net_device *dev;
+       canid_t tx_id, rx_id;
        int err = 0;
        int notify_enetdown = 0;
        int do_rx_reg = 1;
@@ -1111,8 +1112,18 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
        if (len < ISOTP_MIN_NAMELEN)
                return -EINVAL;
 
-       if (addr->can_addr.tp.tx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG))
-               return -EADDRNOTAVAIL;
+       /* sanitize tx/rx CAN identifiers */
+       tx_id = addr->can_addr.tp.tx_id;
+       if (tx_id & CAN_EFF_FLAG)
+               tx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK);
+       else
+               tx_id &= CAN_SFF_MASK;
+
+       rx_id = addr->can_addr.tp.rx_id;
+       if (rx_id & CAN_EFF_FLAG)
+               rx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK);
+       else
+               rx_id &= CAN_SFF_MASK;
 
        if (!addr->can_ifindex)
                return -ENODEV;
@@ -1124,21 +1135,13 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
                do_rx_reg = 0;
 
        /* do not validate rx address for functional addressing */
-       if (do_rx_reg) {
-               if (addr->can_addr.tp.rx_id == addr->can_addr.tp.tx_id) {
-                       err = -EADDRNOTAVAIL;
-                       goto out;
-               }
-
-               if (addr->can_addr.tp.rx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG)) {
-                       err = -EADDRNOTAVAIL;
-                       goto out;
-               }
+       if (do_rx_reg && rx_id == tx_id) {
+               err = -EADDRNOTAVAIL;
+               goto out;
        }
 
        if (so->bound && addr->can_ifindex == so->ifindex &&
-           addr->can_addr.tp.rx_id == so->rxid &&
-           addr->can_addr.tp.tx_id == so->txid)
+           rx_id == so->rxid && tx_id == so->txid)
                goto out;
 
        dev = dev_get_by_index(net, addr->can_ifindex);
@@ -1162,8 +1165,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
        ifindex = dev->ifindex;
 
        if (do_rx_reg)
-               can_rx_register(net, dev, addr->can_addr.tp.rx_id,
-                               SINGLE_MASK(addr->can_addr.tp.rx_id),
+               can_rx_register(net, dev, rx_id, SINGLE_MASK(rx_id),
                                isotp_rcv, sk, "isotp", sk);
 
        dev_put(dev);
@@ -1183,8 +1185,8 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
 
        /* switch to new settings */
        so->ifindex = ifindex;
-       so->rxid = addr->can_addr.tp.rx_id;
-       so->txid = addr->can_addr.tp.tx_id;
+       so->rxid = rx_id;
+       so->txid = tx_id;
        so->bound = 1;
 
 out: