]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 27 Aug 2023 10:11:06 +0000 (12:11 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 27 Aug 2023 10:11:06 +0000 (12:11 +0200)
added patches:
can-raw-add-missing-refcount-for-memory-leak-fix.patch

queue-6.1/can-raw-add-missing-refcount-for-memory-leak-fix.patch [new file with mode: 0644]
queue-6.1/series

diff --git a/queue-6.1/can-raw-add-missing-refcount-for-memory-leak-fix.patch b/queue-6.1/can-raw-add-missing-refcount-for-memory-leak-fix.patch
new file mode 100644 (file)
index 0000000..de2bda3
--- /dev/null
@@ -0,0 +1,120 @@
+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();
index cae4ed5d88e89db0c16a23abef85ef7a5fd2b0ae..e1a148444646526016b8aab376566c1159958471 100644 (file)
@@ -110,3 +110,4 @@ sched-deadline-create-dl-bw-alloc-free-check-overflow-interface.patch
 cgroup-cpuset-free-dl-bw-in-case-can_attach-fails.patch
 thunderbolt-fix-thunderbolt-3-display-flickering-issue-on-2nd-hot-plug-onwards.patch
 ublk-remove-check-io_uring_f_sqe128-in-ublk_ch_uring_cmd.patch
+can-raw-add-missing-refcount-for-memory-leak-fix.patch