mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-13 14:24:11 +08:00
ax25: Fix NULL pointer dereferences in ax25 timers
commitfc6d01ff9e
upstream. The previous commit7ec02f5ac8
("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:7ec02f5ac8
("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.4: adjust context] Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d2be5b563e
commit
40cb8b3b19
@ -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);
|
||||
|
@ -261,12 +261,20 @@ void ax25_disconnect(ax25_cb *ax25, int reason)
|
||||
{
|
||||
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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user