diff --git a/SOURCES/60-hwrng.rules b/SOURCES/60-hwrng.rules new file mode 100644 index 0000000..dfb7cae --- /dev/null +++ b/SOURCES/60-hwrng.rules @@ -0,0 +1 @@ +SUBSYSTEM=="misc", KERNEL=="hw_random", GROUP="rngd", MODE="0640" diff --git a/SOURCES/jitter-use-proper-state-locking.patch b/SOURCES/jitter-use-proper-state-locking.patch new file mode 100644 index 0000000..7381711 --- /dev/null +++ b/SOURCES/jitter-use-proper-state-locking.patch @@ -0,0 +1,161 @@ +From: Neil Horman +Date: Tue, 10 Dec 2019 09:57:36 -0500 +Subject: Move jitter to use proper state locking/thread signaling + +The existing state communication between the main process and jitter threads was +pretty rickety, leading to lots of potential races. Replace it with proper +thread mutex locking and condition signaling. This will improve our ability to +properly shutdown the jitterentropy threads + +Signed-off-by: Neil Horman +Signed-off-by: Vladis Dronov +--- + rngd_jitter.c | 70 ++++++++++++++++++++++++++++++--------------------- + 1 file changed, 41 insertions(+), 29 deletions(-) + +diff --git a/rngd_jitter.c b/rngd_jitter.c +index d0b12a4..32bac53 100644 +--- a/rngd_jitter.c ++++ b/rngd_jitter.c +@@ -49,7 +49,10 @@ struct thread_data { + struct rand_data *ec; + size_t buf_sz; + int slpmode; +- int active; ++ /* mutex/condition to guard done variable */ ++ pthread_cond_t statecond; ++ pthread_mutex_t statemtx; ++ /* done states -1 : init, 0 : ready, 1 : complete */ + int done; + struct timespec slptm; + sigjmp_buf jmpbuf; +@@ -252,10 +255,8 @@ static void *thread_entropy_task(void *data) + char *tmpbuf; + struct timespec start, end; + int written; +- int first = 1; + /* STARTUP */ + +- me->done = 0; + /* + * Set our timeout value + * -1 means adaptive, i.e. sleep for the last +@@ -279,14 +280,19 @@ static void *thread_entropy_task(void *data) + } + + /* +- * Use setjmp here to allow us to return early from +- * jent_read_entropy, as it can run for a long time ++ * A signal will call siglongjmp and return us here when we exit + */ + if (sigsetjmp(me->jmpbuf, 1)) + goto out_interrupt; + ++ /* Indicate we are ready */ ++ pthread_mutex_lock(&me->statemtx); ++ me->done = 0; ++ pthread_cond_signal(&me->statecond); ++ pthread_mutex_unlock(&me->statemtx); ++ + /* Now go to sleep until there is more work to do */ +- do { ++ for(;;) { + message(LOG_DAEMON|LOG_DEBUG, "JITTER thread on cpu %d wakes up for refill\n", me->core_id); + + /* We are awake because we need to refil the buffer */ +@@ -308,20 +314,18 @@ static void *thread_entropy_task(void *data) + if ((ret < 0) && (errno != EBADF)) + message(LOG_DAEMON|LOG_WARNING, "Error on pipe write: %s\n", strerror(errno)); + message(LOG_DAEMON|LOG_DEBUG, "DONE Writing to pipe with return %ld\n", ret); +- if (first) +- me->active = 1; +- if (!first && !me->active) +- break; +- first = 0; + written += ret; + } + +- } while (me->active); ++ } + + out_interrupt: + free(tmpbuf); + out: ++ pthread_mutex_lock(&me->statemtx); + me->done = 1; ++ pthread_cond_signal(&me->statecond); ++ pthread_mutex_unlock(&me->statemtx); + pthread_exit(NULL); + } + +@@ -434,8 +438,9 @@ int init_jitter_entropy_source(struct rng *ent_src) + core_id++; + tdata[i].core_id = core_id; + tdata[i].pipe_fd = pipefds[1]; +- tdata[i].active = 0; +- tdata[i].done = 0; ++ pthread_cond_init(&tdata[i].statecond, NULL); ++ pthread_mutex_init(&tdata[i].statemtx, NULL); ++ tdata[i].done = -1; + core_id++; + tdata[i].buf_sz = ent_src->rng_options[JITTER_OPT_BUF_SZ].int_val; + tdata[i].ec = jent_entropy_collector_alloc(1, 0); +@@ -448,9 +453,16 @@ int init_jitter_entropy_source(struct rng *ent_src) + + /* Make sure all our threads are doing their jobs */ + for (i=0; i < num_threads; i++) { +- while (tdata[i].active == 0) +- sched_yield(); +- message(LOG_DAEMON|LOG_DEBUG, "CPU Thread %d is ready\n", i); ++ /* wait until the done state transitions from negative to zero or more */ ++ pthread_mutex_lock(&tdata[i].statemtx); ++ if (tdata[i].done < 0) ++ pthread_cond_wait(&tdata[i].statecond, &tdata[i].statemtx); ++ if (tdata[i].done == 1) ++ /* we failed during startup */ ++ message(LOG_DAEMON|LOG_DEBUG, "CPU thread %d failed\n", i); ++ else ++ message(LOG_DAEMON|LOG_DEBUG, "CPU Thread %d is ready\n", i); ++ pthread_mutex_unlock(&tdata[i].statemtx); + } + + flags = fcntl(pipefds[0], F_GETFL, 0); +@@ -492,23 +504,23 @@ void close_jitter_entropy_source(struct rng *ent_src) + char tmpbuf[1024]; + int flags; + +- /* Flag all the threads so they exit */ +- for (i=0; i < num_threads; i++) +- tdata[i].active = 0; +- ++ /* Close the pipes to prevent further writing */ + close(pipefds[1]); + + /* And wait for completion of each thread */ + for (i=0; i < num_threads; i++) { +- message(LOG_DAEMON|LOG_DEBUG, "Checking on done for thread %d\n", i); ++ /* Signal the threads to exit */ + pthread_kill(threads[i], SIGUSR1); +- while (!tdata[i].done) +- if(tdata[i].done) { +- message(LOG_DAEMON|LOG_INFO, "Closing thread %d\n", tdata[i].core_id); +- pthread_join(threads[i], NULL); +- jent_entropy_collector_free(tdata[i].ec); +- } else +- sched_yield(); ++ /* and wait for them to shutdown */ ++ pthread_mutex_lock(&tdata[i].statemtx); ++ if (!tdata[i].done) { ++ message(LOG_DAEMON|LOG_DEBUG, "Checking on done for thread %d\n", i); ++ pthread_cond_wait(&tdata[i].statecond, &tdata[i].statemtx); ++ } ++ pthread_mutex_unlock(&tdata[i].statemtx); ++ message(LOG_DAEMON|LOG_INFO, "Closing thread %d\n", tdata[i].core_id); ++ pthread_join(threads[i], NULL); ++ jent_entropy_collector_free(tdata[i].ec); + } + + close(pipefds[0]); +-- +2.26.3 + diff --git a/SOURCES/rngd-wake-threshold.service b/SOURCES/rngd-wake-threshold.service index f7b3de9..4b45da3 100644 --- a/SOURCES/rngd-wake-threshold.service +++ b/SOURCES/rngd-wake-threshold.service @@ -7,7 +7,7 @@ CapabilityBoundingSet=CAP_SYS_ADMIN AmbientCapabilities=CAP_SYS_ADMIN Type=oneshot RemainAfterExit=yes -ExecStart=/bin/sh -c "PSIZE=$(cat /proc/sys/kernel/random/poolsize); let THRESH=$PSIZE*3/4; echo $THRESH>/proc/sys/kernel/random/write_wakeup_threshold" +ExecStart=/bin/sh -c "PSIZE=$(cat /proc/sys/kernel/random/poolsize); let THRESH=$PSIZE*3/4; echo $THRESH>/proc/sys/kernel/random/write_wakeup_threshold; udevadm trigger --sysname-match=hw_random --settle" [Install] WantedBy=sysinit.target diff --git a/SOURCES/rngd.service b/SOURCES/rngd.service index b42e641..e495d19 100644 --- a/SOURCES/rngd.service +++ b/SOURCES/rngd.service @@ -1,5 +1,6 @@ [Unit] Description=Hardware RNG Entropy Gatherer Daemon +ConditionVirtualization=!container Requires=rngd-wake-threshold.service [Service] @@ -7,7 +8,7 @@ User=rngd Group=rngd CapabilityBoundingSet=CAP_SYS_ADMIN AmbientCapabilities=CAP_SYS_ADMIN -ExecStart=/sbin/rngd -f --fill-watermark=0 +ExecStart=/usr/sbin/rngd -f --fill-watermark=0 TimeoutStartSec=60s [Install] diff --git a/SPECS/rng-tools.spec b/SPECS/rng-tools.spec index c3292cf..c2fdbfb 100644 --- a/SPECS/rng-tools.spec +++ b/SPECS/rng-tools.spec @@ -1,29 +1,28 @@ %global _hardened_build 1 -%global _sbindir /sbin Summary: Random number generator related utilities Name: rng-tools Version: 6.8 -Release: 3%{?dist} +Release: 4%{?dist} Group: System Environment/Base License: GPLv2+ URL: https://github.com/nhorman/rng-tools Source0: https://github.com/nhorman/rng-tools/archive/rng-tools-%{version}.tar.gz Source1: rngd.service -Source2: jitterentropy-library-2.1.2.tar.gz -Source3: rngd-wake-threshold.service +Source2: jitterentropy-library-2.1.2.tar.gz +Source3: rngd-wake-threshold.service +Source4: 60-hwrng.rules Patch0: jitterentropy-remove-install.patch -Patch1: jitterentropy-build-static.patch +Patch1: jitterentropy-build-static.patch Patch2: jitter-setjmp.patch Patch3: Fix-message-log-on-error-in-thread_entropy_task.patch Patch4: Add-reserved-option-value-to-not-change-write_wakeup.patch Patch5: jitter-rdtsc.patch +Patch6: jitter-use-proper-state-locking.patch -# https://sourceforge.net/p/gkernel/patches/111/ - -BuildRequires: gettext -BuildRequires: systemd-units +BuildRequires: gettext +BuildRequires: systemd-units BuildRequires: libgcrypt-devel BuildRequires: autoconf automake BuildRequires: libsysfs-devel libcurl-devel @@ -34,12 +33,11 @@ Requires(postun): systemd-units Requires: libgcrypt libsysfs Requires: openssl libxml2 libcurl - %description Hardware random number generation tools. -%prep -%setup +%prep +%setup tar xvf %{SOURCE2} mv jitterentropy-library-2.1.2 jitterentropy-library %patch0 -p1 @@ -48,6 +46,7 @@ mv jitterentropy-library-2.1.2 jitterentropy-library %patch3 -p1 %patch4 -p1 %patch5 -p1 +%patch6 -p1 %build ./autogen.sh @@ -57,15 +56,17 @@ mv jitterentropy-library-2.1.2 jitterentropy-library %install %make_install -# install systemd unit file +# install systemd unit file and udev rules install -Dt %{buildroot}%{_unitdir} -m0644 %{SOURCE1} install -Dt %{buildroot}%{_unitdir} -m0644 %{SOURCE3} +install -Dt %{buildroot}%{_udevrulesdir} -m0644 %{SOURCE4} %pre getent passwd rngd >/dev/null || useradd -r -M -d %{_localstatedir}/lib/rngd -s /sbin/nologin -c "Random Number Generator Daemon" rngd %post %systemd_post rngd.service rngd-wake-threshold.service +udevadm trigger --sysname-match=hw_random --settle %preun %systemd_preun rngd.service rngd-wake-threshold.service @@ -83,11 +84,18 @@ getent passwd rngd >/dev/null || useradd -r -M -d %{_localstatedir}/lib/rngd -s %{_mandir}/man8/rngd.8.* %attr(0644,root,root) %{_unitdir}/rngd.service %attr(0644,root,root) %{_unitdir}/rngd-wake-threshold.service +%attr(0644,root,root) %{_udevrulesdir}/60-hwrng.rules %changelog +* Mon May 24 2021 Vladis Dronov - 6.8-4 +- There is no need to hardcode _sbindir anymore, also the old value is incorrect +- Update the rngd.service file +- Fix a busyloop bug (bz 1956248) +- Fix /dev/hwrng permission issue (bz 1955522) + * Tue Feb 18 2020 Neil Horman - 6.8-3 - Fix coarse clock time on Azure (bz 180155) - + * Mon Dec 02 2019 Neil Horman - 6.8-2 - Fix erroneous message due to bad errno check (bz 1776710) - Enable addition of 0 value for fill-watermark (bz 1776710) @@ -108,7 +116,7 @@ getent passwd rngd >/dev/null || useradd -r -M -d %{_localstatedir}/lib/rngd -s - default to 1 thread on cpu 0 if getaffinty returns error (bz 1658855) * Thu May 17 2018 Neil Horman 6.2-1 -- Update to latest upstream +- Update to latest upstream - Add CI self tests * Thu Feb 15 2018 Adam Williamson - 6.1-4 @@ -197,4 +205,3 @@ getent passwd rngd >/dev/null || useradd -r -M -d %{_localstatedir}/lib/rngd -s * Wed Mar 24 2010 Jeff Garzik - 2-1 - initial revision (as rng-tools) -