Accepting request 622295 from home:WernerFink:branches:security
- Move forward to socket communication within private network - Make haveged survive switch root within initrd (boo#1075359) OBS-URL: https://build.opensuse.org/request/show/622295 OBS-URL: https://build.opensuse.org/package/show/security/haveged?expand=0&rev=116
This commit is contained in:
parent
255ec1fd73
commit
b1519e602b
676
change-sysroot.patch
Normal file
676
change-sysroot.patch
Normal file
@ -0,0 +1,676 @@
|
||||
---
|
||||
nist/nist.c | 10 -
|
||||
src/haveged.c | 503 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
src/haveged.h | 2
|
||||
3 files changed, 501 insertions(+), 14 deletions(-)
|
||||
|
||||
--- nist/nist.c
|
||||
+++ nist/nist.c 2018-07-02 13:55:06.644166819 +0000
|
||||
@@ -11,11 +11,11 @@
|
||||
|
||||
|
||||
static int random_pool1 [_32MB];
|
||||
-char basename[FILENAME_MAX+1];
|
||||
+char mybasename[FILENAME_MAX+1];
|
||||
|
||||
char *GetBaseDir(void)
|
||||
{
|
||||
- return basename;
|
||||
+ return mybasename;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@@ -31,10 +31,10 @@ long result=0;
|
||||
/**
|
||||
* get optional directory name
|
||||
*/
|
||||
- basename[0] = 0;
|
||||
+ mybasename[0] = 0;
|
||||
if (argc>2) {
|
||||
- strcat(basename, argv[2]);
|
||||
- strcat(basename, "/");
|
||||
+ strcat(mybasename, argv[2]);
|
||||
+ strcat(mybasename, "/");
|
||||
}
|
||||
|
||||
filename = argv[1];
|
||||
--- src/haveged.c
|
||||
+++ src/haveged.c 2018-07-12 12:10:51.341352610 +0000
|
||||
@@ -32,9 +32,26 @@
|
||||
#include <syslog.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <asm/types.h>
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/stat.h>
|
||||
#include <linux/random.h>
|
||||
#endif
|
||||
|
||||
+#ifndef NO_COMMAND_MODE
|
||||
+#include <sys/socket.h>
|
||||
+#include <sys/un.h>
|
||||
+#include <limits.h>
|
||||
+#define HAVEGED_SOCKET_PATH "\0/sys/entropy/haveged"
|
||||
+static int cmd_listen(void);
|
||||
+static int cmd_connect(void);
|
||||
+static int getcmd(char *arg);
|
||||
+static int socket_handler(int fd, const volatile char *path, char *const argv[]);
|
||||
+static int socket_fd;
|
||||
+#define MAGIC_CHROOT 'R'
|
||||
+static ssize_t safein(int fd, void *ptr, size_t sz);
|
||||
+static void safeout(int fd, const void *ptr, size_t len);
|
||||
+#endif
|
||||
+
|
||||
#include <errno.h>
|
||||
#include "haveged.h"
|
||||
#include "havegecollect.h"
|
||||
@@ -67,7 +84,8 @@ static struct pparams defaults = {
|
||||
.sample_in = INPUT_DEFAULT,
|
||||
.sample_out = OUTPUT_DEFAULT,
|
||||
.verbose = 0,
|
||||
- .watermark = "/proc/sys/kernel/random/write_wakeup_threshold"
|
||||
+ .watermark = "/proc/sys/kernel/random/write_wakeup_threshold",
|
||||
+ .command = 0,
|
||||
};
|
||||
struct pparams *params = &defaults;
|
||||
|
||||
@@ -90,8 +108,9 @@ static H_UINT poolSize = 0;
|
||||
|
||||
static void daemonize(void);
|
||||
static int get_poolsize(void);
|
||||
-static void run_daemon(H_PTR handle);
|
||||
+static void run_daemon(H_PTR handle, const volatile char *path, char *const argv[]);
|
||||
static void set_watermark(int level);
|
||||
+static void new_root(const char *root, const volatile char *path, char *const argv[]);
|
||||
#endif
|
||||
|
||||
static void anchor_info(H_PTR h);
|
||||
@@ -105,14 +124,21 @@ static void show_meterInfo(H_UINT id, H_
|
||||
static void tidy_exit(int signum);
|
||||
static void usage(int db, int nopts, struct option *long_options, const char **cmds);
|
||||
|
||||
+static sigset_t mask, omask;
|
||||
+
|
||||
#define ATOU(a) (unsigned int)atoi(a)
|
||||
/**
|
||||
* Entry point
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
+ volatile char *path = strdup(argv[0]);
|
||||
+ volatile char *arg0 = argv[0];
|
||||
static const char* cmds[] = {
|
||||
"b", "buffer", "1", SETTINGR("Buffer size [KW], default: ",COLLECT_BUFSIZE),
|
||||
+#ifndef NO_COMMAND_MODE
|
||||
+ "c", "command", "1", "Send a command mode to an already running heaveged",
|
||||
+#endif
|
||||
"d", "data", "1", SETTINGR("Data cache size [KB], with fallback to: ", GENERIC_DCACHE ),
|
||||
"i", "inst", "1", SETTINGR("Instruction cache size [KB], with fallback to: ", GENERIC_ICACHE),
|
||||
"f", "file", "1", "Sample output file, default: '" OUTPUT_DEFAULT "', '-' for stdout",
|
||||
@@ -122,7 +148,9 @@ int main(int argc, char **argv)
|
||||
"o", "onlinetest", "1", "[t<x>][c<x>] x=[a[n][w]][b[w]] 't'ot, 'c'ontinuous, default: ta8b",
|
||||
"p", "pidfile", "1", "daemon pidfile, default: " PID_DEFAULT ,
|
||||
"s", "source", "1", "Injection source file, default: '" INPUT_DEFAULT "', '-' for stdin",
|
||||
+#if NUMBER_CORES>1
|
||||
"t", "threads", "1", "Number of threads",
|
||||
+#endif
|
||||
"v", "verbose", "1", "Verbose mask 0=none,1=summary,2=retries,4=timing,8=loop,16=code,32=test",
|
||||
"w", "write", "1", "Set write_wakeup_threshold [bits]",
|
||||
"h", "help", "0", "This help"
|
||||
@@ -157,11 +185,36 @@ int main(int argc, char **argv)
|
||||
#if NUMBER_CORES>1
|
||||
params->setup |= MULTI_CORE;
|
||||
#endif
|
||||
+
|
||||
+ if (access("/etc/initrd-release", F_OK) >= 0) {
|
||||
+ arg0[0] = '@';
|
||||
+ path[0] = '/';
|
||||
+ }
|
||||
+
|
||||
#ifdef SIGHUP
|
||||
signal(SIGHUP, tidy_exit);
|
||||
#endif
|
||||
signal(SIGINT, tidy_exit);
|
||||
signal(SIGTERM, tidy_exit);
|
||||
+#ifndef NO_COMMAND_MODE
|
||||
+ signal(SIGPIPE, SIG_IGN);
|
||||
+#endif
|
||||
+
|
||||
+ sigemptyset(&mask);
|
||||
+#ifdef SIGHUP
|
||||
+ sigaddset(&mask, SIGHUP);
|
||||
+#endif
|
||||
+ sigaddset(&mask, SIGINT);
|
||||
+ sigaddset(&mask, SIGTERM);
|
||||
+#ifndef NO_COMMAND_MODE
|
||||
+ sigaddset(&mask, SIGPIPE);
|
||||
+#endif
|
||||
+#if NUMBER_CORES>1
|
||||
+ /* Hmmm ... currently the code does not use pthread_create(3) but fork(2) */
|
||||
+ pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
|
||||
+#else
|
||||
+ sigprocmask(SIG_UNBLOCK, &mask, NULL);
|
||||
+#endif
|
||||
strcpy(short_options,"");
|
||||
bufct = bufrem = 0;
|
||||
/**
|
||||
@@ -221,6 +274,12 @@ int main(int argc, char **argv)
|
||||
if (params->buffersz<4)
|
||||
error_exit("invalid size %s", optarg);
|
||||
break;
|
||||
+#ifndef NO_COMMAND_MODE
|
||||
+ case 'c':
|
||||
+ params->command = optarg;
|
||||
+ params->setup |= CMD_MODE;
|
||||
+ break;
|
||||
+#endif
|
||||
case 'd':
|
||||
params->d_cache = ATOU(optarg);
|
||||
break;
|
||||
@@ -272,6 +331,74 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
} while (c!=-1);
|
||||
+#ifndef NO_COMMAND_MODE
|
||||
+ if (params->setup & CMD_MODE) {
|
||||
+ int ret = 0, len;
|
||||
+ char *message = NULL, *ptr, answer[2], cmd[2];
|
||||
+ fd_set read_fd;
|
||||
+
|
||||
+ socket_fd = cmd_connect();
|
||||
+ if (socket_fd < 0) {
|
||||
+ ret = -1;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ cmd[0] = getcmd(params->command);
|
||||
+ if (cmd[0] < 0) {
|
||||
+ ret = -1;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ cmd[1] = '\0';
|
||||
+ switch (cmd[0]) {
|
||||
+ char *root;
|
||||
+ case MAGIC_CHROOT:
|
||||
+ root = optarg;
|
||||
+ len = (int)strlen(root);
|
||||
+ ret = asprintf(&message, "%c\002%c%s%n", cmd[0], (int)(strlen(root) + 1), root, &len);
|
||||
+ if (ret < 0) {
|
||||
+ fprintf(stderr, "%s: can not allocate message\n", params->daemon);
|
||||
+ break;
|
||||
+ }
|
||||
+ ptr = message;
|
||||
+ len += 1;
|
||||
+ safeout(socket_fd, message, len);
|
||||
+ break;
|
||||
+ case '?':
|
||||
+ default:
|
||||
+ ret = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+ answer[0] = '\0';
|
||||
+ ptr = &answer[0];
|
||||
+ len = sizeof(answer);
|
||||
+
|
||||
+ FD_ZERO(&read_fd);
|
||||
+ FD_SET(socket_fd, &read_fd);
|
||||
+
|
||||
+ do {
|
||||
+ struct timeval two = {2, 0};
|
||||
+ ret = select(socket_fd+1, &read_fd, NULL, NULL, &two);
|
||||
+ if (ret >= 0) break;
|
||||
+ if (errno != EINTR)
|
||||
+ error_exit("Select error: %s", strerror(errno));
|
||||
+ }
|
||||
+ while (1);
|
||||
+
|
||||
+ ret = safein(socket_fd, ptr, len);
|
||||
+ close(socket_fd);
|
||||
+ if (ret < 0)
|
||||
+ goto err;
|
||||
+ if (answer[0] != '\x6')
|
||||
+ ret = -1;
|
||||
+ else
|
||||
+ ret = 0;
|
||||
+ err:
|
||||
+ return ret;
|
||||
+ }
|
||||
+ else {
|
||||
+ socket_fd = cmd_listen();
|
||||
+ fprintf(stderr, "%s: listening socket at %d\n", params->daemon, socket_fd);
|
||||
+ }
|
||||
+#endif
|
||||
if (params->tests_config == 0)
|
||||
params->tests_config = (0 != (params->setup & RUN_AS_APP))? TESTS_DEFAULT_APP : TESTS_DEFAULT_RUN;
|
||||
memset(&cmd, 0, sizeof(H_PARAMS));
|
||||
@@ -348,7 +475,7 @@ int main(int argc, char **argv)
|
||||
else run_app(handle, bufct, bufrem);
|
||||
}
|
||||
#ifndef NO_DAEMON
|
||||
- else run_daemon(handle);
|
||||
+ else run_daemon(handle, path, argv);
|
||||
#endif
|
||||
havege_destroy(handle);
|
||||
exit(0);
|
||||
@@ -405,9 +532,11 @@ static int get_poolsize( /* RETURN: nu
|
||||
* Run as a daemon writing to random device entropy pool
|
||||
*/
|
||||
static void run_daemon( /* RETURN: nothing */
|
||||
- H_PTR h) /* IN: app instance */
|
||||
+ H_PTR h, /* IN: app instance */
|
||||
+ const volatile char *path,
|
||||
+ char *const argv[])
|
||||
{
|
||||
- int random_fd = -1;
|
||||
+ int random_fd = -1, conn_fd = -1;
|
||||
struct rand_pool_info *output;
|
||||
|
||||
if (0 != params->run_level) {
|
||||
@@ -428,18 +557,56 @@ static void run_daemon( /* RETURN: no
|
||||
error_exit("Couldn't open random device: %s", strerror(errno));
|
||||
|
||||
output = (struct rand_pool_info *) h->io_buf;
|
||||
+
|
||||
+#if NUMBER_CORES>1
|
||||
+ /* Hmmm ... currently the code does not use pthread_create(3) but fork(2) */
|
||||
+ pthread_sigmask(SIG_BLOCK, &mask, &omask);
|
||||
+#else
|
||||
+ sigprocmask(SIG_BLOCK, &mask, &omask);
|
||||
+#endif
|
||||
for(;;) {
|
||||
- int current,nbytes,r;
|
||||
+ int current, nbytes, r, max = 0;
|
||||
+ fd_set read_fd, write_fd;
|
||||
+
|
||||
+ if (params->exit_code > 128)
|
||||
+ error_exit("Stopping due to signal %d\n", params->exit_code - 128);
|
||||
|
||||
- fd_set write_fd;
|
||||
FD_ZERO(&write_fd);
|
||||
+ FD_ZERO(&read_fd);
|
||||
FD_SET(random_fd, &write_fd);
|
||||
+ if (random_fd > max)
|
||||
+ max = random_fd;
|
||||
+ FD_SET(socket_fd, &read_fd);
|
||||
+ if (socket_fd > max)
|
||||
+ max = socket_fd;
|
||||
+ if (conn_fd >= 0) {
|
||||
+ FD_SET(conn_fd, &read_fd);
|
||||
+ if (conn_fd > max)
|
||||
+ max = conn_fd;
|
||||
+ }
|
||||
for(;;) {
|
||||
- int rc = select(random_fd+1, NULL, &write_fd, NULL, NULL);
|
||||
+ struct timespec two = {2, 0};
|
||||
+ int rc = pselect(max+1, &read_fd, &write_fd, NULL, &two, &omask);
|
||||
if (rc >= 0) break;
|
||||
+ if (params->exit_code > 128)
|
||||
+ break;
|
||||
if (errno != EINTR)
|
||||
error_exit("Select error: %s", strerror(errno));
|
||||
}
|
||||
+ if (params->exit_code > 128)
|
||||
+ continue;
|
||||
+
|
||||
+ if (FD_ISSET(socket_fd, &read_fd) && conn_fd < 0) {
|
||||
+ conn_fd = accept4(socket_fd, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK);
|
||||
+ if (conn_fd >= 0)
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (conn_fd >= 0 && FD_ISSET(conn_fd, &read_fd))
|
||||
+ conn_fd = socket_handler(conn_fd, path, argv);
|
||||
+
|
||||
+ if (!FD_ISSET(random_fd, &write_fd))
|
||||
+ continue;
|
||||
+
|
||||
if (ioctl(random_fd, RNDGETENTCNT, ¤t) == -1)
|
||||
error_exit("Couldn't query entropy-level from kernel");
|
||||
/* get number of bytes needed to fill pool */
|
||||
@@ -719,8 +886,8 @@ static void tidy_exit( /* OUT:
|
||||
int signum) /* IN: signal number */
|
||||
{
|
||||
params->exit_code = 128 + signum;
|
||||
- error_exit("Stopping due to signal %d\n", signum);
|
||||
}
|
||||
+
|
||||
/**
|
||||
* send usage display to stderr
|
||||
*/
|
||||
@@ -750,3 +917,321 @@ static void usage( /* OUT:
|
||||
fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
}
|
||||
+
|
||||
+#ifndef NO_DAEMON
|
||||
+static void new_root(
|
||||
+ const char *root,
|
||||
+ const volatile char *path,
|
||||
+ char *const argv[])
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ fprintf(stderr, "%s: restart in new root: %s\n", params->daemon, root);
|
||||
+ ret = chdir(root);
|
||||
+ if (ret < 0) {
|
||||
+ if (errno != ENOENT)
|
||||
+ error_exit("can't change to working directory : %s", root);
|
||||
+ else
|
||||
+ fprintf(stderr, "%s: can't change to working directory : %s\n", params->daemon, root);
|
||||
+ }
|
||||
+ ret = chroot(".");
|
||||
+ if (ret < 0) {
|
||||
+ if (errno != ENOENT)
|
||||
+ error_exit("can't change root directory");
|
||||
+ else
|
||||
+ fprintf(stderr, "%s: can't change root directory\n", params->daemon);
|
||||
+ }
|
||||
+ ret = chdir("/");
|
||||
+ if (ret < 0) {
|
||||
+ if (errno != ENOENT)
|
||||
+ error_exit("can't change to working directory /");
|
||||
+ else
|
||||
+ fprintf(stderr, "%s: can't change to working directory /\n", params->daemon);
|
||||
+ }
|
||||
+ ret = execv((const char *)path, argv);
|
||||
+ if (ret < 0) {
|
||||
+ if (errno != ENOENT)
|
||||
+ error_exit("can't restart %s", path);
|
||||
+ else
|
||||
+ fprintf(stderr, "%s: can't restart %s\n", params->daemon, path);
|
||||
+ }
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#ifndef NO_COMMAND_MODE
|
||||
+/**
|
||||
+ * Open and listen on a UNIX socket to get command from there
|
||||
+ */
|
||||
+static int cmd_listen(void)
|
||||
+{
|
||||
+ struct sockaddr_un su = { /* The abstract UNIX socket of haveged */
|
||||
+ .sun_family = AF_UNIX,
|
||||
+ .sun_path = HAVEGED_SOCKET_PATH,
|
||||
+ };
|
||||
+ const int one = 1;
|
||||
+ int fd, ret;
|
||||
+
|
||||
+ fd = socket(PF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||
+ if (fd < 0) {
|
||||
+ fprintf(stderr, "%s: can not open UNIX socket\n", params->daemon);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, (socklen_t)sizeof(one));
|
||||
+ if (ret < 0) {
|
||||
+ close(fd);
|
||||
+ fd = -1;
|
||||
+ fprintf(stderr, "%s: can not set option for UNIX socket\n", params->daemon);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ret = bind(fd, &su, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(su.sun_path+1));
|
||||
+ if (ret < 0) {
|
||||
+ close(fd);
|
||||
+ fd = -1;
|
||||
+ if (errno != EADDRINUSE)
|
||||
+ fprintf(stderr, "%s: can not bind a name to UNIX socket\n", params->daemon);
|
||||
+ else
|
||||
+ fd = -2;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ret = listen(fd, SOMAXCONN);
|
||||
+ if (ret < 0) {
|
||||
+ close(fd);
|
||||
+ fd = -1;
|
||||
+ fprintf(stderr, "%s: can not listen on UNIX socket\n", params->daemon);
|
||||
+ goto err;
|
||||
+ }
|
||||
+err:
|
||||
+ return fd;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Open and connect on a UNIX socket to send command over this
|
||||
+ */
|
||||
+static int cmd_connect(void)
|
||||
+{
|
||||
+ struct sockaddr_un su = { /* The abstract UNIX socket of haveged */
|
||||
+ .sun_family = AF_UNIX,
|
||||
+ .sun_path = HAVEGED_SOCKET_PATH,
|
||||
+ };
|
||||
+ const int one = 1;
|
||||
+ int fd, ret;
|
||||
+
|
||||
+ fd = socket(PF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||
+ if (fd < 0) {
|
||||
+ fprintf(stderr, "%s: can not open UNIX socket\n", params->daemon);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, (socklen_t)sizeof(one));
|
||||
+ if (ret < 0) {
|
||||
+ fprintf(stderr, "%s: can not set option for UNIX socket\n", params->daemon);
|
||||
+ close(fd);
|
||||
+ fd = -1;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ret = connect(fd, &su, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(su.sun_path+1));
|
||||
+ if (ret < 0) {
|
||||
+ if (errno != ECONNREFUSED)
|
||||
+ fprintf(stderr, "%s: can not connect on UNIX socket\n", params->daemon);
|
||||
+ close(fd);
|
||||
+ fd = -1;
|
||||
+ goto err;
|
||||
+ }
|
||||
+err:
|
||||
+ return fd;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Handle arguments in command mode
|
||||
+ */
|
||||
+static int getcmd(
|
||||
+ char *arg)
|
||||
+{
|
||||
+ static const struct {
|
||||
+ const char* cmd;
|
||||
+ const int req;
|
||||
+ const int arg;
|
||||
+ const char* opt;
|
||||
+ } cmds[] = {
|
||||
+ { "root=", MAGIC_CHROOT, 1, NULL }, /* New root */
|
||||
+ {}
|
||||
+ }, *cmd = cmds;
|
||||
+ int ret = -1;
|
||||
+
|
||||
+ if (!arg || !*arg)
|
||||
+ goto err;
|
||||
+
|
||||
+ optarg = NULL;
|
||||
+ for (; cmd->cmd; cmd++)
|
||||
+ if (cmd->arg) {
|
||||
+ if (strncmp(cmd->cmd, arg, strlen(cmd->cmd)) == 0) {
|
||||
+ optarg = strchr(arg, '=');
|
||||
+ optarg++;
|
||||
+ ret = cmd->req;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ else {
|
||||
+ if (strcmp(cmd->cmd, arg) == 0) {
|
||||
+ ret = cmd->req;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+err:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Handle incomming messages from socket
|
||||
+ */
|
||||
+static int socket_handler(
|
||||
+ int fd,
|
||||
+ const volatile char *path,
|
||||
+ char *const argv[])
|
||||
+{
|
||||
+ struct ucred cred = {};
|
||||
+ unsigned char magic[2], *ptr;
|
||||
+ char *enqry;
|
||||
+ char *optarg = NULL;
|
||||
+ socklen_t clen;
|
||||
+ int ret = -1, len;
|
||||
+
|
||||
+ if (fd < 0) {
|
||||
+ fprintf(stderr, "%s: no connection jet\n", params->daemon);
|
||||
+ }
|
||||
+
|
||||
+ ptr = &magic[0];
|
||||
+ len = sizeof(magic);
|
||||
+ ret = safein(fd, ptr, len);
|
||||
+
|
||||
+ if (magic[1] == '\002') { /* read argument provided */
|
||||
+ unsigned char alen;
|
||||
+
|
||||
+ ret = safein(fd, &alen, sizeof(unsigned char));
|
||||
+
|
||||
+ optarg = calloc(alen, sizeof(char));
|
||||
+ if (!optarg)
|
||||
+ error_exit("can not allocate memory for message from UNUX socket");
|
||||
+
|
||||
+ ptr = (unsigned char*)optarg;
|
||||
+ len = alen;
|
||||
+ ret = safein(fd, ptr, len);
|
||||
+ }
|
||||
+
|
||||
+ clen = sizeof(struct ucred);
|
||||
+ ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &clen);
|
||||
+ if (ret < 0) {
|
||||
+ fprintf(stderr, "%s: can not get credentials from UNIX socket part1\n", params->daemon);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (clen != sizeof(struct ucred)) {
|
||||
+ fprintf(stderr, "%s: can not get credentials from UNIX socket part2\n", params->daemon);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (cred.uid != 0) {
|
||||
+ enqry = "\x15";
|
||||
+
|
||||
+ ptr = (unsigned char *)enqry;
|
||||
+ len = (int)strlen(enqry)+1;
|
||||
+ safeout(fd, ptr, len);
|
||||
+ }
|
||||
+
|
||||
+ switch (magic[0]) {
|
||||
+ case MAGIC_CHROOT:
|
||||
+ enqry = "\x6";
|
||||
+
|
||||
+ ptr = (unsigned char *)enqry;
|
||||
+ len = (int)strlen(enqry)+1;
|
||||
+ safeout(fd, ptr, len);
|
||||
+
|
||||
+ new_root(optarg, path, argv);
|
||||
+ break;
|
||||
+ default:
|
||||
+ enqry = "\x15";
|
||||
+
|
||||
+ ptr = (unsigned char *)enqry;
|
||||
+ len = (int)strlen(enqry)+1;
|
||||
+ safeout(fd, ptr, len);
|
||||
+ break;
|
||||
+ }
|
||||
+out:
|
||||
+ if (fd > 0) {
|
||||
+ close(fd);
|
||||
+ fd = -1;
|
||||
+ }
|
||||
+ return fd;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Receive incomming messages from socket
|
||||
+ */
|
||||
+static ssize_t safein(
|
||||
+ int fd,
|
||||
+ void *ptr,
|
||||
+ size_t sz)
|
||||
+{
|
||||
+ int saveerr = errno, t;
|
||||
+ ssize_t ret = 0;
|
||||
+ size_t len;
|
||||
+
|
||||
+ if (sz > SSIZE_MAX)
|
||||
+ sz = SSIZE_MAX;
|
||||
+
|
||||
+ t = 0;
|
||||
+ if ((ioctl(fd, FIONREAD, &t) < 0) || (t <= 0))
|
||||
+ goto out;
|
||||
+
|
||||
+ len = (size_t)t;
|
||||
+ if (len > sz)
|
||||
+ len = sz;
|
||||
+
|
||||
+ do {
|
||||
+ ssize_t p = recv(fd, ptr, len, MSG_DONTWAIT);
|
||||
+ if (p < 0) {
|
||||
+ if (errno == EINTR)
|
||||
+ continue;
|
||||
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
+ break;
|
||||
+ error_exit("Unable to read from socket: %d", socket_fd);
|
||||
+ }
|
||||
+ ptr += p;
|
||||
+ ret += p;
|
||||
+ len -= p;
|
||||
+ }
|
||||
+ while (len > 0);
|
||||
+out:
|
||||
+ errno = saveerr;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Send outgoing messages to socket
|
||||
+ */
|
||||
+static void safeout(
|
||||
+ int fd,
|
||||
+ const void *ptr,
|
||||
+ size_t len)
|
||||
+{
|
||||
+ int saveerr = errno;
|
||||
+
|
||||
+ do {
|
||||
+ ssize_t p = send(fd, ptr, len, MSG_NOSIGNAL);
|
||||
+ if (p < 0) {
|
||||
+ if (errno == EINTR)
|
||||
+ continue;
|
||||
+ if (errno == EPIPE || errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
+ break;
|
||||
+ error_exit("Unable to write to socket: %d", fd);
|
||||
+ }
|
||||
+ ptr += p;
|
||||
+ len -= p;
|
||||
+ }
|
||||
+ while (len > 0);
|
||||
+
|
||||
+ errno = saveerr;
|
||||
+}
|
||||
+#endif
|
||||
--- src/haveged.h
|
||||
+++ src/haveged.h 2018-07-02 13:33:12.944114136 +0000
|
||||
@@ -45,6 +45,7 @@ struct pparams {
|
||||
H_UINT verbose; /* Output level for log or stdout */
|
||||
char *version; /* Our version */
|
||||
char *watermark; /* path to write_wakeup_threshold */
|
||||
+ char *command; /* command which will send/received */
|
||||
};
|
||||
/**
|
||||
* Buffer size used when not running as daemon
|
||||
@@ -64,6 +65,7 @@ struct pparams {
|
||||
#define RUN_IN_FG 0x020
|
||||
#define SET_LWM 0x040
|
||||
#define MULTI_CORE 0x080
|
||||
+#define CMD_MODE 0x100
|
||||
/**
|
||||
* Default tests settings
|
||||
*/
|
@ -1,7 +1,10 @@
|
||||
diff -urN haveged-1.9.1/configure.ac haveged-1.9.1.new/configure.ac
|
||||
--- haveged-1.9.1/configure.ac 2014-02-11 16:06:58.000000000 +0100
|
||||
+++ haveged-1.9.1.new/configure.ac 2014-05-12 12:57:40.111268914 +0200
|
||||
@@ -60,6 +60,11 @@
|
||||
---
|
||||
haveged-1.9.2/configure.ac | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
--- haveged-1.9.2/configure.ac
|
||||
+++ haveged-1.9.2/configure.ac 2018-06-26 08:06:45.195289211 +0000
|
||||
@@ -61,6 +61,11 @@ AC_ARG_ENABLE(nistest,
|
||||
AS_HELP_STRING([--enable-nistest=[no/yes]],[Run NIST test suite [default=no]]),
|
||||
, enable_nistest="no")
|
||||
|
||||
@ -13,7 +16,7 @@ diff -urN haveged-1.9.1/configure.ac haveged-1.9.1.new/configure.ac
|
||||
## Make self test features configurable
|
||||
AC_ARG_ENABLE(olt,
|
||||
AS_HELP_STRING([--enable-olt=[yes/no]],[Enable online tests [default=yes]]),
|
||||
@@ -225,7 +230,7 @@
|
||||
@@ -228,7 +233,7 @@ AM_CONDITIONAL(ENABLE_SYSV, test "$init_
|
||||
AM_CONDITIONAL(ENABLE_SYSTEMD, test "$init_type" = "systemd")
|
||||
AM_CONDITIONAL(ENABLE_SYSTEMD_LOOKUP, test "$enable_initdir" = "?")
|
||||
AM_CONDITIONAL(ENABLE_NOINIT, test "$init_type" = "none")
|
||||
|
@ -15,7 +15,11 @@ installkernel() {
|
||||
install() {
|
||||
inst_multiple -o \
|
||||
/usr/sbin/haveged \
|
||||
$systemdsystemunitdir/haveged.service
|
||||
mkdir "$initdir/$systemdsystemunitdir/systemd-journald.service.wants"
|
||||
$systemdsystemunitdir/haveged.service \
|
||||
$systemdsystemunitdir/haveged-switch-root.service
|
||||
mkdir -p "$initdir/$systemdsystemunitdir/sysinit.target.wants"
|
||||
mkdir -p "$initdir/$systemdsystemunitdir/initrd-switch-root.target.wants"
|
||||
mkdir -p "$initdir/$systemdsystemunitdir/systemd-journald.service.wants"
|
||||
ln_r "$systemdsystemunitdir/haveged.service" "$systemdsystemunitdir/systemd-journald.service.wants/haveged.service"
|
||||
ln_r "$systemdsystemunitdir/haveged-switch-root.service" "$systemdsystemunitdir/initrd-switch-root.target.wants/haveged-switch-root.service"
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
Index: haveged-1.9.1/src/haveged.c
|
||||
===================================================================
|
||||
--- haveged-1.9.1.orig/src/haveged.c
|
||||
+++ haveged-1.9.1/src/haveged.c
|
||||
---
|
||||
haveged-1.9.2/src/haveged.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
--- haveged-1.9.2/src/haveged.c
|
||||
+++ haveged-1.9.2/src/haveged.c 2018-06-26 08:07:51.430076528 +0000
|
||||
@@ -361,8 +361,10 @@ static void daemonize( /* RETURN: no
|
||||
void) /* IN: nothing */
|
||||
{
|
||||
@ -13,7 +17,7 @@ Index: haveged-1.9.1/src/haveged.c
|
||||
if (daemon(0, 0) == -1)
|
||||
error_exit("Cannot fork into the background");
|
||||
fh = fopen(params->pid_file, "w");
|
||||
@@ -499,7 +501,9 @@ static void error_exit( /* RETURN: no
|
||||
@@ -501,7 +503,9 @@ static void error_exit( /* RETURN: no
|
||||
#ifndef NO_DAEMON
|
||||
if (params->detached!=0) {
|
||||
unlink(params->pid_file);
|
||||
@ -23,7 +27,7 @@ Index: haveged-1.9.1/src/haveged.c
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -609,11 +613,13 @@ static void print_msg( /* RETURN: no
|
||||
@@ -611,11 +615,13 @@ static void print_msg( /* RETURN: no
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
snprintf(buffer, sizeof(buffer), "%s: %s", params->daemon, format);
|
||||
|
17
haveged-switch-root.service
Normal file
17
haveged-switch-root.service
Normal file
@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=Tell haveged about new root
|
||||
DefaultDependencies=no
|
||||
ConditionPathExists=/etc/initrd-release
|
||||
Before=initrd-switch-root.service
|
||||
JoinsNamespaceOf=haveged.service
|
||||
|
||||
[Service]
|
||||
ExecStart=-/usr/sbin/haveged -c root=/sysroot
|
||||
PrivateNetwork=yes
|
||||
Type=oneshot
|
||||
StandardInput=null
|
||||
StandardOutput=null
|
||||
StandardError=null
|
||||
|
||||
[Install]
|
||||
WantedBy=initrd-switch-root.target
|
@ -1,3 +1,13 @@
|
||||
-------------------------------------------------------------------
|
||||
Mon Jul 2 13:37:19 UTC 2018 - werner@suse.de
|
||||
|
||||
- Move forward to socket communication within private network
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Jun 27 08:51:36 UTC 2018 - werner@suse.de
|
||||
|
||||
- Make haveged survive switch root within initrd (boo#1075359)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Mar 19 15:32:07 CET 2018 - kukuk@suse.de
|
||||
|
||||
|
@ -10,7 +10,7 @@ Before=sysinit.target shutdown.target systemd-journald.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/sbin/haveged -w 1024 -v 0 -F
|
||||
CapabilityBoundingSet=CAP_SYS_ADMIN
|
||||
CapabilityBoundingSet=CAP_SYS_ADMIN CAP_SYS_CHROOT
|
||||
PrivateNetwork=yes
|
||||
Restart=always
|
||||
SuccessExitStatus=137 143
|
||||
|
15
haveged.spec
15
haveged.spec
@ -28,11 +28,13 @@ Source0: http://www.issihosts.com/haveged/%{name}-%{version}.tar.gz
|
||||
Source2: %{name}.service
|
||||
Source3: 90-haveged.rules
|
||||
Source4: haveged-dracut.module
|
||||
Source5: %{name}-switch-root.service
|
||||
Patch0: ppc64le.patch
|
||||
# PATCH-FIX-UPSTREAM: ent tests randomly fail so make them conditional tchvatal@suse.cz bnc#876674
|
||||
Patch1: haveged-conditional-enttest.patch
|
||||
# PATCH-FIX-UPSTREAM: don't write to syslog at startup to avoid deadlocks psimons@suse.com bnc#959237
|
||||
Patch3: haveged-no-syslog.patch
|
||||
Patch2: haveged-no-syslog.patch
|
||||
Patch3: change-sysroot.patch
|
||||
BuildRequires: autoconf
|
||||
BuildRequires: automake
|
||||
BuildRequires: libtool
|
||||
@ -80,11 +82,12 @@ algorithm and supporting features.
|
||||
%setup -q
|
||||
%patch0 -p1
|
||||
%patch1 -p1
|
||||
%patch3 -p1
|
||||
%patch2 -p1
|
||||
%patch3 -p0
|
||||
|
||||
%build
|
||||
autoreconf -fvi
|
||||
export CFLAGS="%{optflags} -fpie"
|
||||
export CFLAGS="%{optflags} -fpie -D_DEFAULT_SOURCE -D_GNU_SOURCE"
|
||||
export LDFLAGS="-Wl,-z,relro,-z,now -pie"
|
||||
# ENT randomly fails so disable the test
|
||||
%configure \
|
||||
@ -109,6 +112,7 @@ make %{?_smp_mflags} check
|
||||
%make_install
|
||||
install -D -m0644 %{SOURCE2} %{buildroot}%{_unitdir}/%{name}.service
|
||||
install -D -m0644 %{SOURCE3} %{buildroot}%{_udevrulesdir}/90-%{name}.rules
|
||||
install -D -m0644 %{SOURCE5} %{buildroot}%{_unitdir}/%{name}-switch-root.service
|
||||
rm -f %{buildroot}%{_libdir}/libhavege.*a
|
||||
ln -s %{_sbindir}/service %{buildroot}%{_sbindir}/rc%{name}
|
||||
|
||||
@ -118,10 +122,12 @@ install -m0755 %{SOURCE4} %{buildroot}%{_prefix}/lib/dracut/modules.d/98%{name}/
|
||||
%post
|
||||
%{?udev_rules_update:%udev_rules_update}
|
||||
%service_add_post %{name}.service
|
||||
%service_add_post %{name}-switch-root.service
|
||||
%{?regenerate_initrd_post}
|
||||
|
||||
%postun
|
||||
%service_del_postun %{name}.service
|
||||
%service_del_postun %{name}-switch-root.service
|
||||
%{?regenerate_initrd_post}
|
||||
|
||||
%posttrans
|
||||
@ -129,9 +135,11 @@ install -m0755 %{SOURCE4} %{buildroot}%{_prefix}/lib/dracut/modules.d/98%{name}/
|
||||
|
||||
%pre
|
||||
%service_add_pre %{name}.service
|
||||
%service_add_pre %{name}-switch-root.service
|
||||
|
||||
%preun
|
||||
%service_del_preun %{name}.service
|
||||
%service_del_preun %{name}-switch-root.service
|
||||
|
||||
%post -n libhavege1 -p /sbin/ldconfig
|
||||
%postun -n libhavege1 -p /sbin/ldconfig
|
||||
@ -142,6 +150,7 @@ install -m0755 %{SOURCE4} %{buildroot}%{_prefix}/lib/dracut/modules.d/98%{name}/
|
||||
%{_sbindir}/%{name}
|
||||
%{_mandir}/man8/%{name}.8%{ext_man}
|
||||
%{_unitdir}/%{name}.service
|
||||
%{_unitdir}/%{name}-switch-root.service
|
||||
%{_udevrulesdir}/90-%{name}.rules
|
||||
%dir %{_prefix}/lib/dracut
|
||||
%dir %{_prefix}/lib/dracut/modules.d
|
||||
|
@ -1,8 +1,12 @@
|
||||
Index: haveged-1.9.1/configure.ac
|
||||
===================================================================
|
||||
--- haveged-1.9.1.orig/configure.ac
|
||||
+++ haveged-1.9.1/configure.ac
|
||||
@@ -156,7 +156,7 @@ case "$host" in
|
||||
---
|
||||
haveged-1.9.2/configure.ac | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- haveged-1.9.2/configure.ac
|
||||
+++ haveged-1.9.2/configure.ac 2018-06-26 08:05:43.668415539 +0000
|
||||
@@ -157,7 +157,7 @@ case "$host" in
|
||||
AC_DEFINE(HAVE_ISA_IA64, 1, [Define to 1 for ia64])
|
||||
;;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user