]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 18 Apr 2022 11:54:46 +0000 (13:54 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 18 Apr 2022 11:54:46 +0000 (13:54 +0200)
added patches:
ax25-add-refcount-in-ax25_dev-to-avoid-uaf-bugs.patch
ax25-fix-npd-bug-in-ax25_disconnect.patch
ax25-fix-null-pointer-dereferences-in-ax25-timers.patch
ax25-fix-refcount-leaks-caused-by-ax25_cb_del.patch
ax25-fix-reference-count-leaks-of-ax25_dev.patch
ax25-fix-uaf-bug-in-ax25_send_control.patch
ax25-fix-uaf-bugs-in-ax25-timers.patch
ax25-fix-uaf-bugs-of-net_device-caused-by-rebinding-operation.patch

queue-5.10/ax25-add-refcount-in-ax25_dev-to-avoid-uaf-bugs.patch [new file with mode: 0644]
queue-5.10/ax25-fix-npd-bug-in-ax25_disconnect.patch [new file with mode: 0644]
queue-5.10/ax25-fix-null-pointer-dereferences-in-ax25-timers.patch [new file with mode: 0644]
queue-5.10/ax25-fix-refcount-leaks-caused-by-ax25_cb_del.patch [new file with mode: 0644]
queue-5.10/ax25-fix-reference-count-leaks-of-ax25_dev.patch [new file with mode: 0644]
queue-5.10/ax25-fix-uaf-bug-in-ax25_send_control.patch [new file with mode: 0644]
queue-5.10/ax25-fix-uaf-bugs-in-ax25-timers.patch [new file with mode: 0644]
queue-5.10/ax25-fix-uaf-bugs-of-net_device-caused-by-rebinding-operation.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/ax25-add-refcount-in-ax25_dev-to-avoid-uaf-bugs.patch b/queue-5.10/ax25-add-refcount-in-ax25_dev-to-avoid-uaf-bugs.patch
new file mode 100644 (file)
index 0000000..7299948
--- /dev/null
@@ -0,0 +1,195 @@
+From foo@baz Mon Apr 18 01:53:59 PM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Fri, 15 Apr 2022 20:49:26 +0300
+Subject: ax25: add refcount in ax25_dev to avoid UAF bugs
+To: stable@vger.kernel.org
+Message-ID: <20220415174933.1076972-1-ovidiu.panait@windriver.com>
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+commit d01ffb9eee4af165d83b08dd73ebdf9fe94a519b upstream.
+
+If we dereference ax25_dev after we call kfree(ax25_dev) in
+ax25_dev_device_down(), it will lead to concurrency UAF bugs.
+There are eight syscall functions suffer from UAF bugs, include
+ax25_bind(), ax25_release(), ax25_connect(), ax25_ioctl(),
+ax25_getname(), ax25_sendmsg(), ax25_getsockopt() and
+ax25_info_show().
+
+One of the concurrency UAF can be shown as below:
+
+  (USE)                       |    (FREE)
+                              |  ax25_device_event
+                              |    ax25_dev_device_down
+ax25_bind                     |    ...
+  ...                         |      kfree(ax25_dev)
+  ax25_fillin_cb()            |    ...
+    ax25_fillin_cb_from_dev() |
+  ...                         |
+
+The root cause of UAF bugs is that kfree(ax25_dev) in
+ax25_dev_device_down() is not protected by any locks.
+When ax25_dev, which there are still pointers point to,
+is released, the concurrency UAF bug will happen.
+
+This patch introduces refcount into ax25_dev in order to
+guarantee that there are no pointers point to it when ax25_dev
+is released.
+
+Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[OP: backport to 5.10: adjusted context]
+Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/ax25.h    |   10 ++++++++++
+ net/ax25/af_ax25.c    |    2 ++
+ net/ax25/ax25_dev.c   |   12 ++++++++++--
+ net/ax25/ax25_route.c |    3 +++
+ 4 files changed, 25 insertions(+), 2 deletions(-)
+
+--- a/include/net/ax25.h
++++ b/include/net/ax25.h
+@@ -236,6 +236,7 @@ typedef struct ax25_dev {
+ #if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER)
+       ax25_dama_info          dama;
+ #endif
++      refcount_t              refcount;
+ } ax25_dev;
+ typedef struct ax25_cb {
+@@ -290,6 +291,15 @@ static __inline__ void ax25_cb_put(ax25_
+       }
+ }
++#define ax25_dev_hold(__ax25_dev) \
++      refcount_inc(&((__ax25_dev)->refcount))
++
++static __inline__ void ax25_dev_put(ax25_dev *ax25_dev)
++{
++      if (refcount_dec_and_test(&ax25_dev->refcount)) {
++              kfree(ax25_dev);
++      }
++}
+ static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
+ {
+       skb->dev      = dev;
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -98,6 +98,7 @@ again:
+                       spin_unlock_bh(&ax25_list_lock);
+                       lock_sock(sk);
+                       s->ax25_dev = NULL;
++                      ax25_dev_put(ax25_dev);
+                       release_sock(sk);
+                       ax25_disconnect(s, ENETUNREACH);
+                       spin_lock_bh(&ax25_list_lock);
+@@ -446,6 +447,7 @@ static int ax25_ctl_ioctl(const unsigned
+         }
+ out_put:
++      ax25_dev_put(ax25_dev);
+       ax25_cb_put(ax25);
+       return ret;
+--- a/net/ax25/ax25_dev.c
++++ b/net/ax25/ax25_dev.c
+@@ -37,6 +37,7 @@ ax25_dev *ax25_addr_ax25dev(ax25_address
+       for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
+               if (ax25cmp(addr, (ax25_address *)ax25_dev->dev->dev_addr) == 0) {
+                       res = ax25_dev;
++                      ax25_dev_hold(ax25_dev);
+               }
+       spin_unlock_bh(&ax25_dev_lock);
+@@ -56,6 +57,7 @@ void ax25_dev_device_up(struct net_devic
+               return;
+       }
++      refcount_set(&ax25_dev->refcount, 1);
+       dev->ax25_ptr     = ax25_dev;
+       ax25_dev->dev     = dev;
+       dev_hold(dev);
+@@ -83,6 +85,7 @@ void ax25_dev_device_up(struct net_devic
+       spin_lock_bh(&ax25_dev_lock);
+       ax25_dev->next = ax25_dev_list;
+       ax25_dev_list  = ax25_dev;
++      ax25_dev_hold(ax25_dev);
+       spin_unlock_bh(&ax25_dev_lock);
+       ax25_register_dev_sysctl(ax25_dev);
+@@ -112,20 +115,22 @@ void ax25_dev_device_down(struct net_dev
+       if ((s = ax25_dev_list) == ax25_dev) {
+               ax25_dev_list = s->next;
++              ax25_dev_put(ax25_dev);
+               spin_unlock_bh(&ax25_dev_lock);
+               dev->ax25_ptr = NULL;
+               dev_put(dev);
+-              kfree(ax25_dev);
++              ax25_dev_put(ax25_dev);
+               return;
+       }
+       while (s != NULL && s->next != NULL) {
+               if (s->next == ax25_dev) {
+                       s->next = ax25_dev->next;
++                      ax25_dev_put(ax25_dev);
+                       spin_unlock_bh(&ax25_dev_lock);
+                       dev->ax25_ptr = NULL;
+                       dev_put(dev);
+-                      kfree(ax25_dev);
++                      ax25_dev_put(ax25_dev);
+                       return;
+               }
+@@ -133,6 +138,7 @@ void ax25_dev_device_down(struct net_dev
+       }
+       spin_unlock_bh(&ax25_dev_lock);
+       dev->ax25_ptr = NULL;
++      ax25_dev_put(ax25_dev);
+ }
+ int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
+@@ -149,6 +155,7 @@ int ax25_fwd_ioctl(unsigned int cmd, str
+               if (ax25_dev->forward != NULL)
+                       return -EINVAL;
+               ax25_dev->forward = fwd_dev->dev;
++              ax25_dev_put(fwd_dev);
+               break;
+       case SIOCAX25DELFWD:
+@@ -161,6 +168,7 @@ int ax25_fwd_ioctl(unsigned int cmd, str
+               return -EINVAL;
+       }
++      ax25_dev_put(ax25_dev);
+       return 0;
+ }
+--- a/net/ax25/ax25_route.c
++++ b/net/ax25/ax25_route.c
+@@ -116,6 +116,7 @@ static int __must_check ax25_rt_add(stru
+       ax25_rt->dev          = ax25_dev->dev;
+       ax25_rt->digipeat     = NULL;
+       ax25_rt->ip_mode      = ' ';
++      ax25_dev_put(ax25_dev);
+       if (route->digi_count != 0) {
+               if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+                       write_unlock_bh(&ax25_route_lock);
+@@ -172,6 +173,7 @@ static int ax25_rt_del(struct ax25_route
+                       }
+               }
+       }
++      ax25_dev_put(ax25_dev);
+       write_unlock_bh(&ax25_route_lock);
+       return 0;
+@@ -214,6 +216,7 @@ static int ax25_rt_opt(struct ax25_route
+       }
+ out:
++      ax25_dev_put(ax25_dev);
+       write_unlock_bh(&ax25_route_lock);
+       return err;
+ }
diff --git a/queue-5.10/ax25-fix-npd-bug-in-ax25_disconnect.patch b/queue-5.10/ax25-fix-npd-bug-in-ax25_disconnect.patch
new file mode 100644 (file)
index 0000000..db0c2a7
--- /dev/null
@@ -0,0 +1,67 @@
+From foo@baz Mon Apr 18 01:53:59 PM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Fri, 15 Apr 2022 20:49:31 +0300
+Subject: ax25: fix NPD bug in ax25_disconnect
+To: stable@vger.kernel.org
+Message-ID: <20220415174933.1076972-6-ovidiu.panait@windriver.com>
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+commit 7ec02f5ac8a5be5a3f20611731243dc5e1d9ba10 upstream.
+
+The ax25_disconnect() in ax25_kill_by_device() is not
+protected by any locks, thus there is a race condition
+between ax25_disconnect() and ax25_destroy_socket().
+when ax25->sk is assigned as NULL by ax25_destroy_socket(),
+a NULL pointer dereference bug will occur if site (1) or (2)
+dereferences ax25->sk.
+
+ax25_kill_by_device()                | ax25_release()
+  ax25_disconnect()                  |   ax25_destroy_socket()
+    ...                              |
+    if(ax25->sk != NULL)             |     ...
+      ...                            |     ax25->sk = NULL;
+      bh_lock_sock(ax25->sk); //(1)  |     ...
+      ...                            |
+      bh_unlock_sock(ax25->sk); //(2)|
+
+This patch moves ax25_disconnect() into lock_sock(), which can
+synchronize with ax25_destroy_socket() in ax25_release().
+
+Fail log:
+===============================================================
+BUG: kernel NULL pointer dereference, address: 0000000000000088
+...
+RIP: 0010:_raw_spin_lock+0x7e/0xd0
+...
+Call Trace:
+ax25_disconnect+0xf6/0x220
+ax25_device_event+0x187/0x250
+raw_notifier_call_chain+0x5e/0x70
+dev_close_many+0x17d/0x230
+rollback_registered_many+0x1f1/0x950
+unregister_netdevice_queue+0x133/0x200
+unregister_netdev+0x13/0x20
+...
+
+Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[OP: backport to 5.10: adjust context]
+Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ax25/af_ax25.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -102,8 +102,8 @@ again:
+                               dev_put(ax25_dev->dev);
+                               ax25_dev_put(ax25_dev);
+                       }
+-                      release_sock(sk);
+                       ax25_disconnect(s, ENETUNREACH);
++                      release_sock(sk);
+                       spin_lock_bh(&ax25_list_lock);
+                       sock_put(sk);
+                       /* The entry could have been deleted from the
diff --git a/queue-5.10/ax25-fix-null-pointer-dereferences-in-ax25-timers.patch b/queue-5.10/ax25-fix-null-pointer-dereferences-in-ax25-timers.patch
new file mode 100644 (file)
index 0000000..d2f8a5f
--- /dev/null
@@ -0,0 +1,123 @@
+From foo@baz Mon Apr 18 01:53:59 PM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Fri, 15 Apr 2022 20:49:32 +0300
+Subject: ax25: Fix NULL pointer dereferences in ax25 timers
+To: stable@vger.kernel.org
+Message-ID: <20220415174933.1076972-7-ovidiu.panait@windriver.com>
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+commit fc6d01ff9ef03b66d4a3a23b46fc3c3d8cf92009 upstream.
+
+The previous commit 7ec02f5ac8a5 ("ax25: fix NPD bug in ax25_disconnect")
+move ax25_disconnect into lock_sock() in order to prevent NPD bugs. But
+there are race conditions that may lead to null pointer dereferences in
+ax25_heartbeat_expiry(), ax25_t1timer_expiry(), ax25_t2timer_expiry(),
+ax25_t3timer_expiry() and ax25_idletimer_expiry(), when we use
+ax25_kill_by_device() to detach the ax25 device.
+
+One of the race conditions that cause null pointer dereferences can be
+shown as below:
+
+      (Thread 1)                    |      (Thread 2)
+ax25_connect()                      |
+ ax25_std_establish_data_link()     |
+  ax25_start_t1timer()              |
+   mod_timer(&ax25->t1timer,..)     |
+                                    | ax25_kill_by_device()
+   (wait a time)                    |  ...
+                                    |  s->ax25_dev = NULL; //(1)
+   ax25_t1timer_expiry()            |
+    ax25->ax25_dev->values[..] //(2)|  ...
+     ...                            |
+
+We set null to ax25_cb->ax25_dev in position (1) and dereference
+the null pointer in position (2).
+
+The corresponding fail log is shown below:
+===============================================================
+BUG: kernel NULL pointer dereference, address: 0000000000000050
+CPU: 1 PID: 0 Comm: swapper/1 Not tainted 5.17.0-rc6-00794-g45690b7d0
+RIP: 0010:ax25_t1timer_expiry+0x12/0x40
+...
+Call Trace:
+ call_timer_fn+0x21/0x120
+ __run_timers.part.0+0x1ca/0x250
+ run_timer_softirq+0x2c/0x60
+ __do_softirq+0xef/0x2f3
+ irq_exit_rcu+0xb6/0x100
+ sysvec_apic_timer_interrupt+0xa2/0xd0
+...
+
+This patch moves ax25_disconnect() before s->ax25_dev = NULL
+and uses del_timer_sync() to delete timers in ax25_disconnect().
+If ax25_disconnect() is called by ax25_kill_by_device() or
+ax25->ax25_dev is NULL, the reason in ax25_disconnect() will be
+equal to ENETUNREACH, it will wait all timers to stop before we
+set null to s->ax25_dev in ax25_kill_by_device().
+
+Fixes: 7ec02f5ac8a5 ("ax25: fix NPD bug in ax25_disconnect")
+Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[OP: backport to 5.10: adjust context]
+Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ax25/af_ax25.c   |    4 ++--
+ net/ax25/ax25_subr.c |   20 ++++++++++++++------
+ 2 files changed, 16 insertions(+), 8 deletions(-)
+
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -89,20 +89,20 @@ again:
+                       sk = s->sk;
+                       if (!sk) {
+                               spin_unlock_bh(&ax25_list_lock);
+-                              s->ax25_dev = NULL;
+                               ax25_disconnect(s, ENETUNREACH);
++                              s->ax25_dev = NULL;
+                               spin_lock_bh(&ax25_list_lock);
+                               goto again;
+                       }
+                       sock_hold(sk);
+                       spin_unlock_bh(&ax25_list_lock);
+                       lock_sock(sk);
++                      ax25_disconnect(s, ENETUNREACH);
+                       s->ax25_dev = NULL;
+                       if (sk->sk_socket) {
+                               dev_put(ax25_dev->dev);
+                               ax25_dev_put(ax25_dev);
+                       }
+-                      ax25_disconnect(s, ENETUNREACH);
+                       release_sock(sk);
+                       spin_lock_bh(&ax25_list_lock);
+                       sock_put(sk);
+--- a/net/ax25/ax25_subr.c
++++ b/net/ax25/ax25_subr.c
+@@ -261,12 +261,20 @@ void ax25_disconnect(ax25_cb *ax25, int
+ {
+       ax25_clear_queues(ax25);
+-      if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
+-              ax25_stop_heartbeat(ax25);
+-      ax25_stop_t1timer(ax25);
+-      ax25_stop_t2timer(ax25);
+-      ax25_stop_t3timer(ax25);
+-      ax25_stop_idletimer(ax25);
++      if (reason == ENETUNREACH) {
++              del_timer_sync(&ax25->timer);
++              del_timer_sync(&ax25->t1timer);
++              del_timer_sync(&ax25->t2timer);
++              del_timer_sync(&ax25->t3timer);
++              del_timer_sync(&ax25->idletimer);
++      } else {
++              if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
++                      ax25_stop_heartbeat(ax25);
++              ax25_stop_t1timer(ax25);
++              ax25_stop_t2timer(ax25);
++              ax25_stop_t3timer(ax25);
++              ax25_stop_idletimer(ax25);
++      }
+       ax25->state = AX25_STATE_0;
diff --git a/queue-5.10/ax25-fix-refcount-leaks-caused-by-ax25_cb_del.patch b/queue-5.10/ax25-fix-refcount-leaks-caused-by-ax25_cb_del.patch
new file mode 100644 (file)
index 0000000..bf5edbd
--- /dev/null
@@ -0,0 +1,102 @@
+From foo@baz Mon Apr 18 01:53:59 PM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Fri, 15 Apr 2022 20:49:29 +0300
+Subject: ax25: Fix refcount leaks caused by ax25_cb_del()
+To: stable@vger.kernel.org
+Message-ID: <20220415174933.1076972-4-ovidiu.panait@windriver.com>
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+commit 9fd75b66b8f68498454d685dc4ba13192ae069b0 upstream.
+
+The previous commit d01ffb9eee4a ("ax25: add refcount in ax25_dev to
+avoid UAF bugs") and commit feef318c855a ("ax25: fix UAF bugs of
+net_device caused by rebinding operation") increase the refcounts of
+ax25_dev and net_device in ax25_bind() and decrease the matching refcounts
+in ax25_kill_by_device() in order to prevent UAF bugs, but there are
+reference count leaks.
+
+The root cause of refcount leaks is shown below:
+
+     (Thread 1)                      |      (Thread 2)
+ax25_bind()                          |
+ ...                                 |
+ ax25_addr_ax25dev()                 |
+  ax25_dev_hold()   //(1)            |
+  ...                                |
+ dev_hold_track()   //(2)            |
+ ...                                 | ax25_destroy_socket()
+                                     |  ax25_cb_del()
+                                     |   ...
+                                     |   hlist_del_init() //(3)
+                                     |
+                                     |
+     (Thread 3)                      |
+ax25_kill_by_device()                |
+ ...                                 |
+ ax25_for_each(s, &ax25_list) {      |
+  if (s->ax25_dev == ax25_dev) //(4) |
+   ...                               |
+
+Firstly, we use ax25_bind() to increase the refcount of ax25_dev in
+position (1) and increase the refcount of net_device in position (2).
+Then, we use ax25_cb_del() invoked by ax25_destroy_socket() to delete
+ax25_cb in hlist in position (3) before calling ax25_kill_by_device().
+Finally, the decrements of refcounts in ax25_kill_by_device() will not
+be executed, because no s->ax25_dev equals to ax25_dev in position (4).
+
+This patch adds decrements of refcounts in ax25_release() and use
+lock_sock() to do synchronization. If refcounts decrease in ax25_release(),
+the decrements of refcounts in ax25_kill_by_device() will not be
+executed and vice versa.
+
+Fixes: d01ffb9eee4a ("ax25: add refcount in ax25_dev to avoid UAF bugs")
+Fixes: 87563a043cef ("ax25: fix reference count leaks of ax25_dev")
+Fixes: feef318c855a ("ax25: fix UAF bugs of net_device caused by rebinding operation")
+Reported-by: Thomas Osterried <thomas@osterried.de>
+Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[OP: backport to 5.10: adjust dev_put_track()->dev_put()]
+Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ax25/af_ax25.c |   14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -98,8 +98,10 @@ again:
+                       spin_unlock_bh(&ax25_list_lock);
+                       lock_sock(sk);
+                       s->ax25_dev = NULL;
+-                      dev_put(ax25_dev->dev);
+-                      ax25_dev_put(ax25_dev);
++                      if (sk->sk_socket) {
++                              dev_put(ax25_dev->dev);
++                              ax25_dev_put(ax25_dev);
++                      }
+                       release_sock(sk);
+                       ax25_disconnect(s, ENETUNREACH);
+                       spin_lock_bh(&ax25_list_lock);
+@@ -978,14 +980,20 @@ static int ax25_release(struct socket *s
+ {
+       struct sock *sk = sock->sk;
+       ax25_cb *ax25;
++      ax25_dev *ax25_dev;
+       if (sk == NULL)
+               return 0;
+       sock_hold(sk);
+-      sock_orphan(sk);
+       lock_sock(sk);
++      sock_orphan(sk);
+       ax25 = sk_to_ax25(sk);
++      ax25_dev = ax25->ax25_dev;
++      if (ax25_dev) {
++              dev_put(ax25_dev->dev);
++              ax25_dev_put(ax25_dev);
++      }
+       if (sk->sk_type == SOCK_SEQPACKET) {
+               switch (ax25->state) {
diff --git a/queue-5.10/ax25-fix-reference-count-leaks-of-ax25_dev.patch b/queue-5.10/ax25-fix-reference-count-leaks-of-ax25_dev.patch
new file mode 100644 (file)
index 0000000..821823f
--- /dev/null
@@ -0,0 +1,239 @@
+From foo@baz Mon Apr 18 01:53:59 PM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Fri, 15 Apr 2022 20:49:27 +0300
+Subject: ax25: fix reference count leaks of ax25_dev
+To: stable@vger.kernel.org
+Message-ID: <20220415174933.1076972-2-ovidiu.panait@windriver.com>
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+commit 87563a043cef044fed5db7967a75741cc16ad2b1 upstream.
+
+The previous commit d01ffb9eee4a ("ax25: add refcount in ax25_dev
+to avoid UAF bugs") introduces refcount into ax25_dev, but there
+are reference leak paths in ax25_ctl_ioctl(), ax25_fwd_ioctl(),
+ax25_rt_add(), ax25_rt_del() and ax25_rt_opt().
+
+This patch uses ax25_dev_put() and adjusts the position of
+ax25_addr_ax25dev() to fix reference cout leaks of ax25_dev.
+
+Fixes: d01ffb9eee4a ("ax25: add refcount in ax25_dev to avoid UAF bugs")
+Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
+Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
+Link: https://lore.kernel.org/r/20220203150811.42256-1-duoming@zju.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[OP: backport to 5.10: adjust context]
+Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/ax25.h    |    8 +++++---
+ net/ax25/af_ax25.c    |   12 ++++++++----
+ net/ax25/ax25_dev.c   |   24 +++++++++++++++++-------
+ net/ax25/ax25_route.c |   16 +++++++++++-----
+ 4 files changed, 41 insertions(+), 19 deletions(-)
+
+--- a/include/net/ax25.h
++++ b/include/net/ax25.h
+@@ -291,10 +291,12 @@ static __inline__ void ax25_cb_put(ax25_
+       }
+ }
+-#define ax25_dev_hold(__ax25_dev) \
+-      refcount_inc(&((__ax25_dev)->refcount))
++static inline void ax25_dev_hold(ax25_dev *ax25_dev)
++{
++      refcount_inc(&ax25_dev->refcount);
++}
+-static __inline__ void ax25_dev_put(ax25_dev *ax25_dev)
++static inline void ax25_dev_put(ax25_dev *ax25_dev)
+ {
+       if (refcount_dec_and_test(&ax25_dev->refcount)) {
+               kfree(ax25_dev);
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -366,21 +366,25 @@ static int ax25_ctl_ioctl(const unsigned
+       if (copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl)))
+               return -EFAULT;
+-      if ((ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr)) == NULL)
+-              return -ENODEV;
+-
+       if (ax25_ctl.digi_count > AX25_MAX_DIGIS)
+               return -EINVAL;
+       if (ax25_ctl.arg > ULONG_MAX / HZ && ax25_ctl.cmd != AX25_KILL)
+               return -EINVAL;
++      ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr);
++      if (!ax25_dev)
++              return -ENODEV;
++
+       digi.ndigi = ax25_ctl.digi_count;
+       for (k = 0; k < digi.ndigi; k++)
+               digi.calls[k] = ax25_ctl.digi_addr[k];
+-      if ((ax25 = ax25_find_cb(&ax25_ctl.source_addr, &ax25_ctl.dest_addr, &digi, ax25_dev->dev)) == NULL)
++      ax25 = ax25_find_cb(&ax25_ctl.source_addr, &ax25_ctl.dest_addr, &digi, ax25_dev->dev);
++      if (!ax25) {
++              ax25_dev_put(ax25_dev);
+               return -ENOTCONN;
++      }
+       switch (ax25_ctl.cmd) {
+       case AX25_KILL:
+--- a/net/ax25/ax25_dev.c
++++ b/net/ax25/ax25_dev.c
+@@ -85,8 +85,8 @@ void ax25_dev_device_up(struct net_devic
+       spin_lock_bh(&ax25_dev_lock);
+       ax25_dev->next = ax25_dev_list;
+       ax25_dev_list  = ax25_dev;
+-      ax25_dev_hold(ax25_dev);
+       spin_unlock_bh(&ax25_dev_lock);
++      ax25_dev_hold(ax25_dev);
+       ax25_register_dev_sysctl(ax25_dev);
+ }
+@@ -115,8 +115,8 @@ void ax25_dev_device_down(struct net_dev
+       if ((s = ax25_dev_list) == ax25_dev) {
+               ax25_dev_list = s->next;
+-              ax25_dev_put(ax25_dev);
+               spin_unlock_bh(&ax25_dev_lock);
++              ax25_dev_put(ax25_dev);
+               dev->ax25_ptr = NULL;
+               dev_put(dev);
+               ax25_dev_put(ax25_dev);
+@@ -126,8 +126,8 @@ void ax25_dev_device_down(struct net_dev
+       while (s != NULL && s->next != NULL) {
+               if (s->next == ax25_dev) {
+                       s->next = ax25_dev->next;
+-                      ax25_dev_put(ax25_dev);
+                       spin_unlock_bh(&ax25_dev_lock);
++                      ax25_dev_put(ax25_dev);
+                       dev->ax25_ptr = NULL;
+                       dev_put(dev);
+                       ax25_dev_put(ax25_dev);
+@@ -150,25 +150,35 @@ int ax25_fwd_ioctl(unsigned int cmd, str
+       switch (cmd) {
+       case SIOCAX25ADDFWD:
+-              if ((fwd_dev = ax25_addr_ax25dev(&fwd->port_to)) == NULL)
++              fwd_dev = ax25_addr_ax25dev(&fwd->port_to);
++              if (!fwd_dev) {
++                      ax25_dev_put(ax25_dev);
+                       return -EINVAL;
+-              if (ax25_dev->forward != NULL)
++              }
++              if (ax25_dev->forward) {
++                      ax25_dev_put(fwd_dev);
++                      ax25_dev_put(ax25_dev);
+                       return -EINVAL;
++              }
+               ax25_dev->forward = fwd_dev->dev;
+               ax25_dev_put(fwd_dev);
++              ax25_dev_put(ax25_dev);
+               break;
+       case SIOCAX25DELFWD:
+-              if (ax25_dev->forward == NULL)
++              if (!ax25_dev->forward) {
++                      ax25_dev_put(ax25_dev);
+                       return -EINVAL;
++              }
+               ax25_dev->forward = NULL;
++              ax25_dev_put(ax25_dev);
+               break;
+       default:
++              ax25_dev_put(ax25_dev);
+               return -EINVAL;
+       }
+-      ax25_dev_put(ax25_dev);
+       return 0;
+ }
+--- a/net/ax25/ax25_route.c
++++ b/net/ax25/ax25_route.c
+@@ -75,11 +75,13 @@ static int __must_check ax25_rt_add(stru
+       ax25_dev *ax25_dev;
+       int i;
+-      if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL)
+-              return -EINVAL;
+       if (route->digi_count > AX25_MAX_DIGIS)
+               return -EINVAL;
++      ax25_dev = ax25_addr_ax25dev(&route->port_addr);
++      if (!ax25_dev)
++              return -EINVAL;
++
+       write_lock_bh(&ax25_route_lock);
+       ax25_rt = ax25_route_list;
+@@ -91,6 +93,7 @@ static int __must_check ax25_rt_add(stru
+                       if (route->digi_count != 0) {
+                               if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+                                       write_unlock_bh(&ax25_route_lock);
++                                      ax25_dev_put(ax25_dev);
+                                       return -ENOMEM;
+                               }
+                               ax25_rt->digipeat->lastrepeat = -1;
+@@ -101,6 +104,7 @@ static int __must_check ax25_rt_add(stru
+                               }
+                       }
+                       write_unlock_bh(&ax25_route_lock);
++                      ax25_dev_put(ax25_dev);
+                       return 0;
+               }
+               ax25_rt = ax25_rt->next;
+@@ -108,6 +112,7 @@ static int __must_check ax25_rt_add(stru
+       if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) {
+               write_unlock_bh(&ax25_route_lock);
++              ax25_dev_put(ax25_dev);
+               return -ENOMEM;
+       }
+@@ -116,11 +121,11 @@ static int __must_check ax25_rt_add(stru
+       ax25_rt->dev          = ax25_dev->dev;
+       ax25_rt->digipeat     = NULL;
+       ax25_rt->ip_mode      = ' ';
+-      ax25_dev_put(ax25_dev);
+       if (route->digi_count != 0) {
+               if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+                       write_unlock_bh(&ax25_route_lock);
+                       kfree(ax25_rt);
++                      ax25_dev_put(ax25_dev);
+                       return -ENOMEM;
+               }
+               ax25_rt->digipeat->lastrepeat = -1;
+@@ -133,6 +138,7 @@ static int __must_check ax25_rt_add(stru
+       ax25_rt->next   = ax25_route_list;
+       ax25_route_list = ax25_rt;
+       write_unlock_bh(&ax25_route_lock);
++      ax25_dev_put(ax25_dev);
+       return 0;
+ }
+@@ -173,8 +179,8 @@ static int ax25_rt_del(struct ax25_route
+                       }
+               }
+       }
+-      ax25_dev_put(ax25_dev);
+       write_unlock_bh(&ax25_route_lock);
++      ax25_dev_put(ax25_dev);
+       return 0;
+ }
+@@ -216,8 +222,8 @@ static int ax25_rt_opt(struct ax25_route
+       }
+ out:
+-      ax25_dev_put(ax25_dev);
+       write_unlock_bh(&ax25_route_lock);
++      ax25_dev_put(ax25_dev);
+       return err;
+ }
diff --git a/queue-5.10/ax25-fix-uaf-bug-in-ax25_send_control.patch b/queue-5.10/ax25-fix-uaf-bug-in-ax25_send_control.patch
new file mode 100644 (file)
index 0000000..88b53b3
--- /dev/null
@@ -0,0 +1,89 @@
+From foo@baz Mon Apr 18 01:53:59 PM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Fri, 15 Apr 2022 20:49:30 +0300
+Subject: ax25: fix UAF bug in ax25_send_control()
+To: stable@vger.kernel.org
+Message-ID: <20220415174933.1076972-5-ovidiu.panait@windriver.com>
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+commit 5352a761308397a0e6250fdc629bb3f615b94747 upstream.
+
+There are UAF bugs in ax25_send_control(), when we call ax25_release()
+to deallocate ax25_dev. The possible race condition is shown below:
+
+      (Thread 1)              |     (Thread 2)
+ax25_dev_device_up() //(1)    |
+                              | ax25_kill_by_device()
+ax25_bind()          //(2)    |
+ax25_connect()                | ...
+ ax25->state = AX25_STATE_1   |
+ ...                          | ax25_dev_device_down() //(3)
+
+      (Thread 3)
+ax25_release()                |
+ ax25_dev_put()  //(4) FREE   |
+ case AX25_STATE_1:           |
+  ax25_send_control()         |
+   alloc_skb()       //USE    |
+
+The refcount of ax25_dev increases in position (1) and (2), and
+decreases in position (3) and (4). The ax25_dev will be freed
+before dereference sites in ax25_send_control().
+
+The following is part of the report:
+
+[  102.297448] BUG: KASAN: use-after-free in ax25_send_control+0x33/0x210
+[  102.297448] Read of size 8 at addr ffff888009e6e408 by task ax25_close/602
+[  102.297448] Call Trace:
+[  102.303751]  ax25_send_control+0x33/0x210
+[  102.303751]  ax25_release+0x356/0x450
+[  102.305431]  __sock_release+0x6d/0x120
+[  102.305431]  sock_close+0xf/0x20
+[  102.305431]  __fput+0x11f/0x420
+[  102.305431]  task_work_run+0x86/0xd0
+[  102.307130]  get_signal+0x1075/0x1220
+[  102.308253]  arch_do_signal_or_restart+0x1df/0xc00
+[  102.308253]  exit_to_user_mode_prepare+0x150/0x1e0
+[  102.308253]  syscall_exit_to_user_mode+0x19/0x50
+[  102.308253]  do_syscall_64+0x48/0x90
+[  102.308253]  entry_SYSCALL_64_after_hwframe+0x44/0xae
+[  102.308253] RIP: 0033:0x405ae7
+
+This patch defers the free operation of ax25_dev and net_device after
+all corresponding dereference sites in ax25_release() to avoid UAF.
+
+Fixes: 9fd75b66b8f6 ("ax25: Fix refcount leaks caused by ax25_cb_del()")
+Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[OP: backport to 5.10: adjust dev_put_track()->dev_put()]
+Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ax25/af_ax25.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -990,10 +990,6 @@ static int ax25_release(struct socket *s
+       sock_orphan(sk);
+       ax25 = sk_to_ax25(sk);
+       ax25_dev = ax25->ax25_dev;
+-      if (ax25_dev) {
+-              dev_put(ax25_dev->dev);
+-              ax25_dev_put(ax25_dev);
+-      }
+       if (sk->sk_type == SOCK_SEQPACKET) {
+               switch (ax25->state) {
+@@ -1055,6 +1051,10 @@ static int ax25_release(struct socket *s
+               sk->sk_state_change(sk);
+               ax25_destroy_socket(ax25);
+       }
++      if (ax25_dev) {
++              dev_put(ax25_dev->dev);
++              ax25_dev_put(ax25_dev);
++      }
+       sock->sk   = NULL;
+       release_sock(sk);
diff --git a/queue-5.10/ax25-fix-uaf-bugs-in-ax25-timers.patch b/queue-5.10/ax25-fix-uaf-bugs-in-ax25-timers.patch
new file mode 100644 (file)
index 0000000..04429c8
--- /dev/null
@@ -0,0 +1,80 @@
+From foo@baz Mon Apr 18 01:53:59 PM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Fri, 15 Apr 2022 20:49:33 +0300
+Subject: ax25: Fix UAF bugs in ax25 timers
+To: stable@vger.kernel.org
+Message-ID: <20220415174933.1076972-8-ovidiu.panait@windriver.com>
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+commit 82e31755e55fbcea6a9dfaae5fe4860ade17cbc0 upstream.
+
+There are race conditions that may lead to UAF bugs in
+ax25_heartbeat_expiry(), ax25_t1timer_expiry(), ax25_t2timer_expiry(),
+ax25_t3timer_expiry() and ax25_idletimer_expiry(), when we call
+ax25_release() to deallocate ax25_dev.
+
+One of the UAF bugs caused by ax25_release() is shown below:
+
+      (Thread 1)                    |      (Thread 2)
+ax25_dev_device_up() //(1)          |
+...                                 | ax25_kill_by_device()
+ax25_bind()          //(2)          |
+ax25_connect()                      | ...
+ ax25_std_establish_data_link()     |
+  ax25_start_t1timer()              | ax25_dev_device_down() //(3)
+   mod_timer(&ax25->t1timer,..)     |
+                                    | ax25_release()
+   (wait a time)                    |  ...
+                                    |  ax25_dev_put(ax25_dev) //(4)FREE
+   ax25_t1timer_expiry()            |
+    ax25->ax25_dev->values[..] //USE|  ...
+     ...                            |
+
+We increase the refcount of ax25_dev in position (1) and (2), and
+decrease the refcount of ax25_dev in position (3) and (4).
+The ax25_dev will be freed in position (4) and be used in
+ax25_t1timer_expiry().
+
+The fail log is shown below:
+==============================================================
+
+[  106.116942] BUG: KASAN: use-after-free in ax25_t1timer_expiry+0x1c/0x60
+[  106.116942] Read of size 8 at addr ffff88800bda9028 by task swapper/0/0
+[  106.116942] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.17.0-06123-g0905eec574
+[  106.116942] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-14
+[  106.116942] Call Trace:
+...
+[  106.116942]  ax25_t1timer_expiry+0x1c/0x60
+[  106.116942]  call_timer_fn+0x122/0x3d0
+[  106.116942]  __run_timers.part.0+0x3f6/0x520
+[  106.116942]  run_timer_softirq+0x4f/0xb0
+[  106.116942]  __do_softirq+0x1c2/0x651
+...
+
+This patch adds del_timer_sync() in ax25_release(), which could ensure
+that all timers stop before we deallocate ax25_dev.
+
+Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[OP: backport to 5.10: adjust context]
+Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ax25/af_ax25.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -1052,6 +1052,11 @@ static int ax25_release(struct socket *s
+               ax25_destroy_socket(ax25);
+       }
+       if (ax25_dev) {
++              del_timer_sync(&ax25->timer);
++              del_timer_sync(&ax25->t1timer);
++              del_timer_sync(&ax25->t2timer);
++              del_timer_sync(&ax25->t3timer);
++              del_timer_sync(&ax25->idletimer);
+               dev_put(ax25_dev->dev);
+               ax25_dev_put(ax25_dev);
+       }
diff --git a/queue-5.10/ax25-fix-uaf-bugs-of-net_device-caused-by-rebinding-operation.patch b/queue-5.10/ax25-fix-uaf-bugs-of-net_device-caused-by-rebinding-operation.patch
new file mode 100644 (file)
index 0000000..a86db23
--- /dev/null
@@ -0,0 +1,101 @@
+From foo@baz Mon Apr 18 01:53:59 PM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Fri, 15 Apr 2022 20:49:28 +0300
+Subject: ax25: fix UAF bugs of net_device caused by rebinding operation
+To: stable@vger.kernel.org
+Message-ID: <20220415174933.1076972-3-ovidiu.panait@windriver.com>
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+commit feef318c855a361a1eccd880f33e88c460eb63b4 upstream.
+
+The ax25_kill_by_device() will set s->ax25_dev = NULL and
+call ax25_disconnect() to change states of ax25_cb and
+sock, if we call ax25_bind() before ax25_kill_by_device().
+
+However, if we call ax25_bind() again between the window of
+ax25_kill_by_device() and ax25_dev_device_down(), the values
+and states changed by ax25_kill_by_device() will be reassigned.
+
+Finally, ax25_dev_device_down() will deallocate net_device.
+If we dereference net_device in syscall functions such as
+ax25_release(), ax25_sendmsg(), ax25_getsockopt(), ax25_getname()
+and ax25_info_show(), a UAF bug will occur.
+
+One of the possible race conditions is shown below:
+
+      (USE)                   |      (FREE)
+ax25_bind()                   |
+                              |  ax25_kill_by_device()
+ax25_bind()                   |
+ax25_connect()                |    ...
+                              |  ax25_dev_device_down()
+                              |    ...
+                              |    dev_put_track(dev, ...) //FREE
+ax25_release()                |    ...
+  ax25_send_control()         |
+    alloc_skb()      //USE    |
+
+the corresponding fail log is shown below:
+===============================================================
+BUG: KASAN: use-after-free in ax25_send_control+0x43/0x210
+...
+Call Trace:
+  ...
+  ax25_send_control+0x43/0x210
+  ax25_release+0x2db/0x3b0
+  __sock_release+0x6d/0x120
+  sock_close+0xf/0x20
+  __fput+0x11f/0x420
+  ...
+Allocated by task 1283:
+  ...
+  __kasan_kmalloc+0x81/0xa0
+  alloc_netdev_mqs+0x5a/0x680
+  mkiss_open+0x6c/0x380
+  tty_ldisc_open+0x55/0x90
+  ...
+Freed by task 1969:
+  ...
+  kfree+0xa3/0x2c0
+  device_release+0x54/0xe0
+  kobject_put+0xa5/0x120
+  tty_ldisc_kill+0x3e/0x80
+  ...
+
+In order to fix these UAF bugs caused by rebinding operation,
+this patch adds dev_hold_track() into ax25_bind() and
+corresponding dev_put_track() into ax25_kill_by_device().
+
+Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[OP: backport to 5.10: adjust dev_put_track()->dev_put() and
+dev_hold_track()->dev_hold()]
+Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ax25/af_ax25.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -98,6 +98,7 @@ again:
+                       spin_unlock_bh(&ax25_list_lock);
+                       lock_sock(sk);
+                       s->ax25_dev = NULL;
++                      dev_put(ax25_dev->dev);
+                       ax25_dev_put(ax25_dev);
+                       release_sock(sk);
+                       ax25_disconnect(s, ENETUNREACH);
+@@ -1122,8 +1123,10 @@ static int ax25_bind(struct socket *sock
+               }
+       }
+-      if (ax25_dev != NULL)
++      if (ax25_dev) {
+               ax25_fillin_cb(ax25, ax25_dev);
++              dev_hold(ax25_dev->dev);
++      }
+ done:
+       ax25_cb_add(ax25);
index 8ab1895a0a0214fd7e40ecd26d01f7d0775b3082..697e47f145d75e8eaa1c912e4e5d62a820587376 100644 (file)
@@ -95,3 +95,11 @@ timers-fix-warning-condition-in-__run_timers.patch
 dma-direct-avoid-redundant-memory-sync-for-swiotlb.patch
 scsi-iscsi-fix-endpoint-reuse-regression.patch
 scsi-iscsi-fix-unbound-endpoint-error-handling.patch
+ax25-add-refcount-in-ax25_dev-to-avoid-uaf-bugs.patch
+ax25-fix-reference-count-leaks-of-ax25_dev.patch
+ax25-fix-uaf-bugs-of-net_device-caused-by-rebinding-operation.patch
+ax25-fix-refcount-leaks-caused-by-ax25_cb_del.patch
+ax25-fix-uaf-bug-in-ax25_send_control.patch
+ax25-fix-npd-bug-in-ax25_disconnect.patch
+ax25-fix-null-pointer-dereferences-in-ax25-timers.patch
+ax25-fix-uaf-bugs-in-ax25-timers.patch