--- /dev/null
+From foo@baz Tue Apr 26 09:02:03 AM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Thu, 21 Apr 2022 13:37:32 +0300
+Subject: ax25: add refcount in ax25_dev to avoid UAF bugs
+To: stable@vger.kernel.org
+Cc: Duoming Zhou <duoming@zju.edu.cn>, "David S . Miller" <davem@davemloft.net>, Ovidiu Panait <ovidiu.panait@windriver.com>
+Message-ID: <20220421103739.1274449-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 4.14: 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
+@@ -235,6 +235,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 {
+@@ -289,6 +290,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
+@@ -101,6 +101,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);
+@@ -450,6 +451,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
+@@ -40,6 +40,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);
+
+@@ -59,6 +60,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);
+@@ -86,6 +88,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);
+@@ -115,20 +118,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;
+ }
+
+@@ -136,6 +141,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)
+@@ -152,6 +158,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:
+@@ -164,6 +171,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
+@@ -119,6 +119,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);
+@@ -175,6 +176,7 @@ static int ax25_rt_del(struct ax25_route
+ }
+ }
+ }
++ ax25_dev_put(ax25_dev);
+ write_unlock_bh(&ax25_route_lock);
+
+ return 0;
+@@ -217,6 +219,7 @@ static int ax25_rt_opt(struct ax25_route
+ }
+
+ out:
++ ax25_dev_put(ax25_dev);
+ write_unlock_bh(&ax25_route_lock);
+ return err;
+ }
--- /dev/null
+From foo@baz Tue Apr 26 09:02:03 AM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Thu, 21 Apr 2022 13:37:37 +0300
+Subject: ax25: fix NPD bug in ax25_disconnect
+To: stable@vger.kernel.org
+Cc: Duoming Zhou <duoming@zju.edu.cn>, "David S . Miller" <davem@davemloft.net>, Ovidiu Panait <ovidiu.panait@windriver.com>
+Message-ID: <20220421103739.1274449-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 4.14: 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
+@@ -105,8 +105,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
--- /dev/null
+From foo@baz Tue Apr 26 09:02:03 AM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Thu, 21 Apr 2022 13:37:38 +0300
+Subject: ax25: Fix NULL pointer dereferences in ax25 timers
+To: stable@vger.kernel.org
+Cc: Duoming Zhou <duoming@zju.edu.cn>, "David S . Miller" <davem@davemloft.net>, Ovidiu Panait <ovidiu.panait@windriver.com>
+Message-ID: <20220421103739.1274449-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 4.14: 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
+@@ -92,20 +92,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
+@@ -264,12 +264,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;
+
--- /dev/null
+From foo@baz Tue Apr 26 09:02:03 AM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Thu, 21 Apr 2022 13:37:35 +0300
+Subject: ax25: Fix refcount leaks caused by ax25_cb_del()
+To: stable@vger.kernel.org
+Cc: Duoming Zhou <duoming@zju.edu.cn>, Thomas Osterried <thomas@osterried.de>, "David S . Miller" <davem@davemloft.net>, Ovidiu Panait <ovidiu.panait@windriver.com>
+Message-ID: <20220421103739.1274449-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 4.14: 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
+@@ -101,8 +101,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);
+@@ -982,14 +984,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) {
--- /dev/null
+From foo@baz Tue Apr 26 09:02:03 AM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Thu, 21 Apr 2022 13:37:33 +0300
+Subject: ax25: fix reference count leaks of ax25_dev
+To: stable@vger.kernel.org
+Cc: Duoming Zhou <duoming@zju.edu.cn>, Dan Carpenter <dan.carpenter@oracle.com>, Jakub Kicinski <kuba@kernel.org>, Ovidiu Panait <ovidiu.panait@windriver.com>
+Message-ID: <20220421103739.1274449-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 4.14: 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
+@@ -290,10 +290,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
+@@ -370,21 +370,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
+@@ -88,8 +88,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);
+ }
+@@ -118,8 +118,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);
+@@ -129,8 +129,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);
+@@ -153,25 +153,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
+@@ -78,11 +78,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;
+@@ -94,6 +96,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;
+@@ -104,6 +107,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;
+@@ -111,6 +115,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;
+ }
+
+@@ -119,11 +124,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;
+@@ -136,6 +141,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;
+ }
+@@ -176,8 +182,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;
+ }
+@@ -219,8 +225,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;
+ }
+
--- /dev/null
+From foo@baz Tue Apr 26 09:02:03 AM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Thu, 21 Apr 2022 13:37:36 +0300
+Subject: ax25: fix UAF bug in ax25_send_control()
+To: stable@vger.kernel.org
+Cc: Duoming Zhou <duoming@zju.edu.cn>, Paolo Abeni <pabeni@redhat.com>, Ovidiu Panait <ovidiu.panait@windriver.com>
+Message-ID: <20220421103739.1274449-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 4.14: 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
+@@ -994,10 +994,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) {
+@@ -1059,6 +1055,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);
--- /dev/null
+From foo@baz Tue Apr 26 09:02:03 AM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Thu, 21 Apr 2022 13:37:39 +0300
+Subject: ax25: Fix UAF bugs in ax25 timers
+To: stable@vger.kernel.org
+Cc: Duoming Zhou <duoming@zju.edu.cn>, Paolo Abeni <pabeni@redhat.com>, Ovidiu Panait <ovidiu.panait@windriver.com>
+Message-ID: <20220421103739.1274449-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 4.14: 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
+@@ -1056,6 +1056,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);
+ }
--- /dev/null
+From foo@baz Tue Apr 26 09:02:03 AM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Thu, 21 Apr 2022 13:37:34 +0300
+Subject: ax25: fix UAF bugs of net_device caused by rebinding operation
+To: stable@vger.kernel.org
+Cc: Duoming Zhou <duoming@zju.edu.cn>, "David S . Miller" <davem@davemloft.net>, Ovidiu Panait <ovidiu.panait@windriver.com>
+Message-ID: <20220421103739.1274449-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 4.14: 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
+@@ -101,6 +101,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);
+@@ -1126,8 +1127,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);
--- /dev/null
+From marex@denx.de Tue Apr 26 09:09:57 2022
+From: Marek Vasut <marex@denx.de>
+Date: Mon, 25 Apr 2022 23:48:59 +0200
+Subject: Revert "net: micrel: fix KS8851_MLL Kconfig"
+To: stable@vger.kernel.org
+Cc: Marek Vasut <marex@denx.de>, "David S . Miller" <davem@davemloft.net>, Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>, Randy Dunlap <rdunlap@infradead.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20220425214859.256650-1-marex@denx.de>
+
+From: Marek Vasut <marex@denx.de>
+
+This reverts commit 84ddee4ea320411fa038d4f1fd9a0161f989b482 which is
+commit c3efcedd272aa6dd5929e20cf902a52ddaa1197a upstream.
+
+The upstream commit 84ddee4ea320 ("net: micrel: fix KS8851_MLL Kconfig")
+depends on e5f31552674e ("ethernet: fix PTP_1588_CLOCK dependencies")
+which is not part of Linux 4.14.y . Revert the aforementioned commit to
+prevent breakage in 4.14.y .
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Cc: David S. Miller <davem@davemloft.net>
+Cc: Jakub Kicinski <kuba@kernel.org>
+Cc: Paolo Abeni <pabeni@redhat.com>
+Cc: Randy Dunlap <rdunlap@infradead.org>
+Cc: Sasha Levin <sashal@kernel.org>
+Cc: <stable@vger.kernel.org> # 5.10.x
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/ethernet/micrel/Kconfig | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/net/ethernet/micrel/Kconfig
++++ b/drivers/net/ethernet/micrel/Kconfig
+@@ -45,7 +45,6 @@ config KS8851
+ config KS8851_MLL
+ tristate "Micrel KS8851 MLL"
+ depends on HAS_IOMEM
+- depends on PTP_1588_CLOCK_OPTIONAL
+ select MII
+ ---help---
+ This platform driver is for Micrel KS8851 Address/data bus
ext4-force-overhead-calculation-if-the-s_overhead_cluster-makes-no-sense.patch
staging-ion-prevent-incorrect-reference-counting-behavour.patch
block-compat_ioctl-fix-range-check-in-blkgetsize.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
+revert-net-micrel-fix-ks8851_mll-kconfig.patch