* [PATCH net 1/9] can: bcm: copy the CAN frames outside of lock_sock()
2026-11-15 9:54 [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
@ 2026-11-15 9:54 ` Marc Kleine-Budde
2026-11-15 9:54 ` [PATCH net 2/9] can: bcm: do not remove the procfs entry in bcm_notify() Marc Kleine-Budde
` (9 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2026-11-15 9:54 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Oliver Hartkopp, stable,
Marc Kleine-Budde
From: Oliver Hartkopp <socketcan@hartkopp.net>
bcm_sendmsg() copies the CAN frames of TX_SETUP, RX_SETUP and TX_SEND
from user space while holding lock_sock(). A copy that faults or
stalls, e.g. on a FUSE backed mapping, holds lock_sock() for its whole
duration.
bcm_notify() takes lock_sock() of every CAN_BCM socket in the namespace
of a vanishing CAN device while holding RTNL, independent of the
binding of the socket. So a stalled copy on any CAN_BCM socket can
block RTNL on the unregistration or namespace change of a CAN device in
this namespace, e.g. of a vcan device in an unprivileged user and
network namespace.
Copy the CAN frames that the opcode handler reads to kernel memory
before lock_sock() and hand them to the handlers with a kvec based
msghdr. bcm_tx_setup(), bcm_rx_setup() and bcm_tx_send() keep their
checks and read the frames with memcpy_from_msg() as before. Up to
sizeof(struct canfd_frame) bytes, i.e. a single CAN FD frame or up to
four CAN CC frames, are copied to a buffer on the stack, more frames to
a kvmalloc() buffer of up to MAX_NFRAMES + 1 CAN FD frames.
As the frames are copied before lock_sock() now, a failing copy is
reported before the error conditions that are checked under
lock_sock(). This is in line with POSIX, which does not define an
order in which multiple error conditions are detected and reported.
The generic SOL_SOCKET options in sk_setsockopt() and sk_getsockopt(),
e.g. SO_ATTACH_FILTER, still access user space under the socket lock.
This is not specific to CAN_BCM and not addressed by this patch.
Fixes: ffd980f976e7 ("[CAN]: Add broadcast manager (bcm) protocol")
Cc: stable@vger.kernel.org
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20261113-can-bcmlock-memcg-v5-1-634c0e04bc72@hartkopp.net
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
net/can/bcm.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 52 insertions(+), 3 deletions(-)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 7bd2aa39777a..3f4c8d828337 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -1643,6 +1643,11 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
struct bcm_sock *bo = bcm_sk(sk);
int ifindex;
struct bcm_msg_head msg_head;
+ struct msghdr fmsg = {}; /* CAN frames copied to kernel memory */
+ struct kvec kv;
+ struct canfd_frame sframe; /* stack buffer for up to CANFD_MTU bytes */
+ void *frames = &sframe;
+ size_t flen = 0;
int cfsiz;
int ret; /* read bytes or error codes as return value */
@@ -1663,6 +1668,47 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if ((size - MHSIZ) % cfsiz)
return -EINVAL;
+ /* Copy the CAN frames from user space before lock_sock(), so a
+ * stalled copy can not block bcm_notify() waiting for lock_sock()
+ * under RTNL. Only the frames the opcode handler reads are copied.
+ * The handlers keep their checks and read the frames from fmsg.
+ */
+ switch (msg_head.opcode) {
+ case TX_SETUP:
+ if (msg_head.nframes >= 1 && msg_head.nframes <= MAX_NFRAMES)
+ flen = msg_head.nframes * cfsiz;
+ break;
+
+ case RX_SETUP:
+ if (!(msg_head.flags & RX_FILTER_ID) &&
+ msg_head.nframes <= MAX_NFRAMES + 1)
+ flen = msg_head.nframes * cfsiz;
+ break;
+
+ case TX_SEND:
+ if (msg_head.nframes == 1 && size == cfsiz + MHSIZ)
+ flen = cfsiz;
+ break;
+ }
+
+ /* a message with missing frames still fails in the handler */
+ flen = min(flen, msg_data_left(msg));
+
+ if (flen > sizeof(sframe)) {
+ frames = kvmalloc(flen, GFP_KERNEL);
+ if (!frames)
+ return -ENOMEM;
+ }
+
+ if (!copy_from_iter_full(frames, flen, &msg->msg_iter)) {
+ ret = -EFAULT;
+ goto out_free;
+ }
+
+ kv.iov_base = frames;
+ kv.iov_len = flen;
+ iov_iter_kvec(&fmsg.msg_iter, ITER_SOURCE, &kv, 1, flen);
+
lock_sock(sk);
/* Re-validate under the socket lock: a concurrent bcm_notify()
@@ -1721,11 +1767,11 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
switch (msg_head.opcode) {
case TX_SETUP:
- ret = bcm_tx_setup(&msg_head, msg, ifindex, sk);
+ ret = bcm_tx_setup(&msg_head, &fmsg, ifindex, sk);
break;
case RX_SETUP:
- ret = bcm_rx_setup(&msg_head, msg, ifindex, sk);
+ ret = bcm_rx_setup(&msg_head, &fmsg, ifindex, sk);
break;
case TX_DELETE:
@@ -1759,7 +1805,7 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if ((msg_head.nframes != 1) || (size != cfsiz + MHSIZ))
ret = -EINVAL;
else
- ret = bcm_tx_send(msg, ifindex, sk, cfsiz);
+ ret = bcm_tx_send(&fmsg, ifindex, sk, cfsiz);
break;
default:
@@ -1769,6 +1815,9 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
out_release:
release_sock(sk);
+out_free:
+ if (frames != &sframe)
+ kvfree(frames);
return ret;
}
base-commit: aa40afa831ebfe45e40a23721711059f2ac584d4
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH net 2/9] can: bcm: do not remove the procfs entry in bcm_notify()
2026-11-15 9:54 [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
2026-11-15 9:54 ` [PATCH net 1/9] can: bcm: copy the CAN frames outside of lock_sock() Marc Kleine-Budde
@ 2026-11-15 9:54 ` Marc Kleine-Budde
2026-11-15 9:54 ` [PATCH net 3/9] can: netlink: fix static FD-NON-ISO mode validation Marc Kleine-Budde
` (8 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2026-11-15 9:54 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Oliver Hartkopp, stable,
Marc Kleine-Budde
From: Oliver Hartkopp <socketcan@hartkopp.net>
bcm_notify() removes the procfs entry of a CAN_BCM socket that is bound
to a vanishing CAN device with remove_proc_entry() while holding RTNL.
remove_proc_entry() waits for all running readers of this entry. A
reader of /proc/net/can-bcm/<inode> that stalls in its copy to user
space, e.g. on a FUSE backed mapping, therefore blocks RTNL on the
unregistration or namespace change of the bound CAN device.
The entry has been removed in bcm_notify() so that a later
bcm_connect() of the unbound socket can register it again without a
"proc_dir_entry already registered" warning.
The CAN_BCM socket itself stays usable after a NETDEV_UNREGISTER:
bcm_notify() only unbinds it and reports ENODEV, so the application can
connect() the socket again, e.g. to a re-created CAN device. The name
of the procfs entry is the inode number of the socket, which does not
change until the socket is closed.
Keep the procfs entry until bcm_release() instead, which removes it
after the socket has left the notifier list and without holding RTNL.
bcm_connect() only creates the entry, if it does not exist yet.
bcm_proc_show() reports an unbound socket as "unbound" instead of
showing the cleared ifindex as "any".
As bcm_proc_show() can now run while the socket is bound or unbound, it
reads bo->ifindex locklessly with READ_ONCE() and the writers use
WRITE_ONCE(). The NETDEV_DOWN handling in bcm_notify(), which runs
without lock_sock(), reads bo->bound and bo->ifindex with READ_ONCE()
as well. bo->ifindex is still only modified under lock_sock(). A
concurrent bind or unbind may show an intermediate state in the procfs
output, which is acceptable for this debug information.
Fixes: 76fe372ccb81 ("can: bcm: Remove proc entry when dev is unregistered.")
Cc: stable@vger.kernel.org
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20261113-can-bcmlock-memcg-v5-2-634c0e04bc72@hartkopp.net
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
net/can/bcm.c | 33 +++++++++++++++------------------
1 file changed, 15 insertions(+), 18 deletions(-)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 3f4c8d828337..1595b7720c98 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -219,11 +219,16 @@ static int bcm_proc_show(struct seq_file *m, void *v)
struct net *net = m->private;
struct sock *sk = (struct sock *)pde_data(m->file->f_inode);
struct bcm_sock *bo = bcm_sk(sk);
+ int ifindex = READ_ONCE(bo->ifindex);
struct bcm_op *op;
seq_printf(m, ">>> sock inode %s", bo->procname);
seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs);
- seq_printf(m, " / bound %s", bcm_proc_getifname(net, ifname, bo->ifindex));
+ if (READ_ONCE(bo->bound))
+ seq_printf(m, " / bound %s",
+ bcm_proc_getifname(net, ifname, ifindex));
+ else
+ seq_puts(m, " / unbound");
seq_printf(m, " <<<\n");
rcu_read_lock();
@@ -1866,19 +1871,9 @@ static void bcm_notify(struct bcm_sock *bo, unsigned long msg,
/* remove device reference, if this is our bound device */
if (bo->bound && bo->ifindex == dev->ifindex) {
-#if IS_ENABLED(CONFIG_PROC_FS)
- if (sock_net(sk)->can.bcmproc_dir && bo->bcm_proc_read) {
- remove_proc_entry(bo->procname, sock_net(sk)->can.bcmproc_dir);
- bo->bcm_proc_read = NULL;
- }
-#endif
- /* Paired with the lockless fast-path check in
- * bcm_sendmsg(); bo->ifindex itself is only ever
- * accessed under lock_sock() so it needs no
- * annotation.
- */
+ /* pairs with the lockless check in bcm_sendmsg() */
WRITE_ONCE(bo->bound, 0);
- bo->ifindex = 0;
+ WRITE_ONCE(bo->ifindex, 0);
notify_enodev = 1;
}
@@ -1892,7 +1887,8 @@ static void bcm_notify(struct bcm_sock *bo, unsigned long msg,
break;
case NETDEV_DOWN:
- if (bo->bound && bo->ifindex == dev->ifindex) {
+ if (READ_ONCE(bo->bound) &&
+ READ_ONCE(bo->ifindex) == dev->ifindex) {
sk->sk_err = ENETDOWN;
if (!sock_flag(sk, SOCK_DEAD))
sk_error_report(sk);
@@ -2013,7 +2009,7 @@ static int bcm_release(struct socket *sock)
/* remove device reference */
if (bo->bound) {
WRITE_ONCE(bo->bound, 0);
- bo->ifindex = 0;
+ WRITE_ONCE(bo->ifindex, 0);
}
sock_orphan(sk);
@@ -2060,16 +2056,17 @@ static int bcm_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int
goto fail;
}
- bo->ifindex = dev->ifindex;
+ WRITE_ONCE(bo->ifindex, dev->ifindex);
dev_put(dev);
} else {
/* no interface reference for ifindex = 0 ('any' CAN device) */
- bo->ifindex = 0;
+ WRITE_ONCE(bo->ifindex, 0);
}
#if IS_ENABLED(CONFIG_PROC_FS)
- if (net->can.bcmproc_dir) {
+ /* create the procfs entry once, it is removed in bcm_release() */
+ if (net->can.bcmproc_dir && !bo->bcm_proc_read) {
/* use unique socket inode number as filename */
snprintf(bo->procname, sizeof(bo->procname),
"%llu", sock_i_ino(sk));
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH net 3/9] can: netlink: fix static FD-NON-ISO mode validation
2026-11-15 9:54 [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
2026-11-15 9:54 ` [PATCH net 1/9] can: bcm: copy the CAN frames outside of lock_sock() Marc Kleine-Budde
2026-11-15 9:54 ` [PATCH net 2/9] can: bcm: do not remove the procfs entry in bcm_notify() Marc Kleine-Budde
@ 2026-11-15 9:54 ` Marc Kleine-Budde
2026-11-15 9:54 ` [PATCH net 4/9] can: raw: use a private mutex instead of lock_sock() Marc Kleine-Budde
` (7 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2026-11-15 9:54 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, linux-can, kernel, Zhu Ling, stable,
Marc Kleine-Budde
From: Zhu Ling <zhuling0805@qq.com>
The static CAN_CTRLMODE_FD_NON_ISO mode does not have to be specified when
CAN FD is disabled. Since commit 6742ca18cb41 ("can: netlink: add userland
error messages"), ctrlstatic_missing is calculated before applying this
exception. Disabling CAN FD on a controller with static FD-NON-ISO mode
therefore fails with -EOPNOTSUPP.
Apply the exception to ctrlstatic_missing instead of modifying ctrlstatic.
Keep the original static mode mask and restore it after applying the
userspace mask, so a request that disables CAN FD cannot remove
CAN_CTRLMODE_FD_NON_ISO from priv->ctrlmode.
Fixes: 6742ca18cb41 ("can: netlink: add userland error messages")
Cc: stable@vger.kernel.org
Signed-off-by: Zhu Ling <zhuling0805@qq.com>
Reviewed-by: Marc Kleine-Budde <mkl@pengutronix.de>
Link: https://patch.msgid.link/tencent_3A964832542399A780E646D6A6246335C409@qq.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
Notes:
FAQ:
Q: What about netlink payload size underestimation in can_get_size() for
the IFLA_CAN_BITRATE_MAX attribute.
A: This issue will be fixed in a follow up patch, to ease backporting to
stable.
Q: What about netlink payload size underestimation in `can_pwm_get_size()`
when PWM capabilities exist but `CAN_CTRLMODE_XL_TMS` is disabled?
A: This issue will be fixed in a follow up patch, to ease backporting to
stable.
drivers/net/can/dev/netlink.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index 081dfddda000..0cd55613a616 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -332,7 +332,7 @@ static int can_ctrlmode_changelink(struct net_device *dev,
/* do not check for static fd-non-iso if 'fd' is disabled */
if (!(maskedflags & CAN_CTRLMODE_FD))
- ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO;
+ ctrlstatic_missing &= ~CAN_CTRLMODE_FD_NON_ISO;
if (ctrlstatic_missing) {
NL_SET_ERR_MSG_FMT(extack,
@@ -357,9 +357,9 @@ static int can_ctrlmode_changelink(struct net_device *dev,
priv->ctrlmode &= ~(CAN_CTRLMODE_XL_TDC_MASK |
CAN_CTRLMODE_XL_TMS);
- /* clear bits to be modified and copy the flag values */
+ /* clear bits to be modified, copy flags and restore static modes */
priv->ctrlmode &= ~cm->mask;
- priv->ctrlmode |= maskedflags;
+ priv->ctrlmode |= maskedflags | ctrlstatic;
/* Wipe potential leftovers from previous CAN FD/XL config */
if (!(priv->ctrlmode & CAN_CTRLMODE_FD)) {
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH net 4/9] can: raw: use a private mutex instead of lock_sock()
2026-11-15 9:54 [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
` (2 preceding siblings ...)
2026-11-15 9:54 ` [PATCH net 3/9] can: netlink: fix static FD-NON-ISO mode validation Marc Kleine-Budde
@ 2026-11-15 9:54 ` Marc Kleine-Budde
2026-11-15 9:54 ` [PATCH net 5/9] can: netlink: fix IFLA_CAN_BITRATE_MAX attribute sizing Marc Kleine-Budde
` (6 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2026-11-15 9:54 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Oliver Hartkopp, stable,
Marc Kleine-Budde
From: Oliver Hartkopp <socketcan@hartkopp.net>
raw_notify() takes lock_sock() of the sockets that are bound to a
vanishing CAN device while holding RTNL. Any path that holds the socket
lock while accessing user space can therefore block RTNL. Since
commit 43c973a0887d ("can: raw, isotp: copy socket options outside of
lock_sock()") the CAN_RAW specific socket options copy their values
outside of the socket lock, but the generic SOL_SOCKET options in
sk_setsockopt() and sk_getsockopt() still access user space under
sockopt_lock_sock(), e.g. for SO_ATTACH_FILTER, SO_LINGER or SO_TXTIME.
A stalled copy, e.g. on a FUSE backed mapping, then blocks raw_notify()
and RTNL on the unregistration or namespace change of the bound CAN
device.
CAN_RAW only uses lock_sock() to serialize its own state: the binding,
the filters and the CAN_RAW socket options. It does not use the socket
backlog, as raw_rcv() queues the frames directly to the socket.
Replace lock_sock() with the mutex conf_lock in struct raw_sock. The
generic socket options do not take this mutex, so they can not block
raw_notify() anymore. No user space access happens while the mutex is
held. The memory allocations for the CAN receivers in can_rx_register()
are still done under the mutex, as they have been under lock_sock()
before.
Sashiko suggested to hold not only the filter copy in raw_getsockopt()
under the new conf_lock mutex but to also protect ro->raw_vcid_opts.
This change will be addressed in a follow-up patch as it goes beyond a
simple lock replacement intended for stable.
Fixes: c18ce101f2e4 ("[CAN]: Add raw protocol")
Cc: stable@vger.kernel.org # depends on "can: raw, isotp: copy socket options outside of lock_sock()"
Tested-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20261113-can-bcmlock-memcg-v5-3-634c0e04bc72@hartkopp.net
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
net/can/raw.c | 41 ++++++++++++++++++++++-------------------
1 file changed, 22 insertions(+), 19 deletions(-)
diff --git a/net/can/raw.c b/net/can/raw.c
index f14270b56f52..b69eaadc5e93 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -103,6 +103,7 @@ struct raw_sock {
struct can_filter dfilter; /* default/single filter */
struct can_filter *filter; /* pointer to filter(s) */
struct uniqframe __percpu *uniq;
+ struct mutex conf_lock; /* protects bind, filters and setsockopt */
};
static LIST_HEAD(raw_notifier_list);
@@ -319,7 +320,7 @@ static void raw_notify(struct raw_sock *ro, unsigned long msg,
/* Lockless fast path, ro->bind_dev covers a concurrent bind().
* Read it before ro->dev, pairs with smp_store_release() in
- * raw_bind(). A stale ro->bind_dev only costs a lock_sock().
+ * raw_bind(). A stale ro->bind_dev only costs a mutex_lock().
*/
bind_dev = smp_load_acquire(&ro->bind_dev);
if (READ_ONCE(ro->dev) != dev &&
@@ -328,9 +329,9 @@ static void raw_notify(struct raw_sock *ro, unsigned long msg,
switch (msg) {
case NETDEV_UNREGISTER:
- lock_sock(sk);
+ mutex_lock(&ro->conf_lock);
if (ro->dev != dev) {
- release_sock(sk);
+ mutex_unlock(&ro->conf_lock);
break;
}
@@ -351,7 +352,7 @@ static void raw_notify(struct raw_sock *ro, unsigned long msg,
sk->sk_err = ENODEV;
if (!sock_flag(sk, SOCK_DEAD))
sk_error_report(sk);
- release_sock(sk);
+ mutex_unlock(&ro->conf_lock);
break;
case NETDEV_DOWN:
@@ -401,6 +402,7 @@ static int raw_init(struct sock *sk)
ro->ifindex = 0;
ro->dev = NULL;
ro->bind_dev = NULL;
+ mutex_init(&ro->conf_lock);
/* set default filter to single entry dfilter */
ro->dfilter.can_id = 0;
@@ -451,7 +453,7 @@ static int raw_release(struct socket *sock)
list_del(&ro->notifier);
spin_unlock(&raw_notifier_lock);
- lock_sock(sk);
+ mutex_lock(&ro->conf_lock);
/* remove current filters & unregister
* the tracked reference ro->dev keeps the device's receive lists
@@ -474,11 +476,11 @@ static int raw_release(struct socket *sock)
ro->dev = NULL;
ro->count = 0;
+ mutex_unlock(&ro->conf_lock);
+
sock_orphan(sk);
sock->sk = NULL;
- release_sock(sk);
-
sock_prot_inuse_add(net, sk->sk_prot, -1);
sock_put(sk);
@@ -500,8 +502,8 @@ static int raw_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int len
if (addr->can_family != AF_CAN)
return -EINVAL;
- /* lock_sock() serializes the binding with raw_notify() */
- lock_sock(sk);
+ /* ro->conf_lock serializes the binding with raw_notify() */
+ mutex_lock(&ro->conf_lock);
if (ro->bound && addr->can_ifindex == ro->ifindex)
goto out;
@@ -581,7 +583,7 @@ static int raw_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int len
sk_error_report(sk);
}
- release_sock(sk);
+ mutex_unlock(&ro->conf_lock);
return err;
}
@@ -621,7 +623,7 @@ static int raw_setsockopt_locked(struct socket *sock, int optname,
*
* The reg_state check is only a shortcut: On a concurrent
* unregistration or namespace change raw_notify() waits for
- * lock_sock() and removes the filters set here.
+ * ro->conf_lock and removes the filters set here.
*/
dev = ro->dev;
if (ro->bound && dev &&
@@ -730,6 +732,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
sockptr_t optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
+ struct raw_sock *ro = raw_sk(sk);
struct can_filter *filter = NULL; /* dyn. alloc'ed filters */
struct can_filter sfilter; /* single filter */
union {
@@ -744,9 +747,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
if (level != SOL_CAN_RAW)
return -EINVAL;
- /* Copy the option values from user space before lock_sock(), so a
- * stalled copy can not block raw_notify() waiting for lock_sock()
- * under RTNL.
+ /* Copy the option values from user space before taking ro->conf_lock,
+ * so a stalled copy can not block raw_notify() waiting for
+ * ro->conf_lock under RTNL.
*/
switch (optname) {
case CAN_RAW_FILTER:
@@ -798,11 +801,11 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
return -EFAULT;
}
- lock_sock(sk);
+ mutex_lock(&ro->conf_lock);
err = raw_setsockopt_locked(sock, optname, &val, filter, count);
- release_sock(sk);
+ mutex_unlock(&ro->conf_lock);
/* on error free the filters allocated for CAN_RAW_FILTER above */
if (err && count > 1)
@@ -831,7 +834,7 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
struct can_filter *filter = NULL;
int err = 0;
- lock_sock(sk);
+ mutex_lock(&ro->conf_lock);
if (ro->count > 0) {
int fsize = ro->count * sizeof(struct can_filter);
@@ -843,7 +846,7 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
} else {
if (len > fsize)
len = fsize;
- /* copy to user space after release_sock() */
+ /* copy to user space after mutex_unlock() */
filter = kmemdup(ro->filter, len, GFP_KERNEL);
if (!filter)
err = -ENOMEM;
@@ -851,7 +854,7 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
} else {
len = 0;
}
- release_sock(sk);
+ mutex_unlock(&ro->conf_lock);
if (filter) {
if (copy_to_iter(filter, len, &opt->iter_out) != len)
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH net 5/9] can: netlink: fix IFLA_CAN_BITRATE_MAX attribute sizing
2026-11-15 9:54 [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
` (3 preceding siblings ...)
2026-11-15 9:54 ` [PATCH net 4/9] can: raw: use a private mutex instead of lock_sock() Marc Kleine-Budde
@ 2026-11-15 9:54 ` Marc Kleine-Budde
2026-11-15 9:54 ` [PATCH net 6/9] can: isotp: use a private mutex instead of lock_sock() Marc Kleine-Budde
` (5 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2026-11-15 9:54 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Zhu Ling, stable,
Marc Kleine-Budde, Sashiko
From: Zhu Ling <zhuling0805@qq.com>
can_fill_info() emits IFLA_CAN_BITRATE_MAX with nla_put(), which consumes
space for both the attribute header and its aligned payload. However,
can_get_size() accounts for the payload only. The resulting underestimate
can make filling the netlink response fail with -EMSGSIZE when the skb has
no remaining slack.
Use nla_total_size() to account for the complete attribute.
Fixes: 2290aefa2e90 ("can: dev: Add support for limiting configured bitrate")
Cc: stable@vger.kernel.org
Signed-off-by: Zhu Ling <zhuling0805@qq.com>
Reviewed-by: Marc Kleine-Budde <mkl@pengutronix.de>
Link: https://patch.msgid.link/tencent_D1C873B86B0E92011A264B0E196B911D5308@qq.com
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/bug/linux-3924d490-baed-49dc-880a-6fd1163cf08d
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
Notes:
FAQ:
Q: What about netlink payload size underestimation in `can_pwm_get_size()`
when PWM capabilities exist but `CAN_CTRLMODE_XL_TMS` is disabled?
A: This issue will be fixed in a follow up patch, to ease backporting to
stable.
drivers/net/can/dev/netlink.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index 0cd55613a616..c0367c9e65f4 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -825,7 +825,7 @@ static size_t can_get_size(const struct net_device *dev)
if (priv->bitrate_const) /* IFLA_CAN_BITRATE_CONST */
size += nla_total_size(sizeof(*priv->bitrate_const) *
priv->bitrate_const_cnt);
- size += sizeof(priv->bitrate_max); /* IFLA_CAN_BITRATE_MAX */
+ size += nla_total_size(sizeof(priv->bitrate_max)); /* IFLA_CAN_BITRATE_MAX */
size += can_ctrlmode_ext_get_size(); /* IFLA_CAN_CTRLMODE_EXT */
size += can_data_bittiming_get_size(dev, &priv->fd,
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH net 6/9] can: isotp: use a private mutex instead of lock_sock()
2026-11-15 9:54 [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
` (4 preceding siblings ...)
2026-11-15 9:54 ` [PATCH net 5/9] can: netlink: fix IFLA_CAN_BITRATE_MAX attribute sizing Marc Kleine-Budde
@ 2026-11-15 9:54 ` Marc Kleine-Budde
2026-11-15 9:54 ` [PATCH net 7/9] can: netlink: fix CAN XL PWM attribute sizing Marc Kleine-Budde
` (4 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2026-11-15 9:54 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Oliver Hartkopp, stable,
Marc Kleine-Budde
From: Oliver Hartkopp <socketcan@hartkopp.net>
isotp_notify() takes lock_sock() of a socket that is bound to a
vanishing CAN device while holding RTNL. Any path that holds the socket
lock while accessing user space can therefore block RTNL. Since
commit 43c973a0887d ("can: raw, isotp: copy socket options outside of
lock_sock()") the CAN_ISOTP specific socket options copy their values
outside of the socket lock, but the generic SOL_SOCKET options in
sk_setsockopt() and sk_getsockopt() still access user space under
sockopt_lock_sock(), e.g. for SO_ATTACH_FILTER, SO_LINGER or SO_TXTIME.
CAN_ISOTP only uses lock_sock() to serialize the binding and the
CAN_ISOTP socket options. It does not use the socket backlog, as the
received PDUs are queued directly to the socket.
Replace lock_sock() with the mutex conf_lock in struct isotp_sock. The
generic socket options do not take this mutex, so they can not block
isotp_notify() anymore. No user space access happens while the mutex is
held. The memory allocations for the CAN receivers in isotp_bind() are
still done under the mutex, as they have been under lock_sock() before.
isotp_release() drops the mutex before synchronize_rcu() and the
hrtimer cancellation, as the socket has already left the notifier list
at this point.
Following a Sashiko feedback for raw.c it would make sense to copy the
content in isotp_getsockopt() under the new conf_lock mutex too.
This change will be addressed in a follow-up patch as it goes beyond a
simple lock replacement intended for stable.
Fixes: e057dd3fc20f ("can: add ISO 15765-2:2016 transport protocol")
Cc: stable@vger.kernel.org # depends on "can: raw, isotp: copy socket options outside of lock_sock()"
Tested-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20261113-can-bcmlock-memcg-v5-4-634c0e04bc72@hartkopp.net
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
net/can/isotp.c | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/net/can/isotp.c b/net/can/isotp.c
index 7a90ba3f1cf1..8229b6a69ecd 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -182,6 +182,7 @@ struct isotp_sock {
struct list_head notifier;
wait_queue_head_t wait;
spinlock_t rx_lock; /* protect single thread state machine */
+ struct mutex conf_lock; /* protects bind and setsockopt */
};
static LIST_HEAD(isotp_notifier_list);
@@ -1497,7 +1498,7 @@ static int isotp_release(struct socket *sock)
list_del(&so->notifier);
spin_unlock(&isotp_notifier_lock);
- lock_sock(sk);
+ mutex_lock(&so->conf_lock);
/* remove current filters & unregister
* the tracked reference so->dev keeps the device's receive lists
@@ -1519,6 +1520,8 @@ static int isotp_release(struct socket *sock)
WRITE_ONCE(so->bound, 0);
so->dev = NULL;
+ mutex_unlock(&so->conf_lock);
+
/* Always wait for a grace period before touching the timers below.
* A concurrent NETDEV_UNREGISTER may have already unregistered our
* filters and cleared so->bound in isotp_notify() without waiting
@@ -1535,7 +1538,6 @@ static int isotp_release(struct socket *sock)
sock_orphan(sk);
sock->sk = NULL;
- release_sock(sk);
sock_prot_inuse_add(net, sk->sk_prot, -1);
sock_put(sk);
@@ -1585,8 +1587,8 @@ static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int l
if (!addr->can_ifindex)
return -ENODEV;
- /* lock_sock() serializes the binding with isotp_notify() */
- lock_sock(sk);
+ /* so->conf_lock serializes the binding with isotp_notify() */
+ mutex_lock(&so->conf_lock);
if (so->bound) {
err = -EINVAL;
@@ -1596,7 +1598,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int l
/* A transmission or reception that outlived a previous binding
* (unbound by NETDEV_UNREGISTER) may still be draining; the FC/echo
* and RX watchdog timers bound how long this takes. Checked together
- * with so->bound in the same lock_sock() section above, so there is
+ * with so->bound in the same so->conf_lock section above, so there is
* no window in which a concurrent isotp_notify() could be missed.
*/
if (READ_ONCE(so->tx.state) != ISOTP_IDLE ||
@@ -1686,7 +1688,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int l
sk_error_report(sk);
}
- release_sock(sk);
+ mutex_unlock(&so->conf_lock);
return err;
}
@@ -1790,6 +1792,7 @@ static int isotp_setsockopt(struct socket *sock, int level, int optname,
{
struct sock *sk = sock->sk;
+ struct isotp_sock *so = isotp_sk(sk);
union {
struct can_isotp_options opt;
struct can_isotp_fc_options rxfc;
@@ -1802,7 +1805,7 @@ static int isotp_setsockopt(struct socket *sock, int level, int optname,
if (level != SOL_CAN_ISOTP)
return -EINVAL;
- /* copy the option values from user space before lock_sock() */
+ /* copy the option values from user space before taking so->conf_lock */
switch (optname) {
case CAN_ISOTP_OPTS:
size = sizeof(val.opt);
@@ -1831,9 +1834,9 @@ static int isotp_setsockopt(struct socket *sock, int level, int optname,
if (copy_from_sockptr(&val, optval, size))
return -EFAULT;
- lock_sock(sk);
+ mutex_lock(&so->conf_lock);
ret = isotp_setsockopt_locked(sock, optname, &val);
- release_sock(sk);
+ mutex_unlock(&so->conf_lock);
return ret;
}
@@ -1906,9 +1909,9 @@ static void isotp_notify(struct isotp_sock *so, unsigned long msg,
switch (msg) {
case NETDEV_UNREGISTER:
- lock_sock(sk);
+ mutex_lock(&so->conf_lock);
if (so->dev != dev) {
- release_sock(sk);
+ mutex_unlock(&so->conf_lock);
break;
}
@@ -1932,7 +1935,7 @@ static void isotp_notify(struct isotp_sock *so, unsigned long msg,
sk->sk_err = ENODEV;
if (!sock_flag(sk, SOCK_DEAD))
sk_error_report(sk);
- release_sock(sk);
+ mutex_unlock(&so->conf_lock);
break;
case NETDEV_DOWN:
@@ -1991,6 +1994,7 @@ static int isotp_init(struct sock *sk)
so->ifindex = 0;
so->bound = 0;
so->dev = NULL;
+ mutex_init(&so->conf_lock);
so->opt.flags = CAN_ISOTP_DEFAULT_FLAGS;
so->opt.ext_address = CAN_ISOTP_DEFAULT_EXT_ADDRESS;
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH net 7/9] can: netlink: fix CAN XL PWM attribute sizing
2026-11-15 9:54 [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
` (5 preceding siblings ...)
2026-11-15 9:54 ` [PATCH net 6/9] can: isotp: use a private mutex instead of lock_sock() Marc Kleine-Budde
@ 2026-11-15 9:54 ` Marc Kleine-Budde
2026-11-15 9:54 ` [PATCH net 8/9] can: bcm: use a private mutex instead of lock_sock() Marc Kleine-Budde
` (3 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2026-11-15 9:54 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Zhu Ling, stable, Sashiko,
Marc Kleine-Budde
From: Zhu Ling <zhuling0805@qq.com>
can_pwm_fill_info() emits the PWM capability limits whenever pwm_const is
present, regardless of whether TMS is enabled. In contrast,
can_pwm_get_size() currently returns 0 when TMS is disabled. It
therefore underestimates the required netlink message size by the nested
attribute header and 6 u32 attributes.
Always account for the PWM capability attributes when pwm_const is present,
and account for the 3 runtime PWM values only when TMS is enabled.
Fixes: 46552323fa67 ("can: netlink: add PWM netlink interface")
Cc: stable@vger.kernel.org
Signed-off-by: Zhu Ling <zhuling0805@qq.com>
Link: https://patch.msgid.link/tencent_9A525E0656A4F7D4CA9CFA1AB1A4BFC6D706@qq.com
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/bug/linux-3924d490-baed-49dc-880a-6fd1163cf08d
Reviewed-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/dev/netlink.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index c0367c9e65f4..5a3c453a65a7 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -783,7 +783,7 @@ static size_t can_pwm_get_size(const struct can_pwm_const *pwm_const,
{
size_t size;
- if (!pwm_const || !pwm_on)
+ if (!pwm_const)
return 0;
size = nla_total_size(0); /* nest IFLA_CAN_PWM */
@@ -795,9 +795,11 @@ static size_t can_pwm_get_size(const struct can_pwm_const *pwm_const,
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMO_MIN */
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMO_MAX */
- size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMS */
- size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWML */
- size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMO */
+ if (pwm_on) {
+ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMS */
+ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWML */
+ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_PWM_PWMO */
+ }
return size;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH net 8/9] can: bcm: use a private mutex instead of lock_sock()
2026-11-15 9:54 [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
` (6 preceding siblings ...)
2026-11-15 9:54 ` [PATCH net 7/9] can: netlink: fix CAN XL PWM attribute sizing Marc Kleine-Budde
@ 2026-11-15 9:54 ` Marc Kleine-Budde
2026-11-15 9:55 ` [PATCH net 9/9] can: gs_usb: gs_can_start_xmit(): don't leak uninitialized memory over USB Marc Kleine-Budde
` (2 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2026-11-15 9:54 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Oliver Hartkopp, stable,
Marc Kleine-Budde
From: Oliver Hartkopp <socketcan@hartkopp.net>
bcm_notify() takes lock_sock() of every CAN_BCM socket in the namespace
of a vanishing CAN device while holding RTNL. Any path that holds the
socket lock while accessing user space can therefore block RTNL. With
"can: bcm: copy the CAN frames outside of lock_sock()" the CAN frames
of bcm_sendmsg() are copied outside of the socket lock, but the generic
SOL_SOCKET options in sk_setsockopt() and sk_getsockopt() still access
user space under sockopt_lock_sock(), e.g. for SO_ATTACH_FILTER,
SO_LINGER or SO_TXTIME.
CAN_BCM only uses lock_sock() to serialize the binding and the bcm_op
lists. It does not use the socket backlog, as the BCM messages are
queued directly to the socket.
Replace lock_sock() with the mutex conf_lock in struct bcm_sock. The
generic socket options do not take this mutex, so they can not block
bcm_notify() anymore. No user space access happens while the mutex is
held. The memory allocations for the bcm_ops and the CAN receivers are
still done under the mutex, as they have been under lock_sock() before.
bcm_release() removes the procfs entry before taking the mutex, as
remove_proc_entry() waits for readers that may stall in their copy to
user space. The socket has already left the notifier list at this
point.
Fixes: ffd980f976e7 ("[CAN]: Add broadcast manager (bcm) protocol")
Cc: stable@vger.kernel.org # depends on "can: bcm: copy the CAN frames outside of lock_sock()"
Tested-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20261113-can-bcmlock-memcg-v5-5-634c0e04bc72@hartkopp.net
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
net/can/bcm.c | 30 ++++++++++++++++--------------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 1595b7720c98..dc9e2890490a 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -145,6 +145,7 @@ struct bcm_sock {
unsigned long dropped_usr_msgs;
struct proc_dir_entry *bcm_proc_read;
char procname [32]; /* inode number in decimal with \0 */
+ struct mutex conf_lock; /* protects bind and the bcm_op lists */
};
static LIST_HEAD(bcm_notifier_list);
@@ -1673,8 +1674,8 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if ((size - MHSIZ) % cfsiz)
return -EINVAL;
- /* Copy the CAN frames from user space before lock_sock(), so a
- * stalled copy can not block bcm_notify() waiting for lock_sock()
+ /* Copy the CAN frames from user space before taking bo->conf_lock, so a
+ * stalled copy can not block bcm_notify() waiting for bo->conf_lock
* under RTNL. Only the frames the opcode handler reads are copied.
* The handlers keep their checks and read the frames from fmsg.
*/
@@ -1714,12 +1715,12 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
kv.iov_len = flen;
iov_iter_kvec(&fmsg.msg_iter, ITER_SOURCE, &kv, 1, flen);
- lock_sock(sk);
+ mutex_lock(&bo->conf_lock);
- /* Re-validate under the socket lock: a concurrent bcm_notify()
+ /* Re-validate under bo->conf_lock: a concurrent bcm_notify()
* may have unbound this socket (device removal) after the
* lockless fast-path check above. bo->ifindex is only ever
- * mutated under lock_sock(), so reading it here - instead of
+ * mutated under bo->conf_lock, so reading it here - instead of
* before taking the lock - guarantees it can't be observed
* torn against bo->bound.
*/
@@ -1819,7 +1820,7 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
}
out_release:
- release_sock(sk);
+ mutex_unlock(&bo->conf_lock);
out_free:
if (frames != &sframe)
kvfree(frames);
@@ -1843,7 +1844,7 @@ static void bcm_notify(struct bcm_sock *bo, unsigned long msg,
switch (msg) {
case NETDEV_UNREGISTER:
- lock_sock(sk);
+ mutex_lock(&bo->conf_lock);
/* rx_ops: remove device specific receive entries */
list_for_each_entry(op, &bo->rx_ops, list) {
@@ -1877,7 +1878,7 @@ static void bcm_notify(struct bcm_sock *bo, unsigned long msg,
notify_enodev = 1;
}
- release_sock(sk);
+ mutex_unlock(&bo->conf_lock);
if (notify_enodev) {
sk->sk_err = ENODEV;
@@ -1930,6 +1931,7 @@ static int bcm_init(struct sock *sk)
bo->ifindex = 0;
bo->dropped_usr_msgs = 0;
bo->bcm_proc_read = NULL;
+ mutex_init(&bo->conf_lock);
INIT_LIST_HEAD(&bo->tx_ops);
INIT_LIST_HEAD(&bo->rx_ops);
@@ -1969,15 +1971,14 @@ static int bcm_release(struct socket *sock)
list_del(&bo->notifier);
spin_unlock(&bcm_notifier_lock);
- /* bcm_notify() can not access this socket anymore */
- lock_sock(sk);
-
#if IS_ENABLED(CONFIG_PROC_FS)
/* remove procfs entry */
if (net->can.bcmproc_dir && bo->bcm_proc_read)
remove_proc_entry(bo->procname, net->can.bcmproc_dir);
#endif /* CONFIG_PROC_FS */
+ mutex_lock(&bo->conf_lock);
+
list_for_each_entry_safe(op, next, &bo->tx_ops, list) {
list_del_rcu(&op->list);
bcm_remove_op(op);
@@ -2012,10 +2013,11 @@ static int bcm_release(struct socket *sock)
WRITE_ONCE(bo->ifindex, 0);
}
+ mutex_unlock(&bo->conf_lock);
+
sock_orphan(sk);
sock->sk = NULL;
- release_sock(sk);
sock_prot_inuse_add(net, sk->sk_prot, -1);
sock_put(sk);
@@ -2034,7 +2036,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int
if (len < BCM_MIN_NAMELEN)
return -EINVAL;
- lock_sock(sk);
+ mutex_lock(&bo->conf_lock);
if (bo->bound) {
ret = -EISCONN;
@@ -2086,7 +2088,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int
WRITE_ONCE(bo->bound, 1);
fail:
- release_sock(sk);
+ mutex_unlock(&bo->conf_lock);
return ret;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH net 9/9] can: gs_usb: gs_can_start_xmit(): don't leak uninitialized memory over USB
2026-11-15 9:54 [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
` (7 preceding siblings ...)
2026-11-15 9:54 ` [PATCH net 8/9] can: bcm: use a private mutex instead of lock_sock() Marc Kleine-Budde
@ 2026-11-15 9:55 ` Marc Kleine-Budde
2026-11-15 10:18 ` [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
2026-11-15 20:10 ` netdev-bot+sinfo
10 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2026-11-15 9:55 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, linux-can, kernel, Marc Kleine-Budde, stable
The driver allocates the transmission buffer using kmalloc(), which means
the memory remains uninitialized. Then various headers are filled and, but
only the actual CAN frame data payload (of length cfd->len or cf->len) is
copied into the buffer, leaving the remaining buffer uninitialized.
Fix this information leak, allocate the buffer with kzalloc().
Closes: https://sashiko.dev/#/bug/linux-0a8c0e8a-c623-426a-8db3-f55111f6cd84
Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices")
Cc: stable@vger.kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/usb/gs_usb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 3b9b2f104d86..15f28833f2de 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -861,7 +861,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
if (!urb)
goto nomem_urb;
- hf = kmalloc(dev->hf_size_tx, GFP_ATOMIC);
+ hf = kzalloc(dev->hf_size_tx, GFP_ATOMIC);
if (!hf)
goto nomem_hf;
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH net 0/9] pull-request: can 2026-11-15
2026-11-15 9:54 [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
` (8 preceding siblings ...)
2026-11-15 9:55 ` [PATCH net 9/9] can: gs_usb: gs_can_start_xmit(): don't leak uninitialized memory over USB Marc Kleine-Budde
@ 2026-11-15 10:18 ` Marc Kleine-Budde
2026-11-15 11:23 ` Oliver Hartkopp
2026-11-15 20:10 ` netdev-bot+sinfo
10 siblings, 1 reply; 14+ messages in thread
From: Marc Kleine-Budde @ 2026-11-15 10:18 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, linux-can, kernel
[-- Attachment #1: Type: text/plain, Size: 979 bytes --]
On 15.11.2026 10:54:51, Marc Kleine-Budde wrote:
> Hello netdev-team,
>
> this is a pull request of 9 patches for net/main.
>
> this first 3 patches are by Zhu Ling and fix problems with the CAN
> netlink handling.
>
> A patch by my fixes a kernel memory information leak over USB in the
> gs_usb driver.
>
> The last 5 patches are by Oliver Hartkopp and avoid RTNL stalls in
> CAN_RAW, CAN_ISOTP and CAN_BCM protocols.
I described patches in topological order, which is intuitive when
looking at the git tree. However the linearized order of patches in this
email patch series is chronological :/ - Sorry, I've added the missing
"--topo-order" to my git send-email script.
regards,
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Embedded Linux | https://www.pengutronix.de |
Vertretung Nürnberg | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH net 0/9] pull-request: can 2026-11-15
2026-11-15 10:18 ` [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
@ 2026-11-15 11:23 ` Oliver Hartkopp
2026-11-15 11:55 ` Marc Kleine-Budde
0 siblings, 1 reply; 14+ messages in thread
From: Oliver Hartkopp @ 2026-11-15 11:23 UTC (permalink / raw)
To: Marc Kleine-Budde, netdev; +Cc: davem, kuba, linux-can, kernel
On 15.11.26 11:18, Marc Kleine-Budde wrote:
> On 15.11.2026 10:54:51, Marc Kleine-Budde wrote:
>> Hello netdev-team,
>>
>> this is a pull request of 9 patches for net/main.
>>
>> this first 3 patches are by Zhu Ling and fix problems with the CAN
>> netlink handling.
>>
>> A patch by my fixes a kernel memory information leak over USB in the
>> gs_usb driver.
>>
>> The last 5 patches are by Oliver Hartkopp and avoid RTNL stalls in
>> CAN_RAW, CAN_ISOTP and CAN_BCM protocols.
>
> I described patches in topological order, which is intuitive when
> looking at the git tree. However the linearized order of patches in this
> email patch series is chronological :/ - Sorry, I've added the missing
> "--topo-order" to my git send-email script.
>
Funny :)
Anyway the current patch order is correct to be applied.
Best regards,
Oliver
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH net 0/9] pull-request: can 2026-11-15
2026-11-15 11:23 ` Oliver Hartkopp
@ 2026-11-15 11:55 ` Marc Kleine-Budde
0 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2026-11-15 11:55 UTC (permalink / raw)
To: Oliver Hartkopp; +Cc: netdev, davem, kuba, linux-can, kernel
[-- Attachment #1: Type: text/plain, Size: 1302 bytes --]
On 15.11.2026 12:23:39, Oliver Hartkopp wrote:
>
>
> On 15.11.26 11:18, Marc Kleine-Budde wrote:
> > On 15.11.2026 10:54:51, Marc Kleine-Budde wrote:
> > > Hello netdev-team,
> > >
> > > this is a pull request of 9 patches for net/main.
> > >
> > > this first 3 patches are by Zhu Ling and fix problems with the CAN
> > > netlink handling.
> > >
> > > A patch by my fixes a kernel memory information leak over USB in the
> > > gs_usb driver.
> > >
> > > The last 5 patches are by Oliver Hartkopp and avoid RTNL stalls in
> > > CAN_RAW, CAN_ISOTP and CAN_BCM protocols.
> >
> > I described patches in topological order, which is intuitive when
> > looking at the git tree. However the linearized order of patches in this
> > email patch series is chronological :/ - Sorry, I've added the missing
> > "--topo-order" to my git send-email script.
> >
> Funny :)
>
> Anyway the current patch order is correct to be applied.
The netdev people usually merge the tag, the emails are relevant for
review.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Embedded Linux | https://www.pengutronix.de |
Vertretung Nürnberg | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH net 0/9] pull-request: can 2026-11-15
2026-11-15 9:54 [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
` (9 preceding siblings ...)
2026-11-15 10:18 ` [PATCH net 0/9] pull-request: can 2026-11-15 Marc Kleine-Budde
@ 2026-11-15 20:10 ` netdev-bot+sinfo
10 siblings, 0 replies; 14+ messages in thread
From: netdev-bot+sinfo @ 2026-11-15 20:10 UTC (permalink / raw)
To: Marc Kleine-Budde; +Cc: netdev, davem, kuba, linux-can, kernel
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- How the issue was discovered, e.g. hit in production, hit during
development, syzbot report, manual code inspection, LLM or static
analysis tool scan.
- Whether the issue was actually triggered, or is only theoretical
(e.g. found by LLM and not proven at runtime). If it was triggered
please include the symptoms, like the stack trace or kernel messages.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account.
*IMPORTANT*: If you do repost (for other reasons) - please include
the relevant info in the cover letter or commit messages.
--
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 14+ messages in thread