dumpon: Fix -v causing error when configuring an encrypted dump

If -v is specified when adding a new device then a full listing of
configured devices is displayed.  This requires sysctl access which
genkey()'s use of capability mode was blocking permission to access.
This leads to both confusing console spam but also incorrectly returning
an error status even if no other had been encountered.

	dumpon: Sysctl get 'kern.shutdown.dumpdevname': Operation not permitted

Fix this by generating the key in a child process.

Reviewed by:	markj
Sponsored by:	Dell EMC
Differential Revision: https://reviews.freebsd.org/D31266
This commit is contained in:
Bryan Drewery 2021-07-21 17:37:03 -07:00
parent b0fa09a0a7
commit 372557d8c3

View file

@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <sys/disk.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/wait.h>
#include <assert.h>
#include <capsicum_helpers.h>
@ -210,7 +211,7 @@ check_size(int fd, const char *fn)
#ifdef HAVE_CRYPTO
static void
genkey(const char *pubkeyfile, struct diocskerneldump_arg *kdap)
_genkey(const char *pubkeyfile, struct diocskerneldump_arg *kdap)
{
FILE *fp;
RSA *pubkey;
@ -305,6 +306,50 @@ genkey(const char *pubkeyfile, struct diocskerneldump_arg *kdap)
}
RSA_free(pubkey);
}
/*
* Run genkey() in a child so it can use capability mode without affecting
* the rest of the runtime.
*/
static void
genkey(const char *pubkeyfile, struct diocskerneldump_arg *kdap)
{
pid_t pid;
int error, filedes[2], status;
ssize_t bytes;
if (pipe2(filedes, O_CLOEXEC) != 0)
err(1, "pipe");
pid = fork();
switch (pid) {
case -1:
err(1, "fork");
break;
case 0:
close(filedes[0]);
_genkey(pubkeyfile, kdap);
/* Write the new kdap back to the parent. */
bytes = write(filedes[1], kdap, sizeof(*kdap));
if (bytes != sizeof(*kdap))
err(1, "genkey pipe write");
_exit(0);
}
close(filedes[1]);
/* Read in the child's genkey() result into kdap. */
bytes = read(filedes[0], kdap, sizeof(*kdap));
if (bytes != sizeof(*kdap))
errx(1, "genkey pipe read");
error = waitpid(pid, &status, WEXITED);
if (error == -1)
err(1, "waitpid");
if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
errx(1, "genkey child exited with status %d",
WEXITSTATUS(status));
else if (WIFSIGNALED(status))
errx(1, "genkey child exited with signal %d",
WTERMSIG(status));
close(filedes[0]);
}
#endif
static void