Skip to content

Commit 395b657

Browse files
f6bvpgregkh
authored andcommitted
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>
1 parent 9e8fc21 commit 395b657

1 file changed

Lines changed: 9 additions & 1 deletion

File tree

net/rose/af_rose.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,16 @@ static void rose_kill_by_device(struct net_device *dev)
216216
* looping forever in ROSE_STATE_0 with no owner.
217217
*/
218218
sock_set_flag(sk, SOCK_DESTROY);
219-
if (rose->neighbour)
219+
if (rose->neighbour) {
220220
rose_neigh_put(rose->neighbour);
221+
/* Clear the pointer after dropping the reference, as
222+
* every other rose_neigh_put() site does. Otherwise
223+
* rose_heartbeat_expiry() (STATE_0 reaping) sees a stale
224+
* rose->neighbour and puts it a second time -> rose_neigh
225+
* refcount underflow / use-after-free.
226+
*/
227+
rose->neighbour = NULL;
228+
}
221229
netdev_put(rose->device, &rose->dev_tracker);
222230
rose->device = NULL;
223231
}

0 commit comments

Comments
 (0)