Skip to content

Commit 057a10f

Browse files
lxinkuba-moo
authored andcommitted
sctp: change to hold/put transport for proto_unreach_timer
A call trace was found in Hangbin's Codenomicon testing with debug kernel: [ 2615.981988] ODEBUG: free active (active state 0) object type: timer_list hint: sctp_generate_proto_unreach_event+0x0/0x3a0 [sctp] [ 2615.995050] WARNING: CPU: 17 PID: 0 at lib/debugobjects.c:328 debug_print_object+0x199/0x2b0 [ 2616.095934] RIP: 0010:debug_print_object+0x199/0x2b0 [ 2616.191533] Call Trace: [ 2616.194265] <IRQ> [ 2616.202068] debug_check_no_obj_freed+0x25e/0x3f0 [ 2616.207336] slab_free_freelist_hook+0xeb/0x140 [ 2616.220971] kfree+0xd6/0x2c0 [ 2616.224293] rcu_do_batch+0x3bd/0xc70 [ 2616.243096] rcu_core+0x8b9/0xd00 [ 2616.256065] __do_softirq+0x23d/0xacd [ 2616.260166] irq_exit+0x236/0x2a0 [ 2616.263879] smp_apic_timer_interrupt+0x18d/0x620 [ 2616.269138] apic_timer_interrupt+0xf/0x20 [ 2616.273711] </IRQ> This is because it holds asoc when transport->proto_unreach_timer starts and puts asoc when the timer stops, and without holding transport the transport could be freed when the timer is still running. So fix it by holding/putting transport instead for proto_unreach_timer in transport, just like other timers in transport. v1->v2: - Also use sctp_transport_put() for the "out_unlock:" path in sctp_generate_proto_unreach_event(), as Marcelo noticed. Fixes: 50b5d6a ("sctp: Fix a race between ICMP protocol unreachable and connect()") Reported-by: Hangbin Liu <[email protected]> Signed-off-by: Xin Long <[email protected]> Acked-by: Marcelo Ricardo Leitner <[email protected]> Link: https://lore.kernel.org/r/102788809b554958b13b95d33440f5448113b8d6.1605331373.git.lucien.xin@gmail.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 65b422d commit 057a10f

File tree

3 files changed

+5
-5
lines changed

3 files changed

+5
-5
lines changed

net/sctp/input.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
449449
else {
450450
if (!mod_timer(&t->proto_unreach_timer,
451451
jiffies + (HZ/20)))
452-
sctp_association_hold(asoc);
452+
sctp_transport_hold(t);
453453
}
454454
} else {
455455
struct net *net = sock_net(sk);
@@ -458,7 +458,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
458458
"encountered!\n", __func__);
459459

460460
if (del_timer(&t->proto_unreach_timer))
461-
sctp_association_put(asoc);
461+
sctp_transport_put(t);
462462

463463
sctp_do_sm(net, SCTP_EVENT_T_OTHER,
464464
SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),

net/sctp/sm_sideeffect.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ void sctp_generate_proto_unreach_event(struct timer_list *t)
419419
/* Try again later. */
420420
if (!mod_timer(&transport->proto_unreach_timer,
421421
jiffies + (HZ/20)))
422-
sctp_association_hold(asoc);
422+
sctp_transport_hold(transport);
423423
goto out_unlock;
424424
}
425425

@@ -435,7 +435,7 @@ void sctp_generate_proto_unreach_event(struct timer_list *t)
435435

436436
out_unlock:
437437
bh_unlock_sock(sk);
438-
sctp_association_put(asoc);
438+
sctp_transport_put(transport);
439439
}
440440

441441
/* Handle the timeout of the RE-CONFIG timer. */

net/sctp/transport.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ void sctp_transport_free(struct sctp_transport *transport)
133133

134134
/* Delete the ICMP proto unreachable timer if it's active. */
135135
if (del_timer(&transport->proto_unreach_timer))
136-
sctp_association_put(transport->asoc);
136+
sctp_transport_put(transport);
137137

138138
sctp_transport_put(transport);
139139
}

0 commit comments

Comments
 (0)