rose_loopback_timer() dereferences rose_loopback_neigh throughout its body but holds no reference on it. A concurrent rose_loopback_clear() followed by rose_add_loopback_neigh() could free and reallocate the neighbour while the timer body is running, causing a use-after-free. Take a reference with rose_neigh_hold() at the start of the callback (bailing out if the pointer is already NULL) and release it with rose_neigh_put() at the single exit point. The neigh cannot be freed while the callback holds a reference. Fixes: d860d1faa6b2 ("net: rose: convert 'use' field to refcount_t") Tested-by: Bernard Pidoux Signed-off-by: Bernard Pidoux --- net/rose/rose_loopback.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c index 914c8f453a1d..d66913df360d 100644 --- a/net/rose/rose_loopback.c +++ b/net/rose/rose_loopback.c @@ -66,10 +66,15 @@ static void rose_loopback_timer(struct timer_list *unused) unsigned int lci_i, lci_o; int count; + if (rose_loopback_neigh) + rose_neigh_hold(rose_loopback_neigh); + else + return; + for (count = 0; count < ROSE_LOOPBACK_LIMIT; count++) { skb = skb_dequeue(&loopback_queue); if (!skb) - return; + goto out; if (skb->len < ROSE_MIN_LEN) { kfree_skb(skb); continue; @@ -109,6 +114,10 @@ static void rose_loopback_timer(struct timer_list *unused) kfree_skb(skb); } } + +out: + rose_neigh_put(rose_loopback_neigh); + if (!skb_queue_empty(&loopback_queue)) mod_timer(&loopback_timer, jiffies + 1); } -- 2.51.0