diff options
| author | Bernard Pidoux <bernard.f6bvp@gmail.com> | 2026-05-31 15:41:45 +0200 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-06-27 11:07:40 +0100 |
| commit | 4507ce5fec5edd8d2c2d8106cc8e6be0f167793e (patch) | |
| tree | f5ed2c6866d5738a295fb81e4d99120d1b30b8c5 | |
| parent | 0c7919c4f1767a3402aed4118045d1f7bc72fef5 (diff) | |
| download | linux-stable-4507ce5fec5edd8d2c2d8106cc8e6be0f167793e.tar.gz linux-stable-4507ce5fec5edd8d2c2d8106cc8e6be0f167793e.zip | |
rose: clear neighbour pointer in rose_kill_by_device()
commit 606e42d195b467480d4d405f8814c48d1651a76a upstream.
rose_kill_by_device() drops the neighbour reference but leaves
rose->neighbour pointing at it, unlike every other rose_neigh_put() site
(see "rose: clear neighbour pointer after rose_neigh_put() in state
machines"). The heartbeat STATE_0 reaping path then puts the same
neighbour a second time, causing a rose_neigh refcount underflow and a
use-after-free.
Set rose->neighbour = NULL after the put, restoring the invariant.
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | net/rose/af_rose.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 81b34b2ddf04..f32344c33a6f 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -216,8 +216,16 @@ start: * looping forever in ROSE_STATE_0 with no owner. */ sock_set_flag(sk, SOCK_DESTROY); - if (rose->neighbour) + if (rose->neighbour) { rose_neigh_put(rose->neighbour); + /* Clear the pointer after dropping the reference, as + * every other rose_neigh_put() site does. Otherwise + * rose_heartbeat_expiry() (STATE_0 reaping) sees a stale + * rose->neighbour and puts it a second time -> rose_neigh + * refcount underflow / use-after-free. + */ + rose->neighbour = NULL; + } netdev_put(rose->device, &rose->dev_tracker); rose->device = NULL; } |
