Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'linux-can-fixes-for-5.9-20200814' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
pull-request: can 2020-08-14

this is a pull request of 6 patches for net/master. All patches fix problems in
the j1939 CAN networking stack.

The first patch is by Eric Dumazet fixes a kernel-infoleak in
j1939_sk_sock2sockaddr_can().

The remaining 5 patches are by Oleksij Rempel and fix recption of j1939
messages not orginated by the stack, a use-after-free in j1939_tp_txtimer(),
ensure that the CAN driver has a ml_priv allocated. These problem were found by
google's syzbot. Further ETP sessions with block size of less than 255 are
fixed and a sanity check was added to j1939_xtp_rx_dat_one() to detect packet
corruption.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+62 -8
+14
net/can/j1939/socket.c
··· 398 398 spin_lock_init(&jsk->sk_session_queue_lock); 399 399 INIT_LIST_HEAD(&jsk->sk_session_queue); 400 400 sk->sk_destruct = j1939_sk_sock_destruct; 401 + sk->sk_protocol = CAN_J1939; 401 402 402 403 return 0; 403 404 } ··· 462 461 } 463 462 464 463 if (ndev->type != ARPHRD_CAN) { 464 + dev_put(ndev); 465 + ret = -ENODEV; 466 + goto out_release_sock; 467 + } 468 + 469 + if (!ndev->ml_priv) { 470 + netdev_warn_once(ndev, 471 + "No CAN mid layer private allocated, please fix your driver and use alloc_candev()!\n"); 465 472 dev_put(ndev); 466 473 ret = -ENODEV; 467 474 goto out_release_sock; ··· 562 553 static void j1939_sk_sock2sockaddr_can(struct sockaddr_can *addr, 563 554 const struct j1939_sock *jsk, int peer) 564 555 { 556 + /* There are two holes (2 bytes and 3 bytes) to clear to avoid 557 + * leaking kernel information to user space. 558 + */ 559 + memset(addr, 0, J1939_MIN_NAMELEN); 560 + 565 561 addr->can_family = AF_CAN; 566 562 addr->can_ifindex = jsk->ifindex; 567 563 addr->can_addr.j1939.pgn = jsk->addr.pgn;
+48 -8
net/can/j1939/transport.c
··· 352 352 skb_queue_tail(&session->skb_queue, skb); 353 353 } 354 354 355 - static struct sk_buff *j1939_session_skb_find(struct j1939_session *session) 355 + static struct 356 + sk_buff *j1939_session_skb_find_by_offset(struct j1939_session *session, 357 + unsigned int offset_start) 356 358 { 357 359 struct j1939_priv *priv = session->priv; 360 + struct j1939_sk_buff_cb *do_skcb; 358 361 struct sk_buff *skb = NULL; 359 362 struct sk_buff *do_skb; 360 - struct j1939_sk_buff_cb *do_skcb; 361 - unsigned int offset_start; 362 363 unsigned long flags; 363 - 364 - offset_start = session->pkt.dpo * 7; 365 364 366 365 spin_lock_irqsave(&session->skb_queue.lock, flags); 367 366 skb_queue_walk(&session->skb_queue, do_skb) { ··· 379 380 skb_queue_len(&session->skb_queue)); 380 381 381 382 return skb; 383 + } 384 + 385 + static struct sk_buff *j1939_session_skb_find(struct j1939_session *session) 386 + { 387 + unsigned int offset_start; 388 + 389 + offset_start = session->pkt.dpo * 7; 390 + return j1939_session_skb_find_by_offset(session, offset_start); 382 391 } 383 392 384 393 /* see if we are receiver ··· 773 766 int ret = 0; 774 767 u8 dat[8]; 775 768 776 - se_skb = j1939_session_skb_find(session); 769 + se_skb = j1939_session_skb_find_by_offset(session, session->pkt.tx * 7); 777 770 if (!se_skb) 778 771 return -ENOBUFS; 779 772 ··· 793 786 len = se_skb->len - offset; 794 787 if (len > 7) 795 788 len = 7; 789 + 790 + if (offset + len > se_skb->len) { 791 + netdev_err_once(priv->ndev, 792 + "%s: 0x%p: requested data outside of queued buffer: offset %i, len %i, pkt.tx: %i\n", 793 + __func__, session, skcb->offset, se_skb->len , session->pkt.tx); 794 + return -EOVERFLOW; 795 + } 796 + 797 + if (!len) { 798 + ret = -ENOBUFS; 799 + break; 800 + } 796 801 797 802 memcpy(&dat[1], &tpdat[offset], len); 798 803 ret = j1939_tp_tx_dat(session, dat, len + 1); ··· 1138 1119 * error, but let j1939_cancel_all_active_sessions() do the 1139 1120 * cleanup including propagation of the error to user space. 1140 1121 */ 1122 + break; 1123 + case -EOVERFLOW: 1124 + j1939_session_cancel(session, J1939_XTP_ABORT_ECTS_TOO_BIG); 1141 1125 break; 1142 1126 case 0: 1143 1127 session->tx_retry = 0; ··· 1772 1750 __func__, session); 1773 1751 goto out_session_cancel; 1774 1752 } 1775 - se_skb = j1939_session_skb_find(session); 1753 + 1754 + se_skb = j1939_session_skb_find_by_offset(session, packet * 7); 1776 1755 if (!se_skb) { 1777 1756 netdev_warn(priv->ndev, "%s: 0x%p: no skb found\n", __func__, 1778 1757 session); ··· 1792 1769 } 1793 1770 1794 1771 tpdat = se_skb->data; 1795 - memcpy(&tpdat[offset], &dat[1], nbytes); 1772 + if (!session->transmission) { 1773 + memcpy(&tpdat[offset], &dat[1], nbytes); 1774 + } else { 1775 + int err; 1776 + 1777 + err = memcmp(&tpdat[offset], &dat[1], nbytes); 1778 + if (err) 1779 + netdev_err_once(priv->ndev, 1780 + "%s: 0x%p: Data of RX-looped back packet (%*ph) doesn't match TX data (%*ph)!\n", 1781 + __func__, session, 1782 + nbytes, &dat[1], 1783 + nbytes, &tpdat[offset]); 1784 + } 1785 + 1796 1786 if (packet == session->pkt.rx) 1797 1787 session->pkt.rx++; 1798 1788 ··· 2051 2015 struct j1939_session *session; 2052 2016 2053 2017 if (!skb->sk) 2018 + return; 2019 + 2020 + if (skb->sk->sk_family != AF_CAN || 2021 + skb->sk->sk_protocol != CAN_J1939) 2054 2022 return; 2055 2023 2056 2024 j1939_session_list_lock(priv);