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

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

diff --git a/queue-5.15/can-raw-add-missing-refcount-for-memory-leak-fix.patch b/queue-5.15/can-raw-add-missing-refcount-for-memory-leak-fix.patch
new file mode 100644 (file)
index 0000000..a5fb1cc
--- /dev/null
@@ -0,0 +1,112 @@
+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 |   34 +++++++++++++++++++++++++---------
+ 1 file changed, 25 insertions(+), 9 deletions(-)
+
+--- a/net/can/raw.c
++++ b/net/can/raw.c
+@@ -283,8 +283,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);
++                      dev_put(dev);
++              }
+               if (ro->count > 1)
+                       kfree(ro->filter);
+@@ -388,10 +390,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
++                      dev_put(ro->dev);
++              } else {
+                       raw_disable_allfilters(sock_net(sk), NULL, sk);
++              }
+       }
+       if (ro->count > 1)
+@@ -442,10 +446,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;
+@@ -453,7 +457,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;
+@@ -464,18 +470,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 */
++                              dev_put(ro->dev);
++                      } 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)
++                      dev_hold(ro->dev);
+       }
+- out:
++out_put_dev:
++      /* remove potential reference from dev_get_by_index() */
++      if (dev)
++              dev_put(dev);
++out:
+       release_sock(sk);
+       rtnl_unlock();
index 4b76611da4230afd8457cbe5da2d8bb527b51703..930ebb9bfd8ad00e58a0b1ddbd9c0f5f7cb56abf 100644 (file)
@@ -80,3 +80,4 @@ cgroup-cpuset-iterate-only-if-deadline-tasks-are-present.patch
 sched-deadline-create-dl-bw-alloc-free-check-overflow-interface.patch
 cgroup-cpuset-free-dl-bw-in-case-can_attach-fails.patch
 drm-i915-fix-premature-release-of-request-s-reusable-memory.patch
+can-raw-add-missing-refcount-for-memory-leak-fix.patch