From: Arjan van de Ven <arjan@linux.intel.com>
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, edumazet@google.com, horms@kernel.org,
jreuter@yaina.de, kuba@kernel.org, linux-hams@vger.kernel.org,
linux-kernel@vger.kernel.org, pabeni@redhat.com,
syzkaller-bugs@googlegroups.com,
syzbot+9c8999af06ca7df15fc6@syzkaller.appspotmail.com
Subject: Re: [syzbot] [hams?] KASAN: slab-use-after-free Read in ax25_send_frame (3)
Date: Mon, 27 Apr 2026 08:25:26 -0700 [thread overview]
Message-ID: <20260427152555.500903-1-arjan@linux.intel.com> (raw)
In-Reply-To: <69ef2847.170a0220.11de9.001a.GAE@google.com>
This email is created by automation to help kernel developers
deal with a large volume of AI generated bug reports by decoding
oopses into more actionable information.
Decoded Backtrace
net/ax25/ax25_out.c (crash site, UAF read)
32 ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen,
32 const ax25_address *src, ax25_address *dest,
32 ax25_digi *digi, struct net_device *dev)
33 {
34 ax25_dev *ax25_dev;
35 ax25_cb *ax25;
...
77 if (digi != NULL) {
->78 ax25->digipeat = kmemdup(digi, sizeof(*digi), GFP_ATOMIC);
// <- digi = neigh->digipeat; freed ax25_digi; 66-byte UAF read
79 if (ax25->digipeat == NULL) {
...
115 return ax25;
116 }
net/rose/rose_link.c (caller, t0timer callback)
79 static void rose_t0timer_expiry(struct timer_list *t)
80 {
81 struct rose_neigh *neigh = timer_container_of(neigh, t, t0timer);
82
->83 rose_transmit_restart_request(neigh);
// <- inlined; calls rose_send_frame -> ax25_send_frame
// with neigh->digipeat as the digi argument
84
85 neigh->dce_mode = 0;
86
87 rose_start_t0timer(neigh);
88 }
rose_send_frame() inlined at rose_link.c:106:
95 static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh)
96 {
...
105 ax25s = neigh->ax25;
->106 neigh->ax25 = ax25_send_frame(skb, 260, rose_call,
&neigh->callsign, neigh->digipeat, neigh->dev);
// <- neigh->digipeat passed as digi; freed by rose_timer_expiry
107 if (ax25s)
108 ax25_cb_put(ax25s);
109 return neigh->ax25 != NULL;
110 }
net/rose/rose_timer.c (free site)
164 static void rose_timer_expiry(struct timer_list *t)
165 {
166 struct rose_sock *rose = timer_container_of(rose, t, timer);
167 struct sock *sk = &rose->sock;
...
174 switch (rose->state) {
...
182 case ROSE_STATE_2: /* T3 */
->183 rose_neigh_put(rose->neighbour);
// <- drops refcount to 0; frees neigh->digipeat (ax25_digi)
// and neigh itself; t0timer still pending
184 rose_disconnect(sk, ETIMEDOUT, -1, -1);
185 break;
...
197 }
include/net/rose.h (rose_neigh_put, inline free function)
160 static inline void rose_neigh_put(struct rose_neigh *rose_neigh)
161 {
162 if (refcount_dec_and_test(&rose_neigh->use)) {
163 if (rose_neigh->ax25)
164 ax25_cb_put(rose_neigh->ax25);
->165 kfree(rose_neigh->digipeat);
// <- frees the ax25_digi (66 bytes); t0timer not cancelled
166 kfree(rose_neigh);
167 }
168 }
net/rose/rose_route.c (allocation site)
84 if (rose_neigh == NULL) {
85 rose_neigh = kmalloc_obj(*rose_neigh, GFP_ATOMIC);
...
100 refcount_set(&rose_neigh->use, 1);
...
107 if (rose_route->ndigis != 0) {
108 rose_neigh->digipeat =
->109 kmalloc_obj(ax25_digi, GFP_ATOMIC);
// <- allocates the 66-byte ax25_digi later freed and read
...
124 }
125 }
Tentative Analysis
The crash is a KASAN slab-use-after-free: rose_t0timer_expiry() reads
the freed rose_neigh->digipeat (an ax25_digi struct, 66 bytes) via
ax25_send_frame() -> kmemdup().
Commit d860d1faa6b2 ("net: rose: convert 'use' field to refcount_t")
changed rose_timer_expiry() from merely decrementing the plain 'use'
counter to calling rose_neigh_put(), which now frees rose_neigh (and
its digipeat) when the refcount hits zero. The new rose_neigh_put()
omits timer cancellation, so after it returns the t0timer embedded in
the (now-freed) rose_neigh can still fire in the same TIMER_SOFTIRQ
batch.
The race on a single-CPU machine (the syzbot scenario) is purely
sequential: rose_timer_expiry() fires first, frees the neigh; then
rose_t0timer_expiry() fires next in the same run_timer_base batch with
a dangling neigh pointer, passes neigh->digipeat to ax25_send_frame,
and kmemdup triggers the KASAN report.
Before d860d1faa6b2, rose_timer_expiry() never freed the neigh; the
free was always performed by rose_remove_neigh() which called
timer_delete_sync() on both timers before freeing. The refcount
conversion introduced a new free path that missed this cancellation.
Potential Solution
Add timer_delete() calls for both ftimer and t0timer inside
rose_neigh_put() before the kfree calls, mirroring what
rose_remove_neigh() already does via timer_delete_sync(). The
non-synchronous variant is required because rose_neigh_put() may be
called from softirq context.
static inline void rose_neigh_put(struct rose_neigh *rose_neigh)
{
if (refcount_dec_and_test(&rose_neigh->use)) {
timer_delete(&rose_neigh->ftimer);
timer_delete(&rose_neigh->t0timer);
if (rose_neigh->ax25)
ax25_cb_put(rose_neigh->ax25);
kfree(rose_neigh->digipeat);
kfree(rose_neigh);
}
}
More information
Oops-Analysis: http://oops.fenrus.org/reports/lkml/69ef2847.170a0220.11de9.001a.GAE_google.com/
Assisted-by: Copilot:claude-sonnet-4.6 linux-kernel-oops-x86.
prev parent reply other threads:[~2026-04-27 15:24 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-27 9:11 [syzbot] [hams?] KASAN: slab-use-after-free Read in ax25_send_frame (3) syzbot
2026-04-27 15:25 ` Arjan van de Ven [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260427152555.500903-1-arjan@linux.intel.com \
--to=arjan@linux.intel.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=jreuter@yaina.de \
--cc=kuba@kernel.org \
--cc=linux-hams@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=syzbot+9c8999af06ca7df15fc6@syzkaller.appspotmail.com \
--cc=syzkaller-bugs@googlegroups.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox