summaryrefslogtreecommitdiffstats
path: root/src/privsep-root.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2019-11-29 13:55:46 +0000
committerRoy Marples <roy@marples.name>2019-11-29 13:55:46 +0000
commitc920247719ccbe2a0297a5467f04f459eb052398 (patch)
tree54368294ead2aa4b2f9eef4ca84a22a9fa767307 /src/privsep-root.c
parente91451a20d134ff9e3b22cc398341b94e5e2904b (diff)
downloaddhcpcd-c920247719ccbe2a0297a5467f04f459eb052398.tar.xz
privsep: Use another eloop instead of a blocking read.
We need to read the error status from making a privileged request. This happens in an eloop already, but the read itself needs to block. So that we can still be interupted, use an inner eloop whose sole purpose is to monitor the root fd for message back. Then we can make the fd non blocking. dhcpcd should now exit cleanly once more.
Diffstat (limited to 'src/privsep-root.c')
-rw-r--r--src/privsep-root.c85
1 files changed, 67 insertions, 18 deletions
diff --git a/src/privsep-root.c b/src/privsep-root.c
index 7716566d..10d97425 100644
--- a/src/privsep-root.c
+++ b/src/privsep-root.c
@@ -53,25 +53,59 @@ struct psr_error
char psr_pad[sizeof(ssize_t) - sizeof(int)];
};
-ssize_t
-ps_root_readerror(struct dhcpcd_ctx *ctx)
+struct psr_ctx {
+ struct dhcpcd_ctx *psr_ctx;
+ struct psr_error psr_error;
+};
+
+static void
+ps_root_readerrorsig(__unused int sig, void *arg)
{
- struct psr_error psr;
+ struct dhcpcd_ctx *ctx = arg;
+
+ eloop_exit(ctx->ps_eloop, EXIT_FAILURE);
+}
+
+static void
+ps_root_readerrorcb(void *arg)
+{
+ struct psr_ctx *psr_ctx = arg;
+ struct dhcpcd_ctx *ctx = psr_ctx->psr_ctx;
+ struct psr_error *psr_error = &psr_ctx->psr_error;
ssize_t len;
+ int exit_code = EXIT_FAILURE;
- /* ps_root_fd should be a blocking socket. */
- len = read(ctx->ps_root_fd, &psr, sizeof(psr));
+ len = read(ctx->ps_root_fd, psr_error, sizeof(*psr_error));
if (len == 0 || len == -1) {
logerr(__func__);
- return len;
- }
- if ((size_t)len < sizeof(psr)) {
+ psr_error->psr_result = -1;
+ psr_error->psr_errno = errno;
+ } else if ((size_t)len < sizeof(*psr_error)) {
logerrx("%s: psr_error truncated", __func__);
+ psr_error->psr_result = -1;
+ psr_error->psr_errno = EINVAL;
+ } else
+ exit_code = EXIT_SUCCESS;
+
+ eloop_exit(ctx->ps_eloop, exit_code);
+}
+
+ssize_t
+ps_root_readerror(struct dhcpcd_ctx *ctx)
+{
+ struct psr_ctx psr_ctx = { .psr_ctx = ctx };
+
+ if (eloop_event_add(ctx->ps_eloop, ctx->ps_root_fd,
+ ps_root_readerrorcb, &psr_ctx) == -1)
+ {
+ logerr(__func__);
return -1;
}
- errno = psr.psr_errno;
- return psr.psr_result;
+ eloop_start(ctx->ps_eloop, &ctx->sigset);
+
+ errno = psr_ctx.psr_error.psr_errno;
+ return psr_ctx.psr_error.psr_result;
}
static ssize_t
@@ -230,7 +264,8 @@ ps_root_recvmsg(void *arg)
{
struct dhcpcd_ctx *ctx = arg;
- if (ps_recvpsmsg(ctx, ctx->ps_root_fd, ps_root_recvmsgcb, ctx) == -1)
+ if (ps_recvpsmsg(ctx, ctx->ps_root_fd, ps_root_recvmsgcb, ctx) == -1 &&
+ errno != ECONNRESET)
logerr(__func__);
}
@@ -241,7 +276,6 @@ ps_root_startcb(void *arg)
setproctitle("[privileged actioneer]");
ctx->ps_root_pid = getpid();
-
return 0;
}
@@ -301,12 +335,27 @@ ps_root_start(struct dhcpcd_ctx *ctx)
if (pid == 0) {
ctx->ps_data_fd = fd[1];
close(fd[0]);
- } else if (pid != -1) {
- ctx->ps_data_fd = fd[0];
- close(fd[1]);
- if (eloop_event_add(ctx->eloop, ctx->ps_data_fd,
- ps_root_dispatch, ctx) == -1)
- logerr(__func__);
+ return 0;
+ } else if (pid == -1)
+ return -1;
+
+ ctx->ps_data_fd = fd[0];
+ close(fd[1]);
+ if (eloop_event_add(ctx->eloop, ctx->ps_data_fd,
+ ps_root_dispatch, ctx) == -1)
+ logerr(__func__);
+
+ if ((ctx->ps_eloop = eloop_new()) == NULL) {
+ logerr(__func__);
+ return -1;
+ }
+
+ if (eloop_signal_set_cb(ctx->ps_eloop,
+ dhcpcd_signals, dhcpcd_signals_len,
+ ps_root_readerrorsig, ctx) == -1)
+ {
+ logerr(__func__);
+ return -1;
}
return pid;
}