Skip to content

rose: guard rose_transmit_link() against a NULL neighbour - #5

Merged
kuba-moo merged 1 commit into
linux-netdev:mainfrom
f6bvp:rose-fix-neighbour-null-transmit
Sep 11, 2026
Merged

rose: guard rose_transmit_link() against a NULL neighbour#5
kuba-moo merged 1 commit into
linux-netdev:mainfrom
f6bvp:rose-fix-neighbour-null-transmit

Conversation

@f6bvp

@f6bvp f6bvp commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

rose_kick() and rose_write_internal() call rose_transmit_link(skb,
rose->neighbour) without checking that rose->neighbour is still set.
Since commit e8eb0c6 ("rose: clear neighbour pointer after
rose_neigh_put() in state machines"), the state machines routinely set
rose->neighbour to NULL once the underlying AX.25 link is gone, while
leaving the socket in ROSE_STATE_3. rose_kick() only checks the state,
not the neighbour, so a write() on such a socket reaches
rose_transmit_link() with neigh == NULL, which immediately
dereferences neigh->loopback and crashes:

Unable to handle kernel NULL pointer dereference at
virtual address 0000000000000036
...
pc : rose_transmit_link+0x14/0x1c8 [rose]
lr : rose_kick+0xec/0x198 [rose]
Call trace:
rose_transmit_link+0x14/0x1c8 [rose] (P)
rose_kick+0xec/0x198 [rose]
rose_sendmsg+0x260/0x3c8 [rose]

Reproduced on f6bvp-8 (a real ROSE/FPAC node) when the BBS daemon
wrote to a socket whose neighbour had just been cleared. Confirmed by
recompiling rose_link.o with a static_assert on
offsetof(struct rose_neigh, loopback), which matches the faulting
address (0x36) exactly.

Fix: drop the skb and return early when neigh is NULL, matching what
rose_transmit_link() already does for other frames it cannot send.

Fixes: e8eb0c6 ("rose: clear neighbour pointer after rose_neigh_put() in state machines")

Single commit, applies cleanly to current main.

rose_kick() and rose_write_internal() call rose_transmit_link(skb,
rose->neighbour) without checking that rose->neighbour is still set.
Since commit e8eb0c6 ("rose: clear neighbour pointer after
rose_neigh_put() in state machines"), the state machines routinely set
rose->neighbour to NULL once the underlying AX.25 link is gone, while
leaving the socket in ROSE_STATE_3. rose_kick() only checks the
state, not the neighbour, so a write() on such a socket reaches
rose_transmit_link() with neigh == NULL, which immediately
dereferences neigh->loopback and crashes:

  Unable to handle kernel NULL pointer dereference at
  virtual address 0000000000000036
  ...
  pc : rose_transmit_link+0x14/0x1c8 [rose]
  lr : rose_kick+0xec/0x198 [rose]
  Call trace:
   rose_transmit_link+0x14/0x1c8 [rose] (P)
   rose_kick+0xec/0x198 [rose]
   rose_sendmsg+0x260/0x3c8 [rose]

Reproduced on f6bvp-8 (a real ROSE/FPAC node) when the BBS daemon
wrote to a socket whose neighbour had just been cleared. Confirmed
by recompiling rose_link.o with a static_assert on
offsetof(struct rose_neigh, loopback), which matches the faulting
address (0x36) exactly.

Drop the skb and return early when neigh is NULL, matching what
rose_transmit_link() already does for other frames it cannot send.

Fixes: e8eb0c6 ("rose: clear neighbour pointer after rose_neigh_put() in state machines")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
@kuba-moo
kuba-moo merged commit 2aa2cf6 into linux-netdev:main Sep 11, 2026
@f6bvp
f6bvp deleted the rose-fix-neighbour-null-transmit branch September 12, 2026 08:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants