--- /dev/null
+From c275a176e4b69868576e543409927ae75e3a3288 Mon Sep 17 00:00:00 2001
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+Date: Mon, 21 Aug 2023 16:45:47 +0200
+Subject: can: raw: add missing refcount for memory leak fix
+
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+
+commit c275a176e4b69868576e543409927ae75e3a3288 upstream.
+
+Commit ee8b94c8510c ("can: raw: fix receiver memory leak") introduced
+a new reference to the CAN netdevice that has assigned CAN filters.
+But this new ro->dev reference did not maintain its own refcount which
+lead to another KASAN use-after-free splat found by Eric Dumazet.
+
+This patch ensures a proper refcount for the CAN nedevice.
+
+Fixes: ee8b94c8510c ("can: raw: fix receiver memory leak")
+Reported-by: Eric Dumazet <edumazet@google.com>
+Cc: Ziyang Xuan <william.xuanziyang@huawei.com>
+Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Link: https://lore.kernel.org/r/20230821144547.6658-3-socketcan@hartkopp.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/can/raw.c | 35 ++++++++++++++++++++++++++---------
+ 1 file changed, 26 insertions(+), 9 deletions(-)
+
+--- a/net/can/raw.c
++++ b/net/can/raw.c
+@@ -85,6 +85,7 @@ struct raw_sock {
+ int bound;
+ int ifindex;
+ struct net_device *dev;
++ netdevice_tracker dev_tracker;
+ struct list_head notifier;
+ int loopback;
+ int recv_own_msgs;
+@@ -285,8 +286,10 @@ static void raw_notify(struct raw_sock *
+ case NETDEV_UNREGISTER:
+ lock_sock(sk);
+ /* remove current filters & unregister */
+- if (ro->bound)
++ if (ro->bound) {
+ raw_disable_allfilters(dev_net(dev), dev, sk);
++ netdev_put(dev, &ro->dev_tracker);
++ }
+
+ if (ro->count > 1)
+ kfree(ro->filter);
+@@ -391,10 +394,12 @@ static int raw_release(struct socket *so
+
+ /* remove current filters & unregister */
+ if (ro->bound) {
+- if (ro->dev)
++ if (ro->dev) {
+ raw_disable_allfilters(dev_net(ro->dev), ro->dev, sk);
+- else
++ netdev_put(ro->dev, &ro->dev_tracker);
++ } else {
+ raw_disable_allfilters(sock_net(sk), NULL, sk);
++ }
+ }
+
+ if (ro->count > 1)
+@@ -445,10 +450,10 @@ static int raw_bind(struct socket *sock,
+ goto out;
+ }
+ if (dev->type != ARPHRD_CAN) {
+- dev_put(dev);
+ err = -ENODEV;
+- goto out;
++ goto out_put_dev;
+ }
++
+ if (!(dev->flags & IFF_UP))
+ notify_enetdown = 1;
+
+@@ -456,7 +461,9 @@ static int raw_bind(struct socket *sock,
+
+ /* filters set by default/setsockopt */
+ err = raw_enable_allfilters(sock_net(sk), dev, sk);
+- dev_put(dev);
++ if (err)
++ goto out_put_dev;
++
+ } else {
+ ifindex = 0;
+
+@@ -467,18 +474,28 @@ static int raw_bind(struct socket *sock,
+ if (!err) {
+ if (ro->bound) {
+ /* unregister old filters */
+- if (ro->dev)
++ if (ro->dev) {
+ raw_disable_allfilters(dev_net(ro->dev),
+ ro->dev, sk);
+- else
++ /* drop reference to old ro->dev */
++ netdev_put(ro->dev, &ro->dev_tracker);
++ } else {
+ raw_disable_allfilters(sock_net(sk), NULL, sk);
++ }
+ }
+ ro->ifindex = ifindex;
+ ro->bound = 1;
++ /* bind() ok -> hold a reference for new ro->dev */
+ ro->dev = dev;
++ if (ro->dev)
++ netdev_hold(ro->dev, &ro->dev_tracker, GFP_KERNEL);
+ }
+
+- out:
++out_put_dev:
++ /* remove potential reference from dev_get_by_index() */
++ if (dev)
++ dev_put(dev);
++out:
+ release_sock(sk);
+ rtnl_unlock();
+