diff options
author | Jeff Garzik <jeff@garzik.org> | 2012-07-17 20:19:24 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2012-07-17 20:19:24 -0400 |
commit | c192b4cf8bb8715dd4c5e4058f5638fc5c4a81d1 (patch) | |
tree | 49425c96020ee70a0cf2f14e934b979ca5e721c2 | |
parent | e42da63c90b4221b7d427566aa05b5d330890e0a (diff) | |
download | rng-tools-c192b4cf8bb8715dd4c5e4058f5638fc5c4a81d1.tar.gz |
Create PID file at startup, in daemon mode
Code imported from Project Hail
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | rngd.8.in | 5 | ||||
-rw-r--r-- | rngd.c | 36 | ||||
-rw-r--r-- | rngd.h | 2 | ||||
-rw-r--r-- | util.c | 104 |
5 files changed, 146 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am index d0cec2d..6822181 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,7 +10,7 @@ man_MANS = rngd.8 rngtest.1 noinst_LIBRARIES = librngd.a rngd_SOURCES = rngd.h rngd.c rngd_entsource.h rngd_entsource.c \ - rngd_linux.h rngd_linux.c + rngd_linux.h rngd_linux.c util.c rngd_LDADD = librngd.a rngtest_SOURCES = exits.h stats.h stats.c rngtest.c @@ -10,6 +10,7 @@ rngd \- Check and feed random data from hardware device to kernel random device [\fB\-b\fR, \fB\-\-background\fR] [\fB\-f\fR, \fB\-\-foreground\fR] [\fB\-o\fR, \fB\-\-random-device=\fIfile\fR] +[\fB\-p\fR, \fB\-\-pid-file=\fIfile\fR] [\fB\-r\fR, \fB\-\-rng-device=\fIfile\fR] [\fB\-s\fR, \fB\-\-random-step=\fInnn\fR] [\fB\-W\fR, \fB\-\-fill-watermark=\fInnn\fR] @@ -48,6 +49,10 @@ Become a daemon (default) \fB\-f\fR, \fB\-\-foreground\fR Do not fork and become a daemon .TP +\fB\-p\fI file\fR, \fB\-\-pid-file=\fIfile\fR +File used for recording daemon PID, and multiple exclusion +(default: /var/run/rngd.pid) +.TP \fB\-o\fI file\fR, \fB\-\-random-device=\fIfile\fR Kernel device used for random number output (default: /dev/random) @@ -45,6 +45,7 @@ #include <string.h> #include <argp.h> #include <syslog.h> +#include <signal.h> #include "rngd.h" #include "fips.h" @@ -59,6 +60,8 @@ /* Background/daemon mode */ int am_daemon; /* Nonzero if we went daemon */ +bool server_running = true; /* set to false, to stop daemon */ + /* Command line arguments and processing */ const char *argp_program_version = "rngd " VERSION "\n" @@ -83,6 +86,9 @@ static struct argp_option options[] = { { "rng-device", 'r', "file", 0, "Kernel device used for random number input (default: /dev/hw_random)" }, + { "pid-file", 'p', "file", 0, + "File used for recording daemon PID, and multiple exclusion (default: /var/run/rngd.pid)" }, + { "random-step", 's', "nnn", 0, "Number of bytes written to random-device at a time (default: 64)" }, @@ -103,6 +109,7 @@ static struct argp_option options[] = { static struct arguments default_arguments = { .random_name = "/dev/random", + .pid_file = "/var/run/rngd.pid", .poll_timeout = 60, .random_step = 64, .fill_watermark = 2048, @@ -136,6 +143,9 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) case 'o': arguments->random_name = arg; break; + case 'p': + arguments->pid_file = arg; + break; case 'r': rng_default.rng_name = arg; break; @@ -227,6 +237,9 @@ static void do_loop(int random_step, double poll_timeout) { int rc; + if (!server_running) + return; + if (iter->disabled) continue; /* failed, no work */ @@ -260,10 +273,16 @@ static void do_loop(int random_step, double poll_timeout) "No entropy sources working, exiting rngd\n"); } +static void term_signal(int signo) +{ + server_running = false; +} + int main(int argc, char **argv) { int rc_rng = 0; int rc_tpm = 0; + int pid_fd = -1; openlog("rngd", 0, LOG_DAEMON); @@ -284,7 +303,7 @@ int main(int argc, char **argv) } return 1; } - + if (arguments->verbose) { printf("Available entropy sources:\n"); if (!rc_rng) @@ -293,7 +312,7 @@ int main(int argc, char **argv) printf("\tTPM\n"); } - if (rc_rng + if (rc_rng && (rc_tpm || !arguments->enable_tpm)) { if (!arguments->quiet) message(LOG_DAEMON|LOG_ERR, @@ -313,10 +332,23 @@ int main(int argc, char **argv) strerror(errno)); return 1; } + + /* require valid, locked PID file to proceed */ + pid_fd = write_pid_file(arguments->pid_file); + if (pid_fd < 0) + return 1; + + signal(SIGHUP, SIG_IGN); + signal(SIGPIPE, SIG_IGN); + signal(SIGINT, term_signal); + signal(SIGTERM, term_signal); } do_loop(arguments->random_step, arguments->poll_timeout ? : -1.0); + if (pid_fd >= 0) + unlink(arguments->pid_file); + return 0; } @@ -40,6 +40,7 @@ enum { /* Command line arguments and processing */ struct arguments { char *random_name; + char *pid_file; int random_step; int fill_watermark; @@ -82,5 +83,6 @@ extern int am_daemon; /* Nonzero if we went daemon */ } while (0) extern void src_list_add(struct rng *ent_src); +extern int write_pid_file(const char *pid_fn); #endif /* RNGD__H */ @@ -0,0 +1,104 @@ + +/* + * Copyright 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define _GNU_SOURCE + +#ifndef HAVE_CONFIG_H +#error Invalid or missing autoconf build environment +#endif + +#include "rng-tools-config.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> + +#include "rngd.h" + +int write_pid_file(const char *pid_fn) +{ + char str[32], *s; + size_t bytes; + int fd; + struct flock lock; + int err; + + /* build file data */ + sprintf(str, "%u\n", (unsigned int) getpid()); + + /* open non-exclusively (works on NFS v2) */ + fd = open(pid_fn, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + if (fd < 0) { + err = errno; + + message(LOG_DAEMON|LOG_ERR, "Cannot open PID file %s: %s", + pid_fn, strerror(err)); + return -err; + } + + /* lock */ + memset(&lock, 0, sizeof(lock)); + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + if (fcntl(fd, F_SETLK, &lock) != 0) { + err = errno; + if (err == EAGAIN) { + message(LOG_DAEMON|LOG_ERR, "PID file %s is already locked", + pid_fn); + } else { + message(LOG_DAEMON|LOG_ERR, "Cannot lock PID file %s: %s", + pid_fn, strerror(err)); + } + close(fd); + return -err; + } + + /* write file data */ + bytes = strlen(str); + s = str; + while (bytes > 0) { + ssize_t rc = write(fd, s, bytes); + if (rc < 0) { + err = errno; + message(LOG_DAEMON|LOG_ERR, "PID number write failed: %s", + strerror(err)); + goto err_out; + } + + bytes -= rc; + s += rc; + } + + /* make sure file data is written to disk */ + if (fsync(fd) < 0) { + err = errno; + message(LOG_DAEMON|LOG_ERR, "PID file fsync failed: %s", strerror(err)); + goto err_out; + } + + return fd; + +err_out: + unlink(pid_fn); + close(fd); + return -err; +} + |