randomread and randomwrite both allocate 4kB on the stack whilst a user is saving/restoring the system entropy pool. This is bad. Specifically, combined with a stack-heavy networking load (e.g. ping flooding a CARP address on a VLAN interface), dd's u_pcb structure is corrupted when running /etc/rc and performing such a save/restore. This manifests as a panic at "dd" exit time, as the proc->p_addr->u_pcb.pcb_fpcpu would be corrupted, falsely triggering a npxsave_proc call to flush the floating point state, and tripping an assertion as this process hadn't actually used the FPU... Removing this array from the stack and turning it into a dynamic allocation fixes this. Chris Pascoe 2004/07/02 Index: rnd.c =================================================================== RCS file: /cvs/src/sys/dev/rnd.c,v retrieving revision 1.70 diff -u -r1.70 rnd.c --- rnd.c 7 May 2004 14:42:27 -0000 1.70 +++ rnd.c 2 Jul 2004 11:54:46 -0000 @@ -957,15 +957,17 @@ struct uio *uio; int ioflag; { - int ret = 0; - int i; + int ret = 0; + int i; + u_int32_t *buf; if (uio->uio_resid == 0) return 0; + buf = malloc(4 * POOLWORDS, M_TEMP, M_WAITOK); + while (!ret && uio->uio_resid > 0) { - u_int32_t buf[ POOLWORDS ]; - int n = min(sizeof(buf), uio->uio_resid); + int n = min(4 * POOLWORDS, uio->uio_resid); switch(minor(dev)) { case RND_RND: @@ -1027,6 +1029,8 @@ if (n != 0 && ret == 0) ret = uiomove((caddr_t)buf, n, uio); } + + free(buf, M_TEMP); return ret; } @@ -1120,7 +1124,8 @@ struct uio *uio; int flags; { - int ret = 0; + int ret = 0; + u_int32_t *buf; if (minor(dev) == RND_RND || minor(dev) == RND_PRND) return ENXIO; @@ -1128,9 +1133,10 @@ if (uio->uio_resid == 0) return 0; + buf = malloc(4 * POOLWORDS, M_TEMP, M_WAITOK); + while (!ret && uio->uio_resid > 0) { - u_int32_t buf[ POOLWORDS ]; - u_short n = min(sizeof(buf),uio->uio_resid); + u_short n = min(4 * POOLWORDS, uio->uio_resid); ret = uiomove((caddr_t)buf, n, uio); if (!ret) { @@ -1143,6 +1149,7 @@ if (minor(dev) == RND_ARND && !ret) arc4random_initialized = 0; + free(buf, M_TEMP); return ret; }