Module Name: src Committed By: martin Date: Wed Oct 9 13:25:13 UTC 2024
Modified Files: src/distrib/sets/lists/debug [netbsd-10]: mi module.md.amd64 module.md.i386 src/distrib/sets/lists/man [netbsd-10]: mi src/distrib/sets/lists/modules [netbsd-10]: md.amd64 md.i386 src/distrib/sets/lists/tests [netbsd-10]: mi src/lib/libc/gen [netbsd-10]: Makefile.inc arc4random.3 arc4random.c getentropy.3 src/lib/libc/include [netbsd-10]: reentrant.h src/share/man/man4 [netbsd-10]: Makefile rnd.4 src/sys/arch/amd64/conf [netbsd-10]: ALL GENERIC src/sys/arch/evbarm/conf [netbsd-10]: GENERIC64 src/sys/arch/i386/conf [netbsd-10]: ALL GENERIC src/sys/dev/acpi [netbsd-10]: files.acpi src/sys/kern [netbsd-10]: kern_entropy.c src/sys/modules [netbsd-10]: Makefile src/sys/sys [netbsd-10]: entropy.h src/tests/lib/libc/gen [netbsd-10]: Makefile Added Files: src/lib/libc/include [netbsd-10]: arc4random.h src/share/man/man4 [netbsd-10]: acpivmgenid.4 src/sys/dev/acpi [netbsd-10]: acpi_vmgenid.c src/sys/modules/acpivmgenid [netbsd-10]: Makefile acpivmgenid.ioconf src/tests/lib/libc/gen [netbsd-10]: t_arc4random.c Log Message: Pull up following revision(s) (requested by riastradh in ticket #939): distrib/sets/lists/debug/module.md.amd64: revision 1.18 sys/modules/Makefile: revision 1.292 lib/libc/gen/arc4random.c: revision 1.34 lib/libc/gen/arc4random.c: revision 1.35 lib/libc/gen/arc4random.c: revision 1.36 lib/libc/gen/arc4random.c: revision 1.37 sys/kern/kern_entropy.c: revision 1.70 lib/libc/gen/arc4random.c: revision 1.38 sys/kern/kern_entropy.c: revision 1.71 lib/libc/gen/getentropy.3: revision 1.8 distrib/sets/lists/modules/md.amd64: revision 1.103 share/man/man4/rnd.4: revision 1.42 share/man/man4/rnd.4: revision 1.44 lib/libc/include/arc4random.h: revision 1.1 distrib/sets/lists/man/mi: revision 1.1786 sys/arch/i386/conf/GENERIC: revision 1.1258 sys/modules/acpivmgenid/acpivmgenid.ioconf: revision 1.1 sys/arch/amd64/conf/ALL: revision 1.190 distrib/sets/lists/debug/mi: revision 1.446 sys/arch/i386/conf/ALL: revision 1.521 lib/libc/gen/Makefile.inc: revision 1.219 distrib/sets/lists/debug/module.md.i386: revision 1.12 sys/dev/acpi/acpi_vmgenid.c: revision 1.1 sys/dev/acpi/acpi_vmgenid.c: revision 1.2 lib/libc/include/reentrant.h: revision 1.22 sys/arch/evbarm/conf/GENERIC64: revision 1.219 share/man/man4/Makefile: revision 1.735 distrib/sets/lists/modules/md.i386: revision 1.100 distrib/sets/lists/tests/mi: revision 1.1334 lib/libc/gen/arc4random.3: revision 1.22 sys/dev/acpi/files.acpi: revision 1.133 lib/libc/gen/arc4random.3: revision 1.23 tests/lib/libc/gen/t_arc4random.c: revision 1.1 sys/sys/entropy.h: revision 1.6 sys/arch/amd64/conf/GENERIC: revision 1.614 sys/modules/acpivmgenid/Makefile: revision 1.1 share/man/man4/acpivmgenid.4: revision 1.1 lib/libc/gen/Makefile.inc: revision 1.220 tests/lib/libc/gen/Makefile: revision 1.56 share/man/man4/acpivmgenid.4: revision 1.2 share/man/man4/acpivmgenid.4: revision 1.3 (all via patch) Catch up with all the lint warnings since exit on warning was disabled. Disable 'missing header declaration' and 'nested extern' warnings for now. acpivmgenid(4): New driver for virtual machine generation ID. Added to amd64/ALL and i386/ALL kernel configurations, and made available as a loadable module acpivmgenid.kmod on x86, for now. TBD: Add to all ACPI-supporting GENERIC kernels. PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork entropy(9): Factor out subroutines to reset and gather entropy. `Reset' means we keep the data in the pool, but assume it had zero entropy. `Gather' means we request samples from all on-demand sources and wait for the synchronous ones to complete. No functional change intended, other than to expose new symbols -- just preparation to expose these to acpivmgenid(4), so it can use these when the VM host notifies us that we, the guest, have been cloned. PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork acpivmgenid(4): Reset and gather entropy on VM clone notification. PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork arc4random(3): Reseed if system entropy epoch changes. This can happen, for example, if the system is a VM instance, and the VM is cloned. This incurs the cost of a system call on every arc4random call, which is unfortunate, but 1. we don't currently have a (machine-independent) mechanism for exposing a read-only page to userland shared by the kernel to enable a cheaper access path to the entropy epoch; and 2. the algorithm here -- a simple application of ChaCha -- is likely also a bottleneck and could be much cheaper by (a) using sys/crypto/chacha for machine-dependent vectorized ChaCha code, and (b) filling a buffer (somewhere between a cipher block and a page) in a batch at a time, instead of running ChaCha to generate only 32 bytes at a time. So although this might be a performance hit, the security benefit is worthwhile and we have a clear path to do better than reversing the performance hit later. PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork acpivmgenid(4): Nix BUGS that have been squashed. Reference kern.entropy.epoch for the remaining bug (which is a performance issue, not a security issue). PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork entropy(9): Allow unprivileged reads of sysctl kern.entropy.epoch. Applications need this in order to know when to reseed. (We should also expose it through a page shared read-only with userland for cheaper access, but until we do, let's let applications get at it through sysctl.) PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork arc4random.c: Fix test program. This isn't wired up anywhere, but let's reduce the bitrot. It was helpful in reminding me that kern.entropy.epoch was, for reasons I can't remember, restricted to privileged access. PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork amd64, evbarm, i386: Add acpivmgenid(4) to GENERIC. PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork rnd(4): Document kern.entropy.epoch is unprivileged and elaborate. Cross-reference acpivmgenid(4). PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork arc4random(3): Note that arc4random respects kern.entropy.epoch. PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork Add debug info for new acpivmgenid module arc4random(3): Add automatic tests. This verifies that: - arc4random zeroes its state and reseeds itself on fork - arc4random reseeds itself on entropy consolidation (e.g., VM clone) - arc4random falls back to global state if it can't allocate local state because address space limits cause mmap to fail NOTE: This adds a new libc symbol __arc4random_global, but it's in the reserved namespace and only used by t_arc4random, so no libc minor bump. PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork getentropy(3): Note intent to reseed on VM clone, and caveats. Tidy markup and pacify some mandoc -Tlint complaints while here. PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork Bump dates on man pages recently updated to mention VM clones. PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork arc4random(3): Pacify some of lint's complaints. PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM fork arc4random: suppress another lint warning To generate a diff of this commit: cvs rdiff -u -r1.394.2.10 -r1.394.2.11 src/distrib/sets/lists/debug/mi cvs rdiff -u -r1.12.2.2 -r1.12.2.3 \ src/distrib/sets/lists/debug/module.md.amd64 cvs rdiff -u -r1.7.2.2 -r1.7.2.3 src/distrib/sets/lists/debug/module.md.i386 cvs rdiff -u -r1.1757.2.13 -r1.1757.2.14 src/distrib/sets/lists/man/mi cvs rdiff -u -r1.98.2.2 -r1.98.2.3 src/distrib/sets/lists/modules/md.amd64 cvs rdiff -u -r1.96.2.2 -r1.96.2.3 src/distrib/sets/lists/modules/md.i386 cvs rdiff -u -r1.1238.2.12 -r1.1238.2.13 src/distrib/sets/lists/tests/mi cvs rdiff -u -r1.216.2.1 -r1.216.2.2 src/lib/libc/gen/Makefile.inc cvs rdiff -u -r1.21 -r1.21.24.1 src/lib/libc/gen/arc4random.3 cvs rdiff -u -r1.33 -r1.33.2.1 src/lib/libc/gen/arc4random.c cvs rdiff -u -r1.4.2.2 -r1.4.2.3 src/lib/libc/gen/getentropy.3 cvs rdiff -u -r0 -r1.1.2.2 src/lib/libc/include/arc4random.h cvs rdiff -u -r1.21 -r1.21.2.1 src/lib/libc/include/reentrant.h cvs rdiff -u -r1.730.2.3 -r1.730.2.4 src/share/man/man4/Makefile cvs rdiff -u -r0 -r1.3.2.2 src/share/man/man4/acpivmgenid.4 cvs rdiff -u -r1.40.2.1 -r1.40.2.2 src/share/man/man4/rnd.4 cvs rdiff -u -r1.174.4.4 -r1.174.4.5 src/sys/arch/amd64/conf/ALL cvs rdiff -u -r1.599.4.6 -r1.599.4.7 src/sys/arch/amd64/conf/GENERIC cvs rdiff -u -r1.206.2.4 -r1.206.2.5 src/sys/arch/evbarm/conf/GENERIC64 cvs rdiff -u -r1.503.4.4 -r1.503.4.5 src/sys/arch/i386/conf/ALL cvs rdiff -u -r1.1243.2.4 -r1.1243.2.5 src/sys/arch/i386/conf/GENERIC cvs rdiff -u -r0 -r1.3.2.2 src/sys/dev/acpi/acpi_vmgenid.c cvs rdiff -u -r1.126.4.3 -r1.126.4.4 src/sys/dev/acpi/files.acpi cvs rdiff -u -r1.57.4.5 -r1.57.4.6 src/sys/kern/kern_entropy.c cvs rdiff -u -r1.274.2.6 -r1.274.2.7 src/sys/modules/Makefile cvs rdiff -u -r0 -r1.1.2.2 src/sys/modules/acpivmgenid/Makefile \ src/sys/modules/acpivmgenid/acpivmgenid.ioconf cvs rdiff -u -r1.4.20.1 -r1.4.20.2 src/sys/sys/entropy.h cvs rdiff -u -r1.55 -r1.55.2.1 src/tests/lib/libc/gen/Makefile cvs rdiff -u -r0 -r1.1.2.2 src/tests/lib/libc/gen/t_arc4random.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/debug/mi diff -u src/distrib/sets/lists/debug/mi:1.394.2.10 src/distrib/sets/lists/debug/mi:1.394.2.11 --- src/distrib/sets/lists/debug/mi:1.394.2.10 Wed Oct 2 12:46:13 2024 +++ src/distrib/sets/lists/debug/mi Wed Oct 9 13:25:10 2024 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.394.2.10 2024/10/02 12:46:13 martin Exp $ +# $NetBSD: mi,v 1.394.2.11 2024/10/09 13:25:10 martin Exp $ ./etc/mtree/set.debug comp-sys-root ./usr/lib comp-sys-usr compatdir ./usr/lib/i18n/libBIG5_g.a comp-c-debuglib debuglib,compatfile @@ -2004,6 +2004,7 @@ ./usr/libdata/debug/usr/tests/lib/libc/gen/posix_spawn/t_spawn.debug tests-kernel-tests debug,atf,compattestfile ./usr/libdata/debug/usr/tests/lib/libc/gen/posix_spawn/t_spawnattr.debug tests-kernel-tests debug,atf,compattestfile ./usr/libdata/debug/usr/tests/lib/libc/gen/t_alarm.debug tests-lib-debug debug,atf,compattestfile +./usr/libdata/debug/usr/tests/lib/libc/gen/t_arc4random.debug tests-lib-debug debug,atf,compattestfile ./usr/libdata/debug/usr/tests/lib/libc/gen/t_assert.debug tests-lib-debug debug,atf,compattestfile ./usr/libdata/debug/usr/tests/lib/libc/gen/t_basedirname.debug tests-lib-debug debug,atf,compattestfile ./usr/libdata/debug/usr/tests/lib/libc/gen/t_closefrom.debug tests-lib-debug debug,atf,compattestfile Index: src/distrib/sets/lists/debug/module.md.amd64 diff -u src/distrib/sets/lists/debug/module.md.amd64:1.12.2.2 src/distrib/sets/lists/debug/module.md.amd64:1.12.2.3 --- src/distrib/sets/lists/debug/module.md.amd64:1.12.2.2 Wed Oct 9 13:00:12 2024 +++ src/distrib/sets/lists/debug/module.md.amd64 Wed Oct 9 13:25:10 2024 @@ -1,4 +1,4 @@ -# $NetBSD: module.md.amd64,v 1.12.2.2 2024/10/09 13:00:12 martin Exp $ +# $NetBSD: module.md.amd64,v 1.12.2.3 2024/10/09 13:25:10 martin Exp $ ./usr/libdata/debug/@MODULEDIR@/acpiacad modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpiacad/acpiacad.kmod.debug modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpibat modules-base-kernel kmod,debug @@ -23,6 +23,8 @@ ./usr/libdata/debug/@MODULEDIR@/acpiverbose/acpiverbose.kmod.debug modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpivga modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpivga/acpivga.kmod.debug modules-base-kernel kmod,debug +./usr/libdata/debug/@MODULEDIR@/acpivmgenid modules-base-kernel kmod,debug +./usr/libdata/debug/@MODULEDIR@/acpivmgenid/acpivmgenid.kmod.debug modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpiwdrt modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpiwdrt/acpiwdrt.kmod.debug modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpiwmi modules-base-kernel kmod,debug Index: src/distrib/sets/lists/debug/module.md.i386 diff -u src/distrib/sets/lists/debug/module.md.i386:1.7.2.2 src/distrib/sets/lists/debug/module.md.i386:1.7.2.3 --- src/distrib/sets/lists/debug/module.md.i386:1.7.2.2 Wed Oct 9 13:00:12 2024 +++ src/distrib/sets/lists/debug/module.md.i386 Wed Oct 9 13:25:10 2024 @@ -1,4 +1,4 @@ -# $NetBSD: module.md.i386,v 1.7.2.2 2024/10/09 13:00:12 martin Exp $ +# $NetBSD: module.md.i386,v 1.7.2.3 2024/10/09 13:25:10 martin Exp $ ./usr/libdata/debug/@MODULEDIR@/acpiacad modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpiacad/acpiacad.kmod.debug modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpibat modules-base-kernel kmod,debug @@ -23,6 +23,8 @@ ./usr/libdata/debug/@MODULEDIR@/acpiverbose/acpiverbose.kmod.debug modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpivga modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpivga/acpivga.kmod.debug modules-base-kernel kmod,debug +./usr/libdata/debug/@MODULEDIR@/acpivmgenid modules-base-kernel kmod,debug +./usr/libdata/debug/@MODULEDIR@/acpivmgenid/acpivmgenid.kmod.debug modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpiwdrt modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpiwdrt/acpiwdrt.kmod.debug modules-base-kernel kmod,debug ./usr/libdata/debug/@MODULEDIR@/acpiwmi modules-base-kernel kmod,debug Index: src/distrib/sets/lists/man/mi diff -u src/distrib/sets/lists/man/mi:1.1757.2.13 src/distrib/sets/lists/man/mi:1.1757.2.14 --- src/distrib/sets/lists/man/mi:1.1757.2.13 Wed Oct 9 13:00:12 2024 +++ src/distrib/sets/lists/man/mi Wed Oct 9 13:25:11 2024 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1757.2.13 2024/10/09 13:00:12 martin Exp $ +# $NetBSD: mi,v 1.1757.2.14 2024/10/09 13:25:11 martin Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -775,6 +775,7 @@ ./usr/share/man/cat4/acpismbus.0 man-sys-catman .cat ./usr/share/man/cat4/acpitz.0 man-sys-catman .cat ./usr/share/man/cat4/acpivga.0 man-sys-catman .cat +./usr/share/man/cat4/acpivmgenid.0 man-sys-catman .cat ./usr/share/man/cat4/acpiwdrt.0 man-sys-catman .cat ./usr/share/man/cat4/acpiwmi.0 man-sys-catman .cat ./usr/share/man/cat4/adb.0 man-sys-catman .cat @@ -4228,6 +4229,7 @@ ./usr/share/man/html4/acpismbus.html man-sys-htmlman html ./usr/share/man/html4/acpitz.html man-sys-htmlman html ./usr/share/man/html4/acpivga.html man-sys-htmlman html +./usr/share/man/html4/acpivmgenid.html man-sys-htmlman html ./usr/share/man/html4/acpiwdrt.html man-sys-htmlman html ./usr/share/man/html4/acpiwmi.html man-sys-htmlman html ./usr/share/man/html4/adb.html man-sys-htmlman html @@ -7375,6 +7377,7 @@ ./usr/share/man/man4/acpismbus.4 man-sys-man .man ./usr/share/man/man4/acpitz.4 man-sys-man .man ./usr/share/man/man4/acpivga.4 man-sys-man .man +./usr/share/man/man4/acpivmgenid.4 man-sys-man .man ./usr/share/man/man4/acpiwdrt.4 man-sys-man .man ./usr/share/man/man4/acpiwmi.4 man-sys-man .man ./usr/share/man/man4/adb.4 man-sys-man .man Index: src/distrib/sets/lists/modules/md.amd64 diff -u src/distrib/sets/lists/modules/md.amd64:1.98.2.2 src/distrib/sets/lists/modules/md.amd64:1.98.2.3 --- src/distrib/sets/lists/modules/md.amd64:1.98.2.2 Wed Oct 9 13:00:12 2024 +++ src/distrib/sets/lists/modules/md.amd64 Wed Oct 9 13:25:10 2024 @@ -1,4 +1,4 @@ -# $NetBSD: md.amd64,v 1.98.2.2 2024/10/09 13:00:12 martin Exp $ +# $NetBSD: md.amd64,v 1.98.2.3 2024/10/09 13:25:10 martin Exp $ # ./@MODULEDIR@/acpiacad modules-base-kernel kmod ./@MODULEDIR@/acpiacad/acpiacad.kmod modules-base-kernel kmod @@ -24,6 +24,8 @@ ./@MODULEDIR@/acpiverbose/acpiverbose.kmod modules-base-kernel kmod ./@MODULEDIR@/acpivga modules-base-kernel kmod ./@MODULEDIR@/acpivga/acpivga.kmod modules-base-kernel kmod +./@MODULEDIR@/acpivmgenid modules-base-kernel kmod +./@MODULEDIR@/acpivmgenid/acpivmgenid.kmod modules-base-kernel kmod ./@MODULEDIR@/acpiwdrt modules-base-kernel kmod ./@MODULEDIR@/acpiwdrt/acpiwdrt.kmod modules-base-kernel kmod ./@MODULEDIR@/acpiwmi modules-base-kernel kmod Index: src/distrib/sets/lists/modules/md.i386 diff -u src/distrib/sets/lists/modules/md.i386:1.96.2.2 src/distrib/sets/lists/modules/md.i386:1.96.2.3 --- src/distrib/sets/lists/modules/md.i386:1.96.2.2 Wed Oct 9 13:00:12 2024 +++ src/distrib/sets/lists/modules/md.i386 Wed Oct 9 13:25:10 2024 @@ -1,4 +1,4 @@ -# $NetBSD: md.i386,v 1.96.2.2 2024/10/09 13:00:12 martin Exp $ +# $NetBSD: md.i386,v 1.96.2.3 2024/10/09 13:25:10 martin Exp $ # ./@MODULEDIR@/acpiacad modules-base-kernel kmod ./@MODULEDIR@/acpiacad/acpiacad.kmod modules-base-kernel kmod @@ -24,6 +24,8 @@ ./@MODULEDIR@/acpiverbose/acpiverbose.kmod modules-base-kernel kmod ./@MODULEDIR@/acpivga modules-base-kernel kmod ./@MODULEDIR@/acpivga/acpivga.kmod modules-base-kernel kmod +./@MODULEDIR@/acpivmgenid modules-base-kernel kmod +./@MODULEDIR@/acpivmgenid/acpivmgenid.kmod modules-base-kernel kmod ./@MODULEDIR@/acpiwdrt modules-base-kernel kmod ./@MODULEDIR@/acpiwdrt/acpiwdrt.kmod modules-base-kernel kmod ./@MODULEDIR@/acpiwmi modules-base-kernel kmod Index: src/distrib/sets/lists/tests/mi diff -u src/distrib/sets/lists/tests/mi:1.1238.2.12 src/distrib/sets/lists/tests/mi:1.1238.2.13 --- src/distrib/sets/lists/tests/mi:1.1238.2.12 Wed Oct 2 12:46:13 2024 +++ src/distrib/sets/lists/tests/mi Wed Oct 9 13:25:12 2024 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1238.2.12 2024/10/02 12:46:13 martin Exp $ +# $NetBSD: mi,v 1.1238.2.13 2024/10/09 13:25:12 martin Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -2942,6 +2942,7 @@ ./usr/tests/lib/libc/gen/posix_spawn/t_spawn tests-kernel-tests compattestfile,atf ./usr/tests/lib/libc/gen/posix_spawn/t_spawnattr tests-kernel-tests compattestfile,atf ./usr/tests/lib/libc/gen/t_alarm tests-lib-tests compattestfile,atf +./usr/tests/lib/libc/gen/t_arc4random tests-lib-tests compattestfile,atf ./usr/tests/lib/libc/gen/t_assert tests-lib-tests compattestfile,atf ./usr/tests/lib/libc/gen/t_basedirname tests-lib-tests compattestfile,atf ./usr/tests/lib/libc/gen/t_closefrom tests-lib-tests compattestfile,atf Index: src/lib/libc/gen/Makefile.inc diff -u src/lib/libc/gen/Makefile.inc:1.216.2.1 src/lib/libc/gen/Makefile.inc:1.216.2.2 --- src/lib/libc/gen/Makefile.inc:1.216.2.1 Tue Oct 8 11:16:17 2024 +++ src/lib/libc/gen/Makefile.inc Wed Oct 9 13:25:10 2024 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.inc,v 1.216.2.1 2024/10/08 11:16:17 martin Exp $ +# $NetBSD: Makefile.inc,v 1.216.2.2 2024/10/09 13:25:10 martin Exp $ # from: @(#)Makefile.inc 8.6 (Berkeley) 5/4/95 # gen sources @@ -39,6 +39,9 @@ SRCS+= alarm.c alphasort.c arc4random.c warnx.c warnc.c wordexp.c xsyslog.c \ vwarn.c vwarnx.c vwarnc.c verr.c verrx.c verrc.c +LINTFLAGS.arc4random.c+=-Ac11 # stdatomic.h +LINTFLAGS.arc4random.c+=-X 129 # expression has null effect (in atomic macros) + # uses alloca COPTS.execvp.c = -Wno-stack-protector COPTS.execl.c = -Wno-stack-protector Index: src/lib/libc/gen/arc4random.3 diff -u src/lib/libc/gen/arc4random.3:1.21 src/lib/libc/gen/arc4random.3:1.21.24.1 --- src/lib/libc/gen/arc4random.3:1.21 Fri Jul 15 21:19:19 2016 +++ src/lib/libc/gen/arc4random.3 Wed Oct 9 13:25:10 2024 @@ -1,4 +1,4 @@ -.\" $NetBSD: arc4random.3,v 1.21 2016/07/15 21:19:19 wiz Exp $ +.\" $NetBSD: arc4random.3,v 1.21.24.1 2024/10/09 13:25:10 martin Exp $ .\" .\" Copyright (c) 2014 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd November 16, 2014 +.Dd August 27, 2024 .Dt ARC4RANDOM 3 .Os .Sh NAME @@ -233,6 +233,15 @@ and .Fn arc4random_addrandom may abort the process in the highly unlikely event that the operating system fails to provide entropy. +.Pp +If +.Nm +detects that the sysctl variable +.Li kern.entropy.epoch +.Pq see Xr rnd 4 +has changed since its last output, it reseeds itself with additional +data from the system entropy pool again before generating its next +output. .Sh SEE ALSO .Xr rand 3 , .Xr random 3 , @@ -252,7 +261,7 @@ for testing purposes. .Pp The name .Sq arc4random -was chosen for hysterical raisins -- it was originally implemented +was chosen for hysterical raisins \(em it was originally implemented using the RC4 stream cipher, which has been known since shortly after it was published in 1994 to have observable biases in the output, and is now known to be broken badly enough to admit practical attacks in Index: src/lib/libc/gen/arc4random.c diff -u src/lib/libc/gen/arc4random.c:1.33 src/lib/libc/gen/arc4random.c:1.33.2.1 --- src/lib/libc/gen/arc4random.c:1.33 Tue Apr 19 20:32:15 2022 +++ src/lib/libc/gen/arc4random.c Wed Oct 9 13:25:10 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: arc4random.c,v 1.33 2022/04/19 20:32:15 rillig Exp $ */ +/* $NetBSD: arc4random.c,v 1.33.2.1 2024/10/09 13:25:10 martin Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -52,7 +52,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: arc4random.c,v 1.33 2022/04/19 20:32:15 rillig Exp $"); +__RCSID("$NetBSD: arc4random.c,v 1.33.2.1 2024/10/09 13:25:10 martin Exp $"); #include "namespace.h" #include "reentrant.h" @@ -65,12 +65,16 @@ __RCSID("$NetBSD: arc4random.c,v 1.33 20 #include <assert.h> #include <sha2.h> +#include <stdatomic.h> #include <stdbool.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <unistd.h> +#include "arc4random.h" +#include "reentrant.h" + #ifdef __weak_alias __weak_alias(arc4random,_arc4random) __weak_alias(arc4random_addrandom,_arc4random_addrandom) @@ -125,7 +129,7 @@ rotate(uint32_t u, unsigned c) (c) += (d); (b) ^= (c); (b) = rotate((b), 7); \ } while (0) -const uint8_t crypto_core_constant32[16] = "expand 32-byte k"; +static const uint8_t crypto_core_constant32[16] = "expand 32-byte k"; static void crypto_core(uint8_t *out, const uint8_t *in, const uint8_t *k, @@ -304,9 +308,7 @@ crypto_core_selftest(void) #define crypto_prng_MAXOUTPUTBYTES \ (crypto_core_OUTPUTBYTES - crypto_prng_SEEDBYTES) -struct crypto_prng { - uint8_t state[crypto_prng_SEEDBYTES]; -}; +__CTASSERT(sizeof(struct crypto_prng) == crypto_prng_SEEDBYTES); static void crypto_prng_seed(struct crypto_prng *prng, const void *seed) @@ -398,12 +400,63 @@ crypto_onetimestream(const void *seed, v (void)explicit_memset(block, 0, sizeof block); } -/* arc4random state: per-thread, per-process (zeroed in child on fork) */ +/* + * entropy_epoch() + * + * Return the current entropy epoch, from the sysctl node + * kern.entropy.epoch. + * + * The entropy epoch is never zero. Initially, or on error, it is + * (unsigned)-1. It may wrap around but it skips (unsigned)-1 and + * 0 when it does. Changes happen less than once per second, so + * wraparound will only affect systems after 136 years of uptime. + * + * XXX This should get it from a page shared read-only by kernel + * with userland, but until we implement such a mechanism, this + * sysctl -- incurring the cost of a syscall -- will have to + * serve. + */ +static unsigned +entropy_epoch(void) +{ + static atomic_int mib0[3]; + static atomic_bool initialized = false; + int mib[3]; + unsigned epoch = (unsigned)-1; + size_t epochlen = sizeof(epoch); -struct arc4random_prng { - struct crypto_prng arc4_prng; - bool arc4_seeded; -}; + /* + * Resolve kern.entropy.epoch if we haven't already. Cache it + * for the next caller. Initialization is idempotent, so it's + * OK if two threads do it at once. + */ + if (atomic_load_explicit(&initialized, memory_order_acquire)) { + mib[0] = atomic_load_explicit(&mib0[0], memory_order_relaxed); + mib[1] = atomic_load_explicit(&mib0[1], memory_order_relaxed); + mib[2] = atomic_load_explicit(&mib0[2], memory_order_relaxed); + } else { + size_t nmib = __arraycount(mib); + + if (sysctlnametomib("kern.entropy.epoch", mib, &nmib) == -1) + return (unsigned)-1; + if (nmib != __arraycount(mib)) + return (unsigned)-1; + atomic_store_explicit(&mib0[0], mib[0], memory_order_relaxed); + atomic_store_explicit(&mib0[1], mib[1], memory_order_relaxed); + atomic_store_explicit(&mib0[2], mib[2], memory_order_relaxed); + atomic_store_explicit(&initialized, true, + memory_order_release); + } + + if (sysctl(mib, __arraycount(mib), &epoch, &epochlen, NULL, 0) == -1) + return (unsigned)-1; + if (epochlen != sizeof(epoch)) + return (unsigned)-1; + + return epoch; +} + +/* arc4random state: per-thread, per-process (zeroed in child on fork) */ static void arc4random_prng_addrandom(struct arc4random_prng *prng, const void *data, @@ -413,6 +466,7 @@ arc4random_prng_addrandom(struct arc4ran SHA256_CTX ctx; uint8_t buf[crypto_prng_SEEDBYTES]; size_t buflen = sizeof buf; + unsigned epoch = entropy_epoch(); __CTASSERT(sizeof buf == SHA256_DIGEST_LENGTH); @@ -436,7 +490,7 @@ arc4random_prng_addrandom(struct arc4ran /* reseed(SHA256(prng() || sysctl(KERN_ARND) || data)) */ crypto_prng_seed(&prng->arc4_prng, buf); (void)explicit_memset(buf, 0, sizeof buf); - prng->arc4_seeded = true; + prng->arc4_epoch = epoch; } #ifdef _REENTRANT @@ -473,14 +527,7 @@ arc4random_prng_destroy(struct arc4rando /* Library state */ -static struct arc4random_global { -#ifdef _REENTRANT - mutex_t lock; - thread_key_t thread_key; -#endif - struct arc4random_prng prng; - bool initialized; -} arc4random_global = { +struct arc4random_global_state arc4random_global = { #ifdef _REENTRANT .lock = MUTEX_INITIALIZER, #endif @@ -567,7 +614,7 @@ arc4random_prng_get(void) } /* Guarantee the PRNG is seeded. */ - if (__predict_false(!prng->arc4_seeded)) + if (__predict_false(prng->arc4_epoch != entropy_epoch())) arc4random_prng_addrandom(prng, NULL, 0); return prng; @@ -752,8 +799,18 @@ main(int argc __unused, char **argv __un switch (pid) { case -1: err(1, "fork"); - case 0: - _exit(arc4random_prng_get()->arc4_seeded); + case 0: { + /* + * Verify the epoch has been set to zero by fork. + */ + struct arc4random_prng *prng = NULL; +#ifdef _REENTRANT + prng = thr_getspecific(arc4random_global.thread_key); +#endif + if (prng == NULL) + prng = &arc4random_global.prng; + _exit(prng->arc4_epoch != 0); + } default: rpid = waitpid(pid, &status, 0); if (rpid == -1) Index: src/lib/libc/gen/getentropy.3 diff -u src/lib/libc/gen/getentropy.3:1.4.2.2 src/lib/libc/gen/getentropy.3:1.4.2.3 --- src/lib/libc/gen/getentropy.3:1.4.2.2 Wed Oct 9 13:12:40 2024 +++ src/lib/libc/gen/getentropy.3 Wed Oct 9 13:25:10 2024 @@ -1,4 +1,4 @@ -.\" $NetBSD: getentropy.3,v 1.4.2.2 2024/10/09 13:12:40 martin Exp $ $ +.\" $NetBSD: getentropy.3,v 1.4.2.3 2024/10/09 13:25:10 martin Exp $ $ .\" .\" Copyright (c) 2020 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd February 28, 2023 +.Dd August 28, 2024 .Dt GETENTROPY 3 .Os .Sh NAME @@ -41,9 +41,8 @@ .Fn getentropy "void *buf" "size_t buflen" .In limits.h .Pp -.Li #define GETENTROPY_MAX 256 +.Li #define GETENTROPY_MAX 256 .Sh DESCRIPTION -.Pp The .Nm function fills @@ -99,6 +98,21 @@ However, the interface alone can make no security guarantees without a physical system configuration that includes random number generation hardware or secret seed material from such hardware on another machine. +.Pp +.Nx +attempts to reseed the system entropy pool when it has detected the +system has been cloned as a guest in a virtual machine, so that +subsequent calls to +.Nm +in the clones yield independent outputs. +However, this relies on the virtual machine host to notify the guest, +e.g. through the +.Xr acpivmgenid 4 +device, and even so there is an unavoidable small window of time +between when the virtual machine is actually cloned and when the system +is reseeded during which +.Nm +may yield identical outputs in the clones. .Sh SEE ALSO .Xr arc4random 3 , .Xr rnd 4 , Index: src/lib/libc/include/reentrant.h diff -u src/lib/libc/include/reentrant.h:1.21 src/lib/libc/include/reentrant.h:1.21.2.1 --- src/lib/libc/include/reentrant.h:1.21 Wed Dec 8 20:11:54 2021 +++ src/lib/libc/include/reentrant.h Wed Oct 9 13:25:11 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: reentrant.h,v 1.21 2021/12/08 20:11:54 andvar Exp $ */ +/* $NetBSD: reentrant.h,v 1.21.2.1 2024/10/09 13:25:11 martin Exp $ */ /*- * Copyright (c) 1997, 1998, 2003 The NetBSD Foundation, Inc. @@ -91,6 +91,9 @@ * is. */ +#ifndef _LIBC_REENTRANT_H_ +#define _LIBC_REENTRANT_H_ + #include <pthread.h> #include <signal.h> @@ -326,3 +329,5 @@ thr_once(once_t *once_control, void (*ro #define FUNLOCKFILE(fp) __nothing #endif /* _REENTRANT */ + +#endif /* _LIBC_REENTRANT_H_ */ Index: src/share/man/man4/Makefile diff -u src/share/man/man4/Makefile:1.730.2.3 src/share/man/man4/Makefile:1.730.2.4 --- src/share/man/man4/Makefile:1.730.2.3 Wed Oct 9 13:00:13 2024 +++ src/share/man/man4/Makefile Wed Oct 9 13:25:11 2024 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.730.2.3 2024/10/09 13:00:13 martin Exp $ +# $NetBSD: Makefile,v 1.730.2.4 2024/10/09 13:25:11 martin Exp $ # @(#)Makefile 8.1 (Berkeley) 6/18/93 MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 \ @@ -99,7 +99,8 @@ MAN+= irframe.4 cir.4 irframetty.4 oboe. # ACPI devices MAN+= acpi.4 acpiacad.4 acpibat.4 acpibut.4 acpicpu.4 \ acpidalb.4 acpiec.4 acpifan.4 acpihed.4 acpilid.4 \ - acpipmtr.4 acpismbus.4 acpitz.4 acpivga.4 acpiwdrt.4 acpiwmi.4 + acpipmtr.4 acpismbus.4 acpitz.4 acpivga.4 acpivmgenid.4 \ + acpiwdrt.4 acpiwmi.4 MAN+= apei.4 # Radio devices Index: src/share/man/man4/rnd.4 diff -u src/share/man/man4/rnd.4:1.40.2.1 src/share/man/man4/rnd.4:1.40.2.2 --- src/share/man/man4/rnd.4:1.40.2.1 Fri Aug 11 14:35:24 2023 +++ src/share/man/man4/rnd.4 Wed Oct 9 13:25:11 2024 @@ -1,4 +1,4 @@ -.\" $NetBSD: rnd.4,v 1.40.2.1 2023/08/11 14:35:24 martin Exp $ +.\" $NetBSD: rnd.4,v 1.40.2.2 2024/10/09 13:25:11 martin Exp $ .\" .\" Copyright (c) 2014-2020 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd August 7, 2023 +.Dd August 27, 2024 .Dt RND 4 .Os .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" @@ -457,18 +457,37 @@ Number of bits of entropy pending in per This is the amount of entropy that will be contributed to the global pool at the next consolidation, such as from triggering .Dv kern.entropy.consolidate . +.El +.Pp +The following read-only +.Xr sysctl 8 +variables provide information to any users, privileged or unprivileged: +.Bl -tag -width abcd .It Dv kern.entropy.epoch Pq Vt unsigned int -Number of times system has reached full entropy, or entropy has been -consolidated with -.Dv kern.entropy.consolidate , -as an unsigned 32-bit integer. -Consulted inside the kernel by subsystems such as -.Xr cprng 9 +An integer that changes whenever the system determines applications +should reseed from the system entropy pool. +This can happen for various reasons: +.Bl -dash -compact +.It +The system has reached full entropy for the first time. +.It +A virtual machine clone has been detected +.Pq e.g., by Xr acpivmgenid 4 . +.It +An operator has set +.Li kern.entropy.consolidate . +.El +.Pp +Consulted by +.Xr arc4random 3 , +and inside the kernel by subsystems such as +.Xr cprng 9 , to decide whether to reseed. +.Pp Initially set to 2^32 \- 1 .Pq i.e., Li "(unsigned)\-1" -meaning the system has never reached full entropy and the entropy has -never been consolidated; never again set to 2^32 \- 1. +meaning the system has never reached full entropy; never again set to +2^32 \- 1. Never zero, so applications can initialize a cache of the epoch to zero to ensure they reseed the next time they check whether it is different from the stored epoch. @@ -625,6 +644,7 @@ The system has full entropy for the firs .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .Sh SEE ALSO .Xr arc4random 3 , +.Xr acpivmgenid 4 , .Xr entropy 7 , .Xr rndctl 8 , .Xr cprng 9 , Index: src/sys/arch/amd64/conf/ALL diff -u src/sys/arch/amd64/conf/ALL:1.174.4.4 src/sys/arch/amd64/conf/ALL:1.174.4.5 --- src/sys/arch/amd64/conf/ALL:1.174.4.4 Wed Oct 9 13:00:13 2024 +++ src/sys/arch/amd64/conf/ALL Wed Oct 9 13:25:12 2024 @@ -1,4 +1,4 @@ -# $NetBSD: ALL,v 1.174.4.4 2024/10/09 13:00:13 martin Exp $ +# $NetBSD: ALL,v 1.174.4.5 2024/10/09 13:25:12 martin Exp $ # From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp # # ALL machine description file @@ -17,7 +17,7 @@ include "arch/amd64/conf/std.amd64" options INCLUDE_CONFIG_FILE # embed config file in kernel binary -#ident "ALL-$Revision: 1.174.4.4 $" +#ident "ALL-$Revision: 1.174.4.5 $" maxusers 64 # estimated number of users @@ -378,6 +378,7 @@ acpismbus* at acpi? # ACPI SMBus CMI (e acpitz* at acpi? # ACPI Thermal Zone acpivga* at acpi? # ACPI Display Adapter acpiout* at acpivga? # ACPI Display Output Device +acpivmgenid* at acpi? # ACPI Virtual Machine Generation ID acpiwdrt* at acpi? # ACPI Watchdog Resource Table acpiwmi* at acpi? # ACPI WMI Mapper apei* at apeibus? # ACPI Platform Error Interfaces Index: src/sys/arch/amd64/conf/GENERIC diff -u src/sys/arch/amd64/conf/GENERIC:1.599.4.6 src/sys/arch/amd64/conf/GENERIC:1.599.4.7 --- src/sys/arch/amd64/conf/GENERIC:1.599.4.6 Thu Jun 20 11:00:07 2024 +++ src/sys/arch/amd64/conf/GENERIC Wed Oct 9 13:25:12 2024 @@ -1,4 +1,4 @@ -# $NetBSD: GENERIC,v 1.599.4.6 2024/06/20 11:00:07 martin Exp $ +# $NetBSD: GENERIC,v 1.599.4.7 2024/10/09 13:25:12 martin Exp $ # # GENERIC machine description file # @@ -22,7 +22,7 @@ include "arch/amd64/conf/std.amd64" options INCLUDE_CONFIG_FILE # embed config file in kernel binary -#ident "GENERIC-$Revision: 1.599.4.6 $" +#ident "GENERIC-$Revision: 1.599.4.7 $" maxusers 64 # estimated number of users @@ -331,14 +331,17 @@ acpidalb* at acpi? # ACPI Direct Applic acpiec* at acpi? # ACPI Embedded Controller (late) acpiecdt* at acpi? # ACPI Embedded Controller (early) acpifan* at acpi? # ACPI Fan +acpihed* at acpi? # ACPI Hardware Error Device acpilid* at acpi? # ACPI Lid Switch #acpipmtr* at acpi? # ACPI Power Meter (experimental) #acpismbus* at acpi? # ACPI SMBus CMI (experimental) acpitz* at acpi? # ACPI Thermal Zone acpivga* at acpi? # ACPI Display Adapter acpiout* at acpivga? # ACPI Display Output Device +acpivmgenid* at acpi? # ACPI Virtual Machine Generation ID acpiwdrt* at acpi? # ACPI Watchdog Resource Table acpiwmi* at acpi? # ACPI WMI Mapper +apei* at apeibus? # ACPI Platform Error Interfaces # Mainboard devices aibs* at acpi? # ASUSTeK AI Booster hardware monitor Index: src/sys/arch/evbarm/conf/GENERIC64 diff -u src/sys/arch/evbarm/conf/GENERIC64:1.206.2.4 src/sys/arch/evbarm/conf/GENERIC64:1.206.2.5 --- src/sys/arch/evbarm/conf/GENERIC64:1.206.2.4 Mon Jun 17 17:55:34 2024 +++ src/sys/arch/evbarm/conf/GENERIC64 Wed Oct 9 13:25:12 2024 @@ -1,5 +1,5 @@ # -# $NetBSD: GENERIC64,v 1.206.2.4 2024/06/17 17:55:34 martin Exp $ +# $NetBSD: GENERIC64,v 1.206.2.5 2024/10/09 13:25:12 martin Exp $ # # GENERIC ARM (aarch64) kernel # @@ -119,6 +119,7 @@ acpifan* at acpi? acpiged* at acpi? acpilid* at acpi? acpitz* at acpi? +acpivmgenid* at acpi? # CPUs cpus* at fdt? pass 0 Index: src/sys/arch/i386/conf/ALL diff -u src/sys/arch/i386/conf/ALL:1.503.4.4 src/sys/arch/i386/conf/ALL:1.503.4.5 --- src/sys/arch/i386/conf/ALL:1.503.4.4 Wed Oct 9 13:00:13 2024 +++ src/sys/arch/i386/conf/ALL Wed Oct 9 13:25:11 2024 @@ -1,4 +1,4 @@ -# $NetBSD: ALL,v 1.503.4.4 2024/10/09 13:00:13 martin Exp $ +# $NetBSD: ALL,v 1.503.4.5 2024/10/09 13:25:11 martin Exp $ # From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp # # ALL machine description file @@ -17,7 +17,7 @@ include "arch/i386/conf/std.i386" options INCLUDE_CONFIG_FILE # embed config file in kernel binary -#ident "ALL-$Revision: 1.503.4.4 $" +#ident "ALL-$Revision: 1.503.4.5 $" maxusers 64 # estimated number of users @@ -365,6 +365,7 @@ acpismbus* at acpi? # ACPI SMBus CMI (e acpitz* at acpi? # ACPI Thermal Zone acpivga* at acpi? # ACPI Display Adapter acpiout* at acpivga? # ACPI Display Output Device +acpivmgenid* at acpi? # ACPI Virtual Machine Generation ID acpiwdrt* at acpi? # ACPI Watchdog Resource Table acpiwmi* at acpi? # ACPI WMI Mapper apei* at apeibus? # ACPI Platform Error Interfaces Index: src/sys/arch/i386/conf/GENERIC diff -u src/sys/arch/i386/conf/GENERIC:1.1243.2.4 src/sys/arch/i386/conf/GENERIC:1.1243.2.5 --- src/sys/arch/i386/conf/GENERIC:1.1243.2.4 Thu Jun 20 11:00:06 2024 +++ src/sys/arch/i386/conf/GENERIC Wed Oct 9 13:25:11 2024 @@ -1,4 +1,4 @@ -# $NetBSD: GENERIC,v 1.1243.2.4 2024/06/20 11:00:06 martin Exp $ +# $NetBSD: GENERIC,v 1.1243.2.5 2024/10/09 13:25:11 martin Exp $ # # GENERIC machine description file # @@ -22,7 +22,7 @@ include "arch/i386/conf/std.i386" options INCLUDE_CONFIG_FILE # embed config file in kernel binary -#ident "GENERIC-$Revision: 1.1243.2.4 $" +#ident "GENERIC-$Revision: 1.1243.2.5 $" maxusers 64 # estimated number of users @@ -314,14 +314,17 @@ acpidalb* at acpi? # ACPI Direct Applic acpiec* at acpi? # ACPI Embedded Controller (late) acpiecdt* at acpi? # ACPI Embedded Controller (early) acpifan* at acpi? # ACPI Fan +acpihed* at acpi? # ACPI Hardware Error Device acpilid* at acpi? # ACPI Lid Switch #acpipmtr* at acpi? # ACPI Power Meter (experimental) #acpismbus* at acpi? # ACPI SMBus CMI (experimental) acpitz* at acpi? # ACPI Thermal Zone acpivga* at acpi? # ACPI Display Adapter acpiout* at acpivga? # ACPI Display Output Device +acpivmgenid* at acpi? # ACPI Virtual Machine Generation ID acpiwdrt* at acpi? # ACPI Watchdog Resource Table acpiwmi* at acpi? # ACPI WMI Mapper +apei* at apeibus? # ACPI Platform Error Interfaces # Mainboard devices aibs* at acpi? # ASUSTeK AI Booster hardware monitor Index: src/sys/dev/acpi/files.acpi diff -u src/sys/dev/acpi/files.acpi:1.126.4.3 src/sys/dev/acpi/files.acpi:1.126.4.4 --- src/sys/dev/acpi/files.acpi:1.126.4.3 Wed Oct 9 13:00:11 2024 +++ src/sys/dev/acpi/files.acpi Wed Oct 9 13:25:12 2024 @@ -1,4 +1,4 @@ -# $NetBSD: files.acpi,v 1.126.4.3 2024/10/09 13:00:11 martin Exp $ +# $NetBSD: files.acpi,v 1.126.4.4 2024/10/09 13:25:12 martin Exp $ defflag opt_acpi.h ACPIVERBOSE ACPI_DEBUG ACPI_ACTIVATE_DEV ACPI_DSDT_OVERRIDE ACPI_SCANPCI ACPI_BREAKPOINT @@ -116,6 +116,11 @@ device acpicppc: acpipcc attach acpicppc at acpinodebus file dev/acpi/acpi_cppc.c acpicppc +# ACPI Virtual Machine Generation ID +device acpivmgenid +attach acpivmgenid at acpinodebus +file dev/acpi/acpi_vmgenid.c acpivmgenid + # ACPI Platform Error Interface device apei attach apei at apeibus Index: src/sys/kern/kern_entropy.c diff -u src/sys/kern/kern_entropy.c:1.57.4.5 src/sys/kern/kern_entropy.c:1.57.4.6 --- src/sys/kern/kern_entropy.c:1.57.4.5 Wed Oct 9 13:04:16 2024 +++ src/sys/kern/kern_entropy.c Wed Oct 9 13:25:10 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_entropy.c,v 1.57.4.5 2024/10/09 13:04:16 martin Exp $ */ +/* $NetBSD: kern_entropy.c,v 1.57.4.6 2024/10/09 13:25:10 martin Exp $ */ /*- * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -77,7 +77,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_entropy.c,v 1.57.4.5 2024/10/09 13:04:16 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_entropy.c,v 1.57.4.6 2024/10/09 13:25:10 martin Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -400,7 +400,7 @@ entropy_init(void) SYSCTL_DESCR("Number of samples pending on CPUs"), NULL, 0, &E->samplespending, 0, CTL_CREATE, CTL_EOL); sysctl_createv(&entropy_sysctllog, 0, &entropy_sysctlroot, NULL, - CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_PRIVATE, CTLTYPE_INT, + CTLFLAG_PERMANENT|CTLFLAG_READONLY, CTLTYPE_INT, "epoch", SYSCTL_DESCR("Entropy epoch"), NULL, 0, &E->epoch, 0, CTL_CREATE, CTL_EOL); @@ -1426,6 +1426,26 @@ sysctl_entropy_consolidate(SYSCTLFN_ARGS } /* + * entropy_gather() + * + * Trigger gathering entropy from all on-demand sources, and, if + * requested, wait for synchronous sources (but not asynchronous + * sources) to complete, or fail with EINTR if interrupted by a + * signal. + */ +int +entropy_gather(void) +{ + int error; + + mutex_enter(&E->lock); + error = entropy_request(ENTROPY_CAPACITY, ENTROPY_WAIT|ENTROPY_SIG); + mutex_exit(&E->lock); + + return error; +} + +/* * sysctl -w kern.entropy.gather=1 * * Trigger gathering entropy from all on-demand sources, and wait @@ -1443,12 +1463,8 @@ sysctl_entropy_gather(SYSCTLFN_ARGS) error = sysctl_lookup(SYSCTLFN_CALL(&node)); if (error || newp == NULL) return error; - if (arg) { - mutex_enter(&E->lock); - error = entropy_request(ENTROPY_CAPACITY, - ENTROPY_WAIT|ENTROPY_SIG); - mutex_exit(&E->lock); - } + if (arg) + error = entropy_gather(); return error; } @@ -2451,6 +2467,27 @@ entropy_reset_xc(void *arg1 __unused, vo } /* + * entropy_reset() + * + * Assume the entropy pool has been exposed, e.g. because the VM + * has been cloned. Nix all the pending entropy and set the + * needed to maximum. + */ +void +entropy_reset(void) +{ + + xc_broadcast(0, &entropy_reset_xc, NULL, NULL); + mutex_enter(&E->lock); + E->bitspending = 0; + E->samplespending = 0; + atomic_store_relaxed(&E->bitsneeded, MINENTROPYBITS); + atomic_store_relaxed(&E->samplesneeded, MINSAMPLES); + E->consolidate = false; + mutex_exit(&E->lock); +} + +/* * entropy_ioctl(cmd, data) * * Handle various /dev/random ioctl queries. @@ -2728,16 +2765,8 @@ entropy_ioctl(unsigned long cmd, void *d * If we disabled estimation or collection, nix all the * pending entropy and set needed to the maximum. */ - if (reset) { - xc_broadcast(0, &entropy_reset_xc, NULL, NULL); - mutex_enter(&E->lock); - E->bitspending = 0; - E->samplespending = 0; - atomic_store_relaxed(&E->bitsneeded, MINENTROPYBITS); - atomic_store_relaxed(&E->samplesneeded, MINSAMPLES); - E->consolidate = false; - mutex_exit(&E->lock); - } + if (reset) + entropy_reset(); /* * If we changed any of the estimation or collection @@ -2750,12 +2779,8 @@ entropy_ioctl(unsigned long cmd, void *d * we have committed side effects, because this ioctl * command is idempotent, so repeating it is safe. */ - if (request) { - mutex_enter(&E->lock); - error = entropy_request(ENTROPY_CAPACITY, - ENTROPY_WAIT|ENTROPY_SIG); - mutex_exit(&E->lock); - } + if (request) + error = entropy_gather(); break; } case RNDADDDATA: { /* Enter seed into entropy pool. */ Index: src/sys/modules/Makefile diff -u src/sys/modules/Makefile:1.274.2.6 src/sys/modules/Makefile:1.274.2.7 --- src/sys/modules/Makefile:1.274.2.6 Wed Oct 9 13:00:13 2024 +++ src/sys/modules/Makefile Wed Oct 9 13:25:10 2024 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.274.2.6 2024/10/09 13:00:13 martin Exp $ +# $NetBSD: Makefile,v 1.274.2.7 2024/10/09 13:25:10 martin Exp $ .include <bsd.own.mk> @@ -287,6 +287,7 @@ SUBDIR+= acpilid SUBDIR+= acpipmtr SUBDIR+= acpitz SUBDIR+= acpivga +SUBDIR+= acpivmgenid SUBDIR+= acpiwdrt SUBDIR+= acpiwmi SUBDIR+= aibs Index: src/sys/sys/entropy.h diff -u src/sys/sys/entropy.h:1.4.20.1 src/sys/sys/entropy.h:1.4.20.2 --- src/sys/sys/entropy.h:1.4.20.1 Wed Oct 9 13:04:17 2024 +++ src/sys/sys/entropy.h Wed Oct 9 13:25:13 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: entropy.h,v 1.4.20.1 2024/10/09 13:04:17 martin Exp $ */ +/* $NetBSD: entropy.h,v 1.4.20.2 2024/10/09 13:25:13 martin Exp $ */ /*- * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -49,6 +49,8 @@ struct knote; #define ENTROPY_HARDFAIL 0x04 void entropy_bootrequest(void); +void entropy_reset(void); +int entropy_gather(void); void entropy_consolidate(void); int entropy_consolidate_sig(void); unsigned entropy_epoch(void); Index: src/tests/lib/libc/gen/Makefile diff -u src/tests/lib/libc/gen/Makefile:1.55 src/tests/lib/libc/gen/Makefile:1.55.2.1 --- src/tests/lib/libc/gen/Makefile:1.55 Tue May 31 13:42:59 2022 +++ src/tests/lib/libc/gen/Makefile Wed Oct 9 13:25:13 2024 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.55 2022/05/31 13:42:59 riastradh Exp $ +# $NetBSD: Makefile,v 1.55.2.1 2024/10/09 13:25:13 martin Exp $ .include <bsd.own.mk> @@ -8,6 +8,7 @@ TESTS_SUBDIRS+= execve TESTS_SUBDIRS+= posix_spawn TESTS_C+= t_alarm +TESTS_C+= t_arc4random TESTS_C+= t_assert TESTS_C+= t_basedirname TESTS_C+= t_closefrom @@ -44,6 +45,7 @@ TESTS_C+= t_vis COPTS.t_siginfo.c+= -DENABLE_TESTS .endif +CPPFLAGS.t_arc4random.c+=-I${NETBSDSRCDIR}/lib/libc/include CPPFLAGS.t_siginfo.c+=-D__TEST_FENV COPTS.t_fpsetround.c+=${${ACTIVE_CC} == "gcc":? -frounding-math :} @@ -54,6 +56,8 @@ DPADD.t_fpclassify+= ${LIBM} LDADD.t_fpsetround+= -lm DPADD.t_fpsetround+= ${LIBM} +LDADD.t_arc4random+= -lpthread +DPADD.t_arc4random+= ${LIBPTHREAD} LDADD.t_nice+= -lpthread DPADD.t_nice+= ${LIBPTHREAD} LDADD.t_syslog+= -lpthread Added files: Index: src/lib/libc/include/arc4random.h diff -u /dev/null src/lib/libc/include/arc4random.h:1.1.2.2 --- /dev/null Wed Oct 9 13:25:13 2024 +++ src/lib/libc/include/arc4random.h Wed Oct 9 13:25:11 2024 @@ -0,0 +1,60 @@ +/* $NetBSD: arc4random.h,v 1.1.2.2 2024/10/09 13:25:11 martin Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LIBC_GEN_ARC4RANDOM_H_ +#define _LIBC_GEN_ARC4RANDOM_H_ + +#include <stdbool.h> +#include <stdint.h> + +#include "reentrant.h" + +struct crypto_prng { + uint8_t state[32]; +}; + +struct arc4random_prng { + struct crypto_prng arc4_prng; + unsigned arc4_epoch; +}; + +struct arc4random_global_state { + mutex_t lock; + thread_key_t thread_key; + struct arc4random_prng prng; + bool initialized; +}; + +#define arc4random_global __arc4random_global /* libc private symbol */ + +extern struct arc4random_global_state arc4random_global; + +#endif /* _LIBC_GEN_ARC4RANDOM_H_ */ Index: src/share/man/man4/acpivmgenid.4 diff -u /dev/null src/share/man/man4/acpivmgenid.4:1.3.2.2 --- /dev/null Wed Oct 9 13:25:13 2024 +++ src/share/man/man4/acpivmgenid.4 Wed Oct 9 13:25:11 2024 @@ -0,0 +1,108 @@ +.\" $NetBSD: acpivmgenid.4,v 1.3.2.2 2024/10/09 13:25:11 martin Exp $ +.\" +.\" Copyright (c) 2024 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd August 26, 2024 +.Dt ACPIVMGENID 4 +.Os +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.Sh NAME +.Nm acpivmgenid +.Nd ACPI Virtual Machine Generation ID +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.Sh SYNOPSIS +.Cd "acpivmgenid* at acpi?" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.Sh DESCRIPTION +.Nm +provides a generation ID for virtual machines. +.Pp +When starting two otherwise identical virtual machines, whether from +the same clean image or by cloning snapshots or any other mechanism, +the VM host may choose a different generation ID. +Although this generation ID is not secret, it is incorporated into the +.Xr entropy 7 +pool (with a measure of zero entropy) so that the two virtual machines +will produce independent random output. +.Pp +If a live VM is cloned, the VM host may change the generation ID in one +or both of the clones and notify them through the +.Nm +device. +When this happens, +.Nx +will reseed system random number generators, so that output of +.Pa /dev/urandom +and +.Xr getentropy 3 +will be independent in the two clones, and the +.Xr sysctl 7 +variable +.Li kern.entropy.epoch +will advance to notify applications that they should reseed random +number generators from the system entropy pool. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.Sh SYSCTLS +The following +.Xr sysctl 7 +nodes are available: +.Bl -tag -width Li +.It Li "hw.acpivmgenid" Ns Va N Ns Li ".id" +The current 16-byte VM generation ID. +.It Li "hw.acpivmgenid" Ns Va N Ns Li ".paddr" +The physical address of the VM generation ID provided by the host. +.El +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.Sh SEE ALSO +.Xr arc4random 3 , +.Xr getentropy 3 , +.Xr rnd 4 , +.Xr entropy 7 +.Rs +.%T Virtual Machine Generation ID +.%Q Microsoft +.%D 2018-08-01 +.%U http://go.microsoft.com/fwlink/?LinkId=260709 +.Re +.Rs +.%T Virtual Machine Generation ID Device +.%Q The QEMU Project Developers +.%U https://www.qemu.org/docs/master/specs/vmgenid.html +.Re +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.Sh HISTORY +The +.Nm +driver first appeared in +.Nx 11.0 . +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.Sh BUGS +Currently there is no cheaper way to detect VM generation ID changes +than to query sysctl. +(Applications deciding whether to reseed random number generators +should generally query +.Li kern.entropy.epoch , +not +.Li "hw.acpivmgenid" Ns Va N Ns Li ".id" . ) Index: src/sys/dev/acpi/acpi_vmgenid.c diff -u /dev/null src/sys/dev/acpi/acpi_vmgenid.c:1.3.2.2 --- /dev/null Wed Oct 9 13:25:13 2024 +++ src/sys/dev/acpi/acpi_vmgenid.c Wed Oct 9 13:25:12 2024 @@ -0,0 +1,351 @@ +/* $NetBSD: acpi_vmgenid.c,v 1.3.2.2 2024/10/09 13:25:12 martin Exp $ */ + +/*- + * Copyright (c) 2024 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Virtual Machine Generation ID + * + * The VMGENID is an 8-byte cookie shared between a VM host and VM + * guest. Whenever the host clones a VM, it changes the VMGENID + * and sends an ACPI notification to the guest. + * + * References: + * + * `Virtual Machine Generation ID', Microsoft, 2012-08-01. + * http://go.microsoft.com/fwlink/?LinkId=260709 + * + * `Virtual Machine Generation ID Device', The QEMU Project + * Developers. + * https://www.qemu.org/docs/master/specs/vmgenid.html + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: acpi_vmgenid.c,v 1.3.2.2 2024/10/09 13:25:12 martin Exp $"); + +#include <sys/device.h> +#include <sys/entropy.h> +#include <sys/module.h> +#include <sys/rndsource.h> +#include <sys/sysctl.h> + +#include <dev/acpi/acpireg.h> +#include <dev/acpi/acpivar.h> + +#define _COMPONENT ACPI_RESOURCE_COMPONENT +ACPI_MODULE_NAME ("acpi_vmgenid") + +struct acpivmgenid { + uint8_t id[16]; +} __aligned(8); + +struct acpivmgenid_softc { + device_t sc_dev; + struct acpi_devnode *sc_node; + uint64_t sc_paddr; + struct acpivmgenid *sc_vaddr; + struct krndsource sc_rndsource; + struct sysctllog *sc_sysctllog; + const struct sysctlnode *sc_sysctlroot; +}; + +static int acpivmgenid_match(device_t, cfdata_t, void *); +static void acpivmgenid_attach(device_t, device_t, void *); +static int acpivmgenid_detach(device_t, int); +static void acpivmgenid_set(struct acpivmgenid_softc *, const char *); +static void acpivmgenid_notify(ACPI_HANDLE, uint32_t, void *); +static void acpivmgenid_reset(void *); +static int acpivmgenid_sysctl(SYSCTLFN_ARGS); + +static const struct device_compatible_entry compat_data[] = { + { .compat = "VM_Gen_Counter" }, /* from the Microsoft spec */ + { .compat = "VM_GEN_COUNTER" }, /* used by qemu */ + { .compat = "VMGENCTR" }, /* recognized by Linux */ + DEVICE_COMPAT_EOL +}; + +CFATTACH_DECL_NEW(acpivmgenid, sizeof(struct acpivmgenid_softc), + acpivmgenid_match, acpivmgenid_attach, acpivmgenid_detach, NULL); + +static int +acpivmgenid_match(device_t parent, cfdata_t match, void *aux) +{ + const struct acpi_attach_args *const aa = aux; + + return acpi_compatible_match(aa, compat_data); +} + +static void +acpivmgenid_attach(device_t parent, device_t self, void *aux) +{ + struct acpivmgenid_softc *const sc = device_private(self); + const struct acpi_attach_args *const aa = aux; + ACPI_BUFFER addrbuf = { + .Pointer = NULL, + .Length = ACPI_ALLOCATE_BUFFER, + }; + ACPI_OBJECT *addrobj, *addrarr; + ACPI_STATUS rv; + int error; + + aprint_naive(": ACPI VM Generation ID\n"); + aprint_normal(": ACPI VM Generation ID\n"); + + sc->sc_dev = self; + sc->sc_node = aa->aa_node; + + /* + * Get the address from the ADDR object, which is a package of + * two 32-bit integers representing the low and high halves of + * a 64-bit physical address. + */ + rv = AcpiEvaluateObjectTyped(sc->sc_node->ad_handle, "ADDR", NULL, + &addrbuf, ACPI_TYPE_PACKAGE); + if (ACPI_FAILURE(rv)) { + aprint_error_dev(self, "failed to get ADDR: %s\n", + AcpiFormatException(rv)); + goto out; + } + addrobj = addrbuf.Pointer; + if (addrobj->Type != ACPI_TYPE_PACKAGE || + addrobj->Package.Count != 2) { + aprint_error_dev(self, "invalid ADDR\n"); + goto out; + } + addrarr = addrobj->Package.Elements; + if (addrarr[0].Type != ACPI_TYPE_INTEGER || + addrarr[1].Type != ACPI_TYPE_INTEGER || + addrarr[0].Integer.Value > UINT32_MAX || + addrarr[1].Integer.Value > UINT32_MAX) { + aprint_error_dev(self, "invalid ADDR\n"); + goto out; + } + sc->sc_paddr = (ACPI_PHYSICAL_ADDRESS)addrarr[0].Integer.Value; + sc->sc_paddr |= (ACPI_PHYSICAL_ADDRESS)addrarr[1].Integer.Value << 32; + aprint_normal_dev(self, "paddr=0x%"PRIx64"\n", (uint64_t)sc->sc_paddr); + + /* + * Map the physical address into virtual address space. + */ + sc->sc_vaddr = AcpiOsMapMemory(sc->sc_paddr, sizeof(*sc->sc_vaddr)); + if (sc->sc_vaddr == NULL) { + aprint_error_dev(self, "failed to map address\n"); + goto out; + } + + /* + * Register a random source so we can attribute samples. + */ + rnd_attach_source(&sc->sc_rndsource, device_xname(self), + RND_TYPE_UNKNOWN, RND_FLAG_COLLECT_TIME|RND_FLAG_COLLECT_VALUE); + + /* + * Register an ACPI notifier so that we can detect changes. + */ + (void)acpi_register_notify(sc->sc_node, acpivmgenid_notify); + + /* + * Now that we have registered a random source and a notifier, + * read out the first value. + */ + acpivmgenid_set(sc, "initial"); + + /* + * Attach a sysctl tree, rooted at hw.acpivmgenidN. + */ + error = sysctl_createv(&sc->sc_sysctllog, 0, NULL, &sc->sc_sysctlroot, + CTLFLAG_PERMANENT, CTLTYPE_NODE, device_xname(self), + SYSCTL_DESCR("Virtual Machine Generation ID device"), + NULL, 0, NULL, 0, + CTL_HW, CTL_CREATE, CTL_EOL); + if (error) { + aprint_error_dev(self, "failed to create sysctl hw.%s: %d\n", + device_xname(self), error); + goto out; + } + + /* + * hw.acpivmgenidN.id (`struct', 16-byte array) + */ + error = sysctl_createv(&sc->sc_sysctllog, 0, &sc->sc_sysctlroot, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_PRIVATE, CTLTYPE_STRUCT, + "id", SYSCTL_DESCR("Virtual Machine Generation ID"), + &acpivmgenid_sysctl, 0, sc, sizeof(struct acpivmgenid), + CTL_CREATE, CTL_EOL); + if (error) { + aprint_error_dev(self, + "failed to create sysctl hw.%s.id: %d\n", + device_xname(self), error); + goto out; + } + + /* + * hw.acpivmgenidN.paddr (64-bit integer) + */ + __CTASSERT(sizeof(ACPI_PHYSICAL_ADDRESS) == sizeof(quad_t)); + error = sysctl_createv(&sc->sc_sysctllog, 0, &sc->sc_sysctlroot, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_PRIVATE, CTLTYPE_QUAD, + "paddr", SYSCTL_DESCR("Physical address of VM Generation ID"), + NULL, 0, &sc->sc_paddr, sizeof(sc->sc_paddr), + CTL_CREATE, CTL_EOL); + if (error) { + aprint_error_dev(self, + "failed to create sysctl hw.%s.paddr: %d\n", + device_xname(self), error); + goto out; + } + +out: ACPI_FREE(addrbuf.Pointer); +} + +static int +acpivmgenid_detach(device_t self, int flags) +{ + struct acpivmgenid_softc *const sc = device_private(self); + int error; + + error = config_detach_children(self, flags); + if (error) + return error; + + sysctl_teardown(&sc->sc_sysctllog); + acpi_deregister_notify(sc->sc_node); + rnd_detach_source(&sc->sc_rndsource); + if (sc->sc_vaddr) { + AcpiOsUnmapMemory(sc->sc_vaddr, sizeof(*sc->sc_vaddr)); + sc->sc_vaddr = NULL; /* paranoia */ + } + sc->sc_paddr = 0; /* paranoia */ + + return 0; +} + +static void +acpivmgenid_set(struct acpivmgenid_softc *sc, const char *prefix) +{ + struct acpivmgenid vmgenid; + char vmgenidstr[2*__arraycount(vmgenid.id) + 1]; + unsigned i; + + /* + * Grab the current VM generation ID. No obvious way to make + * this atomic, so let's hope if it changes in the middle we'll + * get another notification. + */ + memcpy(&vmgenid, sc->sc_vaddr, sizeof(vmgenid)); + + /* + * Print the VM generation ID to the console for posterity. + */ + for (i = 0; i < __arraycount(vmgenid.id); i++) { + vmgenidstr[2*i] = "0123456789abcdef"[vmgenid.id[i] >> 4]; + vmgenidstr[2*i + 1] = "0123456789abcdef"[vmgenid.id[i] & 0xf]; + } + vmgenidstr[2*sizeof(vmgenid)] = '\0'; + aprint_verbose_dev(sc->sc_dev, "%s: %s\n", prefix, vmgenidstr); + + /* + * Enter the new VM generation ID into the entropy pool. + */ + rnd_add_data(&sc->sc_rndsource, &vmgenid, sizeof(vmgenid), 0); +} + +static void +acpivmgenid_notify(ACPI_HANDLE hdl, uint32_t notify, void *opaque) +{ + const device_t self = opaque; + struct acpivmgenid_softc *const sc = device_private(self); + + if (notify != 0x80) { + aprint_debug_dev(self, "unknown notify 0x%02x\n", notify); + return; + } + + (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, &acpivmgenid_reset, sc); +} + +static void +acpivmgenid_reset(void *cookie) +{ + struct acpivmgenid_softc *const sc = cookie; + + /* + * Reset the system entropy pool's measure of entropy (not the + * data, just the system's assessment of whether it has + * entropy), and gather more entropy from any synchronous + * sources we have available like CPU RNG instructions. We + * can't be interrupted by a signal so ignore return value. + */ + entropy_reset(); + (void)entropy_gather(); + + /* + * Grab the current VM generation ID to put it into the entropy + * pool; then force consolidation so it affects all subsequent + * draws from the entropy pool and the entropy epoch advances. + */ + acpivmgenid_set(sc, "cloned"); + entropy_consolidate(); +} + +static int +acpivmgenid_sysctl(SYSCTLFN_ARGS) +{ + struct sysctlnode node = *rnode; + struct acpivmgenid_softc *const sc = node.sysctl_data; + + node.sysctl_data = sc->sc_vaddr; + return sysctl_lookup(SYSCTLFN_CALL(&node)); +} + +MODULE(MODULE_CLASS_DRIVER, acpivmgenid, NULL); + +#ifdef _MODULE +#include "ioconf.c" +#endif + +static int +acpivmgenid_modcmd(modcmd_t cmd, void *opaque) +{ + int error = 0; + + switch (cmd) { + case MODULE_CMD_INIT: +#ifdef _MODULE + error = config_init_component(cfdriver_ioconf_acpivmgenid, + cfattach_ioconf_acpivmgenid, cfdata_ioconf_acpivmgenid); +#endif + return error; + case MODULE_CMD_FINI: +#ifdef _MODULE + error = config_fini_component(cfdriver_ioconf_acpivmgenid, + cfattach_ioconf_acpivmgenid, cfdata_ioconf_acpivmgenid); +#endif + return error; + default: + return ENOTTY; + } +} Index: src/sys/modules/acpivmgenid/Makefile diff -u /dev/null src/sys/modules/acpivmgenid/Makefile:1.1.2.2 --- /dev/null Wed Oct 9 13:25:13 2024 +++ src/sys/modules/acpivmgenid/Makefile Wed Oct 9 13:25:12 2024 @@ -0,0 +1,11 @@ +# $NetBSD: Makefile,v 1.1.2.2 2024/10/09 13:25:12 martin Exp $ + +.include "../Makefile.inc" + +.PATH: ${S}/dev/acpi + +KMOD= acpivmgenid +IOCONF= acpivmgenid.ioconf +SRCS= acpi_vmgenid.c + +.include <bsd.kmodule.mk> Index: src/sys/modules/acpivmgenid/acpivmgenid.ioconf diff -u /dev/null src/sys/modules/acpivmgenid/acpivmgenid.ioconf:1.1.2.2 --- /dev/null Wed Oct 9 13:25:13 2024 +++ src/sys/modules/acpivmgenid/acpivmgenid.ioconf Wed Oct 9 13:25:12 2024 @@ -0,0 +1,10 @@ +# $NetBSD: acpivmgenid.ioconf,v 1.1.2.2 2024/10/09 13:25:12 martin Exp $ + +ioconf acpivmgenid + +include "conf/files" +include "dev/acpi/files.acpi" + +pseudo-root acpi* + +acpivmgenid* at acpi? Index: src/tests/lib/libc/gen/t_arc4random.c diff -u /dev/null src/tests/lib/libc/gen/t_arc4random.c:1.1.2.2 --- /dev/null Wed Oct 9 13:25:13 2024 +++ src/tests/lib/libc/gen/t_arc4random.c Wed Oct 9 13:25:13 2024 @@ -0,0 +1,467 @@ +/* $NetBSD: t_arc4random.c,v 1.1.2.2 2024/10/09 13:25:13 martin Exp $ */ + +/*- + * Copyright (c) 2024 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define _REENTRANT + +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_arc4random.c,v 1.1.2.2 2024/10/09 13:25:13 martin Exp $"); + +#include <sys/resource.h> +#include <sys/sysctl.h> +#include <sys/wait.h> + +#include <atf-c.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "arc4random.h" +#include "reentrant.h" +#include "h_macros.h" + +/* + * iszero(buf, len) + * + * True if len bytes at buf are all zero, false if any one of them + * is nonzero. + */ +static bool +iszero(const void *buf, size_t len) +{ + const unsigned char *p = buf; + size_t i; + + for (i = 0; i < len; i++) { + if (p[i] != 0) + return false; + } + return true; +} + +/* + * arc4random_prng() + * + * Get a pointer to the current arc4random state, without updating + * any of the state, not even lazy initialization. + */ +static struct arc4random_prng * +arc4random_prng(void) +{ + struct arc4random_prng *prng = NULL; + + /* + * If arc4random has been initialized and there is a thread key + * (i.e., libc was built with _REENTRANT), get the thread-local + * arc4random state if there is one. + */ + if (arc4random_global.initialized) + prng = thr_getspecific(arc4random_global.thread_key); + + /* + * If we couldn't get the thread-local state, get the global + * state instead. + */ + if (prng == NULL) + prng = &arc4random_global.prng; + + return prng; +} + +/* + * arc4random_global_buf(buf, len) + * + * Same as arc4random_buf, but force use of the global state. + * Must happen before any other use of arc4random. + */ +static void +arc4random_global_buf(void *buf, size_t len) +{ + struct rlimit rlim, orlim; + struct arc4random_prng *prng; + + /* + * Save the address space limit. + */ + RL(getrlimit(RLIMIT_AS, &orlim)); + memcpy(&rlim, &orlim, sizeof(rlim)); + + /* + * Get a sample while the address space limit is zero. This + * should try, and fail, to allocate a thread-local arc4random + * state with mmap(2). + */ + rlim.rlim_cur = 0; + RL(setrlimit(RLIMIT_AS, &rlim)); + arc4random_buf(buf, len); + RL(setrlimit(RLIMIT_AS, &orlim)); + + /* + * Restore the address space limit. + */ + RL(setrlimit(RLIMIT_AS, &orlim)); + + /* + * Verify the PRNG is the global one, not the thread-local one, + * and that it was initialized. + */ + prng = arc4random_prng(); + ATF_CHECK_EQ(prng, &arc4random_global.prng); + ATF_CHECK(!iszero(&prng->arc4_prng, sizeof(prng->arc4_prng))); + ATF_CHECK(prng->arc4_epoch != 0); +} + +/* + * arc4random_global_thread(cookie) + * + * Start routine for a thread that just grabs an output from the + * global state. + */ +static void * +arc4random_global_thread(void *cookie) +{ + unsigned char buf[32]; + + arc4random_global_buf(buf, sizeof(buf)); + + return NULL; +} + +ATF_TC(addrandom); +ATF_TC_HEAD(addrandom, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test arc4random_addrandom updates the state"); +} +ATF_TC_BODY(addrandom, tc) +{ + unsigned char buf[32], zero32[32] = {0}; + struct arc4random_prng *prng, copy; + + /* + * Get a sample to start things off. + */ + arc4random_buf(buf, sizeof(buf)); + ATF_CHECK(!iszero(buf, sizeof(buf))); /* Pr[fail] = 1/2^256 */ + + /* + * By this point, the global state must be initialized -- if + * not, the process should have aborted. + */ + ATF_CHECK(arc4random_global.initialized); + + /* + * Get the PRNG, global or local. By this point, the PRNG + * state should be nonzero (with overwhelmingly high + * probability) and the epoch should also be nonzero. + */ + prng = arc4random_prng(); + ATF_CHECK(!iszero(&prng->arc4_prng, sizeof(prng->arc4_prng))); + ATF_CHECK(prng->arc4_epoch != 0); + + /* + * Save a copy and update the state with arc4random_addrandom. + */ + copy = *prng; + arc4random_addrandom(zero32, sizeof(zero32)); + + /* + * The state should have changed. (The epoch may or may not.) + */ + ATF_CHECK(memcmp(&prng->arc4_prng, ©.arc4_prng, + sizeof(copy.arc4_prng)) != 0); + + /* + * Save a copy and update the state with arc4random_stir. + */ + copy = *prng; + arc4random_stir(); + + /* + * The state should have changed. (The epoch may or may not.) + */ + ATF_CHECK(memcmp(&prng->arc4_prng, ©.arc4_prng, + sizeof(copy.arc4_prng)) != 0); +} + +ATF_TC(consolidate); +ATF_TC_HEAD(consolidate, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test consolidating entropy resets the epoch"); +} +ATF_TC_BODY(consolidate, tc) +{ + unsigned char buf[32]; + struct arc4random_prng *local, *global = &arc4random_global.prng; + unsigned localepoch, globalepoch; + const int consolidate = 1; + pthread_t thread; + + /* + * Get a sample from the global state to make sure the global + * state is initialized. Remember the epoch. + */ + arc4random_global_buf(buf, sizeof(buf)); + ATF_CHECK(!iszero(buf, sizeof(buf))); /* Pr[fail] = 1/2^256 */ + ATF_CHECK(!iszero(&global->arc4_prng, sizeof(global->arc4_prng))); + ATF_CHECK((globalepoch = global->arc4_epoch) != 0); + + /* + * Get a sample from the local state too to make sure the local + * state is initialized. Remember the epoch. + */ + arc4random_buf(buf, sizeof(buf)); + ATF_CHECK(!iszero(buf, sizeof(buf))); /* Pr[fail] = 1/2^256 */ + local = arc4random_prng(); + ATF_CHECK(!iszero(&local->arc4_prng, sizeof(local->arc4_prng))); + ATF_CHECK((localepoch = local->arc4_epoch) != 0); + + /* + * Trigger entropy consolidation. + */ + RL(sysctlbyname("kern.entropy.consolidate", /*oldp*/NULL, /*oldlen*/0, + &consolidate, sizeof(consolidate))); + + /* + * Verify the epoch cache isn't changed yet until we ask for + * more data. + */ + ATF_CHECK_EQ_MSG(globalepoch, global->arc4_epoch, + "global epoch was %u, now %u", globalepoch, global->arc4_epoch); + ATF_CHECK_EQ_MSG(localepoch, local->arc4_epoch, + "local epoch was %u, now %u", localepoch, local->arc4_epoch); + + /* + * Request new output and verify the local epoch cache has + * changed. + */ + arc4random_buf(buf, sizeof(buf)); + ATF_CHECK(!iszero(buf, sizeof(buf))); /* Pr[fail] = 1/2^256 */ + ATF_CHECK_MSG(localepoch != local->arc4_epoch, + "local epoch unchanged from %u", localepoch); + + /* + * Create a new thread to grab output from the global state, + * wait for it to complete, and verify the global epoch cache + * has changed. (Now that we have already used the local state + * in this thread, we can't use the global state any more.) + */ + RZ(pthread_create(&thread, NULL, &arc4random_global_thread, NULL)); + RZ(pthread_join(thread, NULL)); + ATF_CHECK_MSG(globalepoch != global->arc4_epoch, + "global epoch unchanged from %u", globalepoch); +} + +ATF_TC(fork); +ATF_TC_HEAD(fork, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test fork zeros the state and gets independent state"); +} +ATF_TC_BODY(fork, tc) +{ + unsigned char buf[32]; + struct arc4random_prng *local, *global = &arc4random_global.prng; + struct arc4random_prng childstate; + int fd[2]; + pid_t child, pid; + ssize_t nread; + int status; + + /* + * Get a sample from the global state to make sure the global + * state is initialized. + */ + arc4random_global_buf(buf, sizeof(buf)); + ATF_CHECK(!iszero(buf, sizeof(buf))); /* Pr[fail] = 1/2^256 */ + ATF_CHECK(!iszero(&global->arc4_prng, sizeof(global->arc4_prng))); + ATF_CHECK(global->arc4_epoch != 0); + + /* + * Get a sample from the local state too to make sure the local + * state is initialized. + */ + arc4random_buf(buf, sizeof(buf)); + ATF_CHECK(!iszero(buf, sizeof(buf))); /* Pr[fail] = 1/2^256 */ + local = arc4random_prng(); + ATF_CHECK(!iszero(&local->arc4_prng, sizeof(local->arc4_prng))); + ATF_CHECK(local->arc4_epoch != 0); + + /* + * Create a pipe to transfer the state from child to parent. + */ + RL(pipe(fd)); + + /* + * Fork a child. + */ + RL(child = fork()); + if (child == 0) { + status = 0; + + /* + * Verify the states have been zero'd on fork. + */ + if (!iszero(local, sizeof(*local))) { + fprintf(stderr, "failed to zero local state\n"); + status = 1; + } + if (!iszero(global, sizeof(*global))) { + fprintf(stderr, "failed to zero global state\n"); + status = 1; + } + + /* + * Verify we generate nonzero output. + */ + arc4random_buf(buf, sizeof(buf)); + if (iszero(buf, sizeof(buf))) { + fprintf(stderr, "failed to generate nonzero output\n"); + status = 1; + } + + /* + * Share the state to compare with parent. + */ + if ((size_t)write(fd[1], local, sizeof(*local)) != + sizeof(*local)) { + fprintf(stderr, "failed to share local state\n"); + status = 1; + } + _exit(status); + } + + /* + * Verify the global state has been zeroed as expected. (This + * way it is never available to the child, even shortly after + * the fork syscall returns before the atfork handler is + * called.) + */ + ATF_CHECK(iszero(global, sizeof(*global))); + + /* + * Read the state from the child. + */ + RL(nread = read(fd[0], &childstate, sizeof(childstate))); + ATF_CHECK_EQ_MSG(nread, sizeof(childstate), + "nread=%zu sizeof(childstate)=%zu", nread, sizeof(childstate)); + + /* + * Verify the child state is distinct. (The global state has + * been zero'd so it's OK it if coincides.) Check again after + * we grab another output. + */ + ATF_CHECK(memcmp(local, &childstate, sizeof(*local)) != 0); + arc4random_buf(buf, sizeof(buf)); + ATF_CHECK(!iszero(buf, sizeof(buf))); /* Pr[fail] = 1/2^256 */ + ATF_CHECK(memcmp(local, &childstate, sizeof(*local)) != 0); + + /* + * Wait for the child to complete and verify it passed. + */ + RL(pid = waitpid(child, &status, 0)); + ATF_CHECK_EQ_MSG(status, 0, "child exited with nonzero status=%d", + status); +} + +ATF_TC(global); +ATF_TC_HEAD(global, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test the global state is used when address space limit is hit"); +} +ATF_TC_BODY(global, tc) +{ + unsigned char buf[32], buf1[32]; + + /* + * Get a sample from the global state (and verify it was using + * the global state). + */ + arc4random_global_buf(buf, sizeof(buf)); + + /* + * Verify we got a sample. + */ + ATF_CHECK(!iszero(buf, sizeof(buf))); /* Pr[fail] = 1/2^256 */ + + /* + * Get a sample from whatever state and make sure it wasn't + * repeated, which happens only with probability 1/2^256. + */ + arc4random_buf(buf1, sizeof(buf1)); + ATF_CHECK(!iszero(buf1, sizeof(buf1))); /* Pr[fail] = 1/2^256 */ + ATF_CHECK(memcmp(buf, buf1, sizeof(buf)) != 0); +} + +ATF_TC(local); +ATF_TC_HEAD(local, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test arc4random uses thread-local state"); + /* XXX skip if libc was built without _REENTRANT */ +} +ATF_TC_BODY(local, tc) +{ + unsigned char buf[32], buf1[32]; + struct arc4random_prng *prng; + + /* + * Get a sample to start things off. + */ + arc4random_buf(buf, sizeof(buf)); + ATF_CHECK(!iszero(buf, sizeof(buf))); /* Pr[fail] = 1/2^256 */ + + /* + * Verify the arc4random state is _not_ the global state. + */ + prng = arc4random_prng(); + ATF_CHECK(prng != &arc4random_global.prng); + ATF_CHECK(!iszero(&prng->arc4_prng, sizeof(prng->arc4_prng))); + ATF_CHECK(prng->arc4_epoch != 0); + + /* + * Get another sample and make sure it wasn't repeated, which + * happens only with probability 1/2^256. + */ + arc4random_buf(buf1, sizeof(buf1)); + ATF_CHECK(!iszero(buf1, sizeof(buf1))); /* Pr[fail] = 1/2^256 */ + ATF_CHECK(memcmp(buf, buf1, sizeof(buf)) != 0); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, addrandom); + ATF_TP_ADD_TC(tp, consolidate); + ATF_TP_ADD_TC(tp, fork); + ATF_TP_ADD_TC(tp, global); + ATF_TP_ADD_TC(tp, local); + + return atf_no_error(); +}