Module Name: src Committed By: riastradh Date: Sun Apr 16 11:14:58 UTC 2023
Modified Files: src/sys/kern: subr_autoconf.c Log Message: autoconf(9): Avoid potential ABA bug in config_makeroom. When we unlock alldevs_lock to allocate a new cd_devs array nsp, other threads may have: 1. freed the old one (osp), 2. done some other memory allocation, 3. allocated a new _larger_ array whose address happens to concide with osp (e.g., in (2) the page was recycled for a different pool cache), and 4. updated cd_devs back to osp but increased cd_ndevs. In that case, the memory may be corrupted: we try to copy the wrong number of device_t pointers into nsp and we free osp with the wrong (stale) length. Avoid this by checking whether cd_ndevs has changed too -- if not, osp might have been recycled but at least the lengths we're about to copy and free are still correct so there's no harm in an ABA situation. XXX pullup-8 XXX pullup-9 XXX pullup-10 To generate a diff of this commit: cvs rdiff -u -r1.307 -r1.308 src/sys/kern/subr_autoconf.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/subr_autoconf.c diff -u src/sys/kern/subr_autoconf.c:1.307 src/sys/kern/subr_autoconf.c:1.308 --- src/sys/kern/subr_autoconf.c:1.307 Wed Feb 22 17:00:16 2023 +++ src/sys/kern/subr_autoconf.c Sun Apr 16 11:14:58 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_autoconf.c,v 1.307 2023/02/22 17:00:16 riastradh Exp $ */ +/* $NetBSD: subr_autoconf.c,v 1.308 2023/04/16 11:14:58 riastradh Exp $ */ /* * Copyright (c) 1996, 2000 Christopher G. Demetriou @@ -77,7 +77,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.307 2023/02/22 17:00:16 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.308 2023/04/16 11:14:58 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -1357,7 +1357,7 @@ config_makeroom(int n, struct cfdriver * * If another thread moved the array while we did * not hold alldevs_lock, try again. */ - if (cd->cd_devs != osp) { + if (cd->cd_devs != osp || cd->cd_ndevs != ondevs) { mutex_exit(&alldevs_lock); kmem_free(nsp, sizeof(device_t) * nndevs); mutex_enter(&alldevs_lock);