Sun Apr 16 11:14:58 2023 UTC ()
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


(riastradh)
diff -r1.307 -r1.308 src/sys/kern/subr_autoconf.c

cvs diff -r1.307 -r1.308 src/sys/kern/subr_autoconf.c (expand / switch to unified diff)

--- src/sys/kern/subr_autoconf.c 2023/02/22 17:00:16 1.307
+++ src/sys/kern/subr_autoconf.c 2023/04/16 11:14:58 1.308
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: subr_autoconf.c,v 1.307 2023/02/22 17:00:16 riastradh Exp $ */ 1/* $NetBSD: subr_autoconf.c,v 1.308 2023/04/16 11:14:58 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1996, 2000 Christopher G. Demetriou 4 * Copyright (c) 1996, 2000 Christopher G. Demetriou
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -67,27 +67,27 @@ @@ -67,27 +67,27 @@
67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 * SUCH DAMAGE. 72 * SUCH DAMAGE.
73 * 73 *
74 * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp (LBL) 74 * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp (LBL)
75 * 75 *
76 * @(#)subr_autoconf.c 8.3 (Berkeley) 5/17/94 76 * @(#)subr_autoconf.c 8.3 (Berkeley) 5/17/94
77 */ 77 */
78 78
79#include <sys/cdefs.h> 79#include <sys/cdefs.h>
80__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.307 2023/02/22 17:00:16 riastradh Exp $"); 80__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.308 2023/04/16 11:14:58 riastradh Exp $");
81 81
82#ifdef _KERNEL_OPT 82#ifdef _KERNEL_OPT
83#include "opt_ddb.h" 83#include "opt_ddb.h"
84#include "drvctl.h" 84#include "drvctl.h"
85#endif 85#endif
86 86
87#include <sys/param.h> 87#include <sys/param.h>
88#include <sys/device.h> 88#include <sys/device.h>
89#include <sys/device_impl.h> 89#include <sys/device_impl.h>
90#include <sys/disklabel.h> 90#include <sys/disklabel.h>
91#include <sys/conf.h> 91#include <sys/conf.h>
92#include <sys/kauth.h> 92#include <sys/kauth.h>
93#include <sys/kmem.h> 93#include <sys/kmem.h>
@@ -1347,27 +1347,27 @@ config_makeroom(int n, struct cfdriver * @@ -1347,27 +1347,27 @@ config_makeroom(int n, struct cfdriver *
1347 1347
1348 /* 1348 /*
1349 * Release alldevs_lock around allocation, which may 1349 * Release alldevs_lock around allocation, which may
1350 * sleep. 1350 * sleep.
1351 */ 1351 */
1352 mutex_exit(&alldevs_lock); 1352 mutex_exit(&alldevs_lock);
1353 nsp = kmem_alloc(sizeof(device_t) * nndevs, KM_SLEEP); 1353 nsp = kmem_alloc(sizeof(device_t) * nndevs, KM_SLEEP);
1354 mutex_enter(&alldevs_lock); 1354 mutex_enter(&alldevs_lock);
1355 1355
1356 /* 1356 /*
1357 * If another thread moved the array while we did 1357 * If another thread moved the array while we did
1358 * not hold alldevs_lock, try again. 1358 * not hold alldevs_lock, try again.
1359 */ 1359 */
1360 if (cd->cd_devs != osp) { 1360 if (cd->cd_devs != osp || cd->cd_ndevs != ondevs) {
1361 mutex_exit(&alldevs_lock); 1361 mutex_exit(&alldevs_lock);
1362 kmem_free(nsp, sizeof(device_t) * nndevs); 1362 kmem_free(nsp, sizeof(device_t) * nndevs);
1363 mutex_enter(&alldevs_lock); 1363 mutex_enter(&alldevs_lock);
1364 continue; 1364 continue;
1365 } 1365 }
1366 1366
1367 memset(nsp + ondevs, 0, sizeof(device_t) * (nndevs - ondevs)); 1367 memset(nsp + ondevs, 0, sizeof(device_t) * (nndevs - ondevs));
1368 if (ondevs != 0) 1368 if (ondevs != 0)
1369 memcpy(nsp, cd->cd_devs, sizeof(device_t) * ondevs); 1369 memcpy(nsp, cd->cd_devs, sizeof(device_t) * ondevs);
1370 1370
1371 cd->cd_ndevs = nndevs; 1371 cd->cd_ndevs = nndevs;
1372 cd->cd_devs = nsp; 1372 cd->cd_devs = nsp;
1373 if (ondevs != 0) { 1373 if (ondevs != 0) {