/* -*-c-*-
*
- * $Id: noise.c,v 1.1 1997/08/07 09:45:26 mdw Exp $
+ * $Id: noise.c,v 1.6 1998/06/18 15:08:14 mdw Exp $
*
* Collection of environmental noise
*
- * (c) 1997 EBI
+ * (c) 1998 EBI
*/
/*----- Licensing notice --------------------------------------------------*
/*----- Revision history --------------------------------------------------*
*
* $Log: noise.c,v $
+ * Revision 1.6 1998/06/18 15:08:14 mdw
+ * Improve signal handling when accumulating noise from child processes.
+ *
+ * Revision 1.5 1998/04/23 13:25:23 mdw
+ * Try to reduce the amount of `ps'ing done under OSF/1, because /dev/kmem
+ * seems very slow.
+ *
+ * Revision 1.4 1998/02/20 17:52:32 mdw
+ * Don't use `df' for noise gathering, because it gets upset when NFS
+ * servers aren't responding.
+ *
+ * Revision 1.3 1998/01/12 16:46:19 mdw
+ * Fix copyright date.
+ *
+ * Revision 1.2 1997/08/20 16:19:57 mdw
+ * Fix test for `/dev/random' so that it doesn't close `stdin' if it fails!
+ *
* Revision 1.1 1997/08/07 09:45:26 mdw
* New source file added to acquire environmental noise and add it to the
* randomness pool (see `rand.c').
#include <ctype.h>
#include <errno.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int pfd[2];
pid_t pid;
+#ifdef HAVE_SIGPROCMASK
+ sigset_t ob, nb;
+#endif
+
/* --- Create a pipe for talking to the child --- */
if (pipe(pfd))
return;
+ /* --- Sort out the signal handling for the parent --- *
+ *
+ * Block @SIGCHLD@ while this is going on. Unlike the standard @system@
+ * function, I won't disable @SIGINT@ and @SIGQUIT@. Then, if the user
+ * stops the child with a terminal signal, the parent (i.e., me) gets
+ * killed too, and I don't end up with a tiny dribble of entropy when I'm
+ * expecting quite a lot.
+ */
+
+#ifdef HAVE_SIGPROCMASK
+ sigemptyset(&nb);
+ sigaddset(&nb, SIGCHLD);
+ if (sigprocmask(SIG_BLOCK, &nb, &ob))
+ goto fail_0;
+#endif
+
/* --- Create the child process --- */
pid = fork();
if (pid < 0)
- return;
+ goto fail_1;
if (pid == 0) {
int fd;
0
};
- /* --- Become whoever I'm being run as --- */
+ /* --- Restore signal handling things --- */
+
+#ifdef HAVE_SIGPROCMASK
+ sigprocmask(SIG_SETMASK, &nb, 0);
+#endif
+
+ /* --- Become nobody --- *
+ *
+ * This assumes that @-2@ is a safe user to be. It shouldn't be root,
+ * because it doesn't need to be, and nothing should be done as root
+ * which could be done as someone else. It shouldn't be the user who
+ * invoked me, because that would enable her to kill the children before
+ * I've read enough entropy from them, and that wouldn't be good.
+ */
- setuid(getuid());
+ setuid(-2);
/* --- Close the old standard streams --- */
{
int st;
-
wait(&st);
rand_add(&st, sizeof(st));
rand_add(&pid, sizeof(pid));
}
+
+ /* --- Restore signals --- */
+
+fail_1:
+#ifdef HAVE_SIGPROCMASK
+ sigprocmask(SIG_SETMASK, &ob, 0);
+#endif
+fail_0:;
}
/* --- @noise_acquire@ --- *
unsigned char buff[64];
ssize_t sz;
- if ((fd = open("/dev/random", O_RDONLY) >= 0) &&
+ if ((fd = open("/dev/random", O_RDONLY)) >= 0 &&
(f = fcntl(fd, F_GETFL, 0)) >= 0 &&
fcntl(fd, F_SETFL, f | O_NONBLOCK) >= 0 &&
(sz = read(fd, buff, sizeof(buff))) > 0) {
/* --- Try some commands which ask the outside world some questions --- */
- noise__shell("ps auxww");
- noise__shell("ps -ef");
- noise__shell("df");
- /* @noise__shell("netstat -a");@ -- takes too long */
+ noise__shell("ps auxww || ps -ef; netstat -an");
/* --- Get our resource usage to see if that's at all interesting --- */