Skip to content

Commit 5de7665

Browse files
Eric Dumazetkuba-moo
authored andcommitted
net: rose: fix timer races against user threads
Rose timers only acquire the socket spinlock, without checking if the socket is owned by one user thread. Add a check and rearm the timers if needed. BUG: KASAN: slab-use-after-free in rose_timer_expiry+0x31d/0x360 net/rose/rose_timer.c:174 Read of size 2 at addr ffff88802f09b82a by task swapper/0/0 CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.13.0-rc5-syzkaller-00172-gd1bf27c4e176 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024 Call Trace: <IRQ> __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:378 [inline] print_report+0x169/0x550 mm/kasan/report.c:489 kasan_report+0x143/0x180 mm/kasan/report.c:602 rose_timer_expiry+0x31d/0x360 net/rose/rose_timer.c:174 call_timer_fn+0x187/0x650 kernel/time/timer.c:1793 expire_timers kernel/time/timer.c:1844 [inline] __run_timers kernel/time/timer.c:2418 [inline] __run_timer_base+0x66a/0x8e0 kernel/time/timer.c:2430 run_timer_base kernel/time/timer.c:2439 [inline] run_timer_softirq+0xb7/0x170 kernel/time/timer.c:2449 handle_softirqs+0x2d4/0x9b0 kernel/softirq.c:561 __do_softirq kernel/softirq.c:595 [inline] invoke_softirq kernel/softirq.c:435 [inline] __irq_exit_rcu+0xf7/0x220 kernel/softirq.c:662 irq_exit_rcu+0x9/0x30 kernel/softirq.c:678 instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1049 [inline] sysvec_apic_timer_interrupt+0xa6/0xc0 arch/x86/kernel/apic/apic.c:1049 </IRQ> Fixes: 1da177e ("Linux-2.6.12-rc2") Reported-by: syzbot <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 09ebd02 commit 5de7665

File tree

1 file changed

+15
-0
lines changed

1 file changed

+15
-0
lines changed

net/rose/rose_timer.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ static void rose_heartbeat_expiry(struct timer_list *t)
122122
struct rose_sock *rose = rose_sk(sk);
123123

124124
bh_lock_sock(sk);
125+
if (sock_owned_by_user(sk)) {
126+
sk_reset_timer(sk, &sk->sk_timer, jiffies + HZ/20);
127+
goto out;
128+
}
125129
switch (rose->state) {
126130
case ROSE_STATE_0:
127131
/* Magic here: If we listen() and a new link dies before it
@@ -152,6 +156,7 @@ static void rose_heartbeat_expiry(struct timer_list *t)
152156
}
153157

154158
rose_start_heartbeat(sk);
159+
out:
155160
bh_unlock_sock(sk);
156161
sock_put(sk);
157162
}
@@ -162,6 +167,10 @@ static void rose_timer_expiry(struct timer_list *t)
162167
struct sock *sk = &rose->sock;
163168

164169
bh_lock_sock(sk);
170+
if (sock_owned_by_user(sk)) {
171+
sk_reset_timer(sk, &rose->timer, jiffies + HZ/20);
172+
goto out;
173+
}
165174
switch (rose->state) {
166175
case ROSE_STATE_1: /* T1 */
167176
case ROSE_STATE_4: /* T2 */
@@ -182,6 +191,7 @@ static void rose_timer_expiry(struct timer_list *t)
182191
}
183192
break;
184193
}
194+
out:
185195
bh_unlock_sock(sk);
186196
sock_put(sk);
187197
}
@@ -192,6 +202,10 @@ static void rose_idletimer_expiry(struct timer_list *t)
192202
struct sock *sk = &rose->sock;
193203

194204
bh_lock_sock(sk);
205+
if (sock_owned_by_user(sk)) {
206+
sk_reset_timer(sk, &rose->idletimer, jiffies + HZ/20);
207+
goto out;
208+
}
195209
rose_clear_queues(sk);
196210

197211
rose_write_internal(sk, ROSE_CLEAR_REQUEST);
@@ -207,6 +221,7 @@ static void rose_idletimer_expiry(struct timer_list *t)
207221
sk->sk_state_change(sk);
208222
sock_set_flag(sk, SOCK_DEAD);
209223
}
224+
out:
210225
bh_unlock_sock(sk);
211226
sock_put(sk);
212227
}

0 commit comments

Comments
 (0)