socsvn commit: r293059 - in soc2013/def/crashdump-head: sbin sbin/cryptcore sbin/decryptcore sbin/dumpon sbin/savecore sys/amd64/amd64 sys/ddb sys/dev/null sys/geom sys/kern sys/sys
def at FreeBSD.org
def at FreeBSD.org
Mon Oct 26 04:19:16 UTC 2015
Author: def
Date: Mon Oct 26 04:19:08 2015
New Revision: 293059
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=293059
Log:
Use ioctl(2) DIOCSKERNELDUMP for EKCD setup.
Added:
soc2013/def/crashdump-head/sbin/decryptcore/
soc2013/def/crashdump-head/sbin/decryptcore/Makefile
soc2013/def/crashdump-head/sbin/decryptcore/decryptcore.c
Deleted:
soc2013/def/crashdump-head/sbin/cryptcore/
Modified:
soc2013/def/crashdump-head/sbin/Makefile
soc2013/def/crashdump-head/sbin/dumpon/Makefile
soc2013/def/crashdump-head/sbin/dumpon/dumpon.c
soc2013/def/crashdump-head/sbin/savecore/savecore.c
soc2013/def/crashdump-head/sys/amd64/amd64/minidump_machdep.c
soc2013/def/crashdump-head/sys/ddb/db_textdump.c
soc2013/def/crashdump-head/sys/dev/null/null.c
soc2013/def/crashdump-head/sys/geom/geom_dev.c
soc2013/def/crashdump-head/sys/kern/kern_dump.c
soc2013/def/crashdump-head/sys/kern/kern_shutdown.c
soc2013/def/crashdump-head/sys/sys/conf.h
soc2013/def/crashdump-head/sys/sys/disk.h
soc2013/def/crashdump-head/sys/sys/kerneldump.h
Modified: soc2013/def/crashdump-head/sbin/Makefile
==============================================================================
--- soc2013/def/crashdump-head/sbin/Makefile Mon Oct 26 03:55:13 2015 (r293058)
+++ soc2013/def/crashdump-head/sbin/Makefile Mon Oct 26 04:19:08 2015 (r293059)
@@ -11,7 +11,7 @@
clri \
comcontrol \
conscontrol \
- cryptcore \
+ decryptcore \
ddb \
devfs \
dhclient \
Added: soc2013/def/crashdump-head/sbin/decryptcore/Makefile
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ soc2013/def/crashdump-head/sbin/decryptcore/Makefile Mon Oct 26 04:19:08 2015 (r293059)
@@ -0,0 +1,12 @@
+PROG= decryptcore
+
+SRCS= ${PROG}.c
+
+LIBADD= crypto pjdlog
+
+MAN=
+
+CFLAGS+=-I${.CURDIR}/../../sys
+CFLAGS+=-I${.CURDIR}/../../lib/libpjdlog
+
+.include <bsd.prog.mk>
Added: soc2013/def/crashdump-head/sbin/decryptcore/decryptcore.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ soc2013/def/crashdump-head/sbin/decryptcore/decryptcore.c Mon Oct 26 04:19:08 2015 (r293059)
@@ -0,0 +1,277 @@
+#include <sys/capsicum.h>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/kerneldump.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+#include <openssl/engine.h>
+
+#include <fcntl.h>
+#include <pjdlog.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(void)
+{
+
+ pjdlog_exitx(1, "usage: decryptcore [-Lv] -p privatekey -k encryptedkey -i encryptedcore -o decryptedcore");
+}
+
+static int
+wait_for_process(pid_t pid)
+{
+ int status;
+
+ if (waitpid(pid, &status, WNOHANG | WUNTRACED | WEXITED) == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to wait for a child process");
+ goto failed;
+ }
+
+ if (WIFEXITED(status))
+ return (WEXITSTATUS(status));
+failed:
+ return (1);
+}
+
+static bool
+decrypt(const char *privkeyfile, const char *keyfile, const char *input,
+ const char *output)
+{
+ uint8_t buf[2 * KERNELDUMP_BLOCK_SIZE], key[KERNELDUMP_KEY_SIZE];
+ EVP_CIPHER_CTX ctx;
+ FILE *fp;
+ struct kerneldumpkey *kdk;
+ RSA *privkey;
+ int error, ifd, kfd, ofd, olen, privkeysize;
+ ssize_t bytes, size;
+ size_t bufused, kdksize;
+ pid_t pid;
+
+ PJDLOG_ASSERT(privkeyfile != NULL);
+ PJDLOG_ASSERT(keyfile != NULL);
+ PJDLOG_ASSERT(input != NULL);
+ PJDLOG_ASSERT(output != NULL);
+
+ fp = NULL;
+ ifd = -1;
+ kdk = NULL;
+ kfd = -1;
+ ofd = -1;
+ privkey = NULL;
+
+ pid = fork();
+ if (pid == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to create child process");
+ return (false);
+ }
+
+ if (pid > 0)
+ return (wait_for_process(pid) == 0);
+
+ kfd = open(keyfile, O_RDONLY);
+ if (kfd == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to open %s", keyfile);
+ goto failed;
+ }
+ ifd = open(input, O_RDONLY);
+ if (ifd == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to open %s", input);
+ goto failed;
+ }
+ ofd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ if (ofd == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to open %s", output);
+ goto failed;
+ }
+ fp = fopen(privkeyfile, "r");
+ if (fp == NULL) {
+ pjdlog_errno(LOG_ERR, "Unable to open %s", privkeyfile);
+ goto failed;
+ }
+
+ if (cap_enter() == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to enter capability mode");
+ goto failed;
+ }
+
+ privkey = RSA_new();
+ if (privkey == NULL) {
+ pjdlog_error("Unable to allocate an RSA structure. %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto failed;
+ }
+ EVP_CIPHER_CTX_init(&ctx);
+
+ kdksize = sizeof(*kdk);
+ kdk = calloc(1, kdksize);
+ if (kdk == NULL) {
+ pjdlog_errno(LOG_ERR, "Unable to allocate kernel dump key");
+ goto failed;
+ }
+
+ size = read(kfd, kdk, kdksize);
+ if (size == (ssize_t)kdksize) {
+ kdksize += (size_t)kdk->kdk_encryptedkeysize;
+ kdk = realloc(kdk, kdksize);
+ if (kdk == NULL) {
+ pjdlog_errno(LOG_ERR, "Unable to reallocate kernel dump key");
+ goto failed;
+ }
+ size += read(kfd, &kdk->kdk_encryptedkey,
+ kdk->kdk_encryptedkeysize);
+ }
+ error = errno;
+ close(kfd);
+ kfd = -1;
+ if (size != (ssize_t)kdksize) {
+ errno = error;
+ pjdlog_errno(LOG_ERR, "Unable to read data from %s", keyfile);
+ goto failed;
+ }
+
+ privkey = PEM_read_RSAPrivateKey(fp, &privkey, NULL, NULL);
+ fclose(fp);
+ fp = NULL;
+ if (privkey == NULL) {
+ pjdlog_error("Unable to read data from %s.", privkeyfile);
+ goto failed;
+ }
+
+ privkeysize = RSA_size(privkey);
+ if (privkeysize != (int)kdk->kdk_encryptedkeysize) {
+ pjdlog_error("RSA modulus size mismatch: equals %db and should be %ub.",
+ 8 * privkeysize, 8 * kdk->kdk_encryptedkeysize);
+ goto failed;
+ }
+ if (RSA_private_decrypt(kdk->kdk_encryptedkeysize, kdk->kdk_encryptedkey,
+ key, privkey, RSA_PKCS1_PADDING) != sizeof(key)) {
+ pjdlog_error("Unable to decrypt key. %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto failed;
+ }
+ RSA_free(privkey);
+ privkey = NULL;
+
+ EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, kdk->kdk_iv);
+ EVP_CIPHER_CTX_set_key_length(&ctx, sizeof(key));
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+ bufused = 0;
+ while ((bytes = read(ifd, buf + bufused, sizeof(buf) - bufused)) > 0) {
+ bufused += bytes;
+ if (bufused != sizeof(buf))
+ continue;
+
+ if (EVP_DecryptUpdate(&ctx, buf, &olen, buf,
+ sizeof(buf)) == 0) {
+ pjdlog_error("Unable to decrypt core.");
+ goto failed;
+ }
+ PJDLOG_ASSERT(olen == (int)sizeof(buf));
+
+ if (write(ofd, buf, sizeof(buf)) != (ssize_t)sizeof(buf)) {
+ pjdlog_errno(LOG_ERR, "Unable to write data to %s",
+ output);
+ goto failed;
+ }
+ bufused = 0;
+ }
+ if (bytes < 0) {
+ pjdlog_errno(LOG_ERR, "Unable to read data from %s", input);
+ goto failed;
+ }
+
+ close(ofd);
+ close(ifd);
+ bzero(key, sizeof(key));
+ bzero(buf, sizeof(buf));
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ free(kdk);
+ exit(0);
+failed:
+ if (ofd >= 0)
+ close(ofd);
+ if (ifd >= 0)
+ close(kfd);
+ if (kfd >= 0)
+ close(kfd);
+ if (fp != NULL)
+ fclose(fp);
+ bzero(key, sizeof(key));
+ bzero(buf, sizeof(buf));
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ free(kdk);
+ RSA_free(privkey);
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ const char *input, *keyfile, *output, *rsakeyfile;
+ int debug;
+ char ch;
+ bool usesyslog;
+
+ pjdlog_init(PJDLOG_MODE_STD);
+ pjdlog_prefix_set("(decryptcore) ");
+
+ debug = 0;
+ rsakeyfile = NULL;
+ usesyslog = false;
+ while ((ch = getopt(argc, argv, "Li:k:o:p:v")) != -1) {
+ switch (ch) {
+ case 'L':
+ usesyslog = true;
+ break;
+ case 'i':
+ input = optarg;
+ break;
+ case 'k':
+ keyfile = optarg;
+ break;
+ case 'o':
+ output = optarg;
+ break;
+ case 'p':
+ rsakeyfile = optarg;
+ break;
+ case 'v':
+ debug++;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 0)
+ usage();
+ if (input == NULL || keyfile == NULL || output == NULL ||
+ rsakeyfile == NULL) {
+ usage();
+ }
+
+ if (usesyslog)
+ pjdlog_mode_set(PJDLOG_MODE_SYSLOG);
+ pjdlog_debug_set(debug);
+
+ if (!decrypt(rsakeyfile, keyfile, input, output)) {
+ if (unlink(output) != 0)
+ pjdlog_exit(1, "Unable to remove output");
+ exit(1);
+ }
+
+ pjdlog_fini();
+
+ return (0);
+}
Modified: soc2013/def/crashdump-head/sbin/dumpon/Makefile
==============================================================================
--- soc2013/def/crashdump-head/sbin/dumpon/Makefile Mon Oct 26 03:55:13 2015 (r293058)
+++ soc2013/def/crashdump-head/sbin/dumpon/Makefile Mon Oct 26 04:19:08 2015 (r293059)
@@ -1,6 +1,9 @@
# $FreeBSD$
PROG= dumpon
+
+LIBADD= crypto
+
MAN= dumpon.8
.include <bsd.prog.mk>
Modified: soc2013/def/crashdump-head/sbin/dumpon/dumpon.c
==============================================================================
--- soc2013/def/crashdump-head/sbin/dumpon/dumpon.c Mon Oct 26 03:55:13 2015 (r293058)
+++ soc2013/def/crashdump-head/sbin/dumpon/dumpon.c Mon Oct 26 04:19:08 2015 (r293059)
@@ -41,10 +41,16 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/capsicum.h>
#include <sys/param.h>
#include <sys/disk.h>
#include <sys/sysctl.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+
+#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
@@ -62,7 +68,7 @@
usage(void)
{
fprintf(stderr, "%s\n%s\n%s\n",
- "usage: dumpon [-v] special_file",
+ "usage: dumpon [-v] [-k public_key] special_file",
" dumpon [-v] off",
" dumpon [-v] -l");
exit(EX_USAGE);
@@ -95,6 +101,71 @@
}
static void
+genkey(const char *pubkeyfile, struct diocskerneldump_arg *kda)
+{
+ FILE *fp;
+ RSA *pubkey;
+
+ assert(pubkeyfile != NULL);
+ assert(kda != NULL);
+
+ fp = NULL;
+ pubkey = NULL;
+
+ fp = fopen(pubkeyfile, "r");
+ if (fp == NULL) {
+ warn("Unable to open %s", pubkeyfile);
+ goto failed;
+ }
+
+ if (cap_enter() == -1) {
+ warn("Unable to enter capability mode");
+ goto failed;
+ }
+
+ pubkey = RSA_new();
+ if (pubkey == NULL) {
+ warnx("Unable to allocate an RSA structure. %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto failed;
+ }
+
+ pubkey = PEM_read_RSA_PUBKEY(fp, &pubkey, NULL, NULL);
+ fclose(fp);
+ fp = NULL;
+ if (pubkey == NULL) {
+ warnx("Unable to read data from %s.", pubkeyfile);
+ goto failed;
+ }
+
+ kda->kda_encryptedkeysize = RSA_size(pubkey);
+ kda->kda_encryptedkey = calloc(1, kda->kda_encryptedkeysize);
+ if (kda->kda_encryptedkey == NULL) {
+ warn("Unable to allocate encrypted key");
+ goto failed;
+ }
+
+ arc4random_buf(kda->kda_key, sizeof(kda->kda_key));
+ if (RSA_public_encrypt(sizeof(kda->kda_key), kda->kda_key,
+ kda->kda_encryptedkey, pubkey,
+ RSA_PKCS1_PADDING) != (int)kda->kda_encryptedkeysize) {
+ warn("Unable to encrypt the one-time key");
+ goto failed;
+ }
+ RSA_free(pubkey);
+ pubkey = NULL;
+
+ kda->kda_encrypt = 1;
+ return;
+failed:
+ if (fp != NULL)
+ fclose(fp);
+ free(kda->kda_encryptedkey);
+ RSA_free(pubkey);
+ exit(1);
+}
+
+static void
listdumpdev(void)
{
char dumpdev[PATH_MAX];
@@ -123,13 +194,20 @@
int
main(int argc, char *argv[])
{
+ struct diocskerneldump_arg kda;
+ const char *pubkeyfile;
int ch;
int i, fd;
- u_int u;
int do_listdumpdev = 0;
- while ((ch = getopt(argc, argv, "lv")) != -1)
+ bzero(&kda, sizeof(kda));
+ pubkeyfile = NULL;
+
+ while ((ch = getopt(argc, argv, "k:lv")) != -1)
switch((char)ch) {
+ case 'k':
+ pubkeyfile = optarg;
+ break;
case 'l':
do_listdumpdev = 1;
break;
@@ -156,18 +234,22 @@
if (fd < 0)
err(EX_OSFILE, "%s", argv[0]);
check_size(fd, argv[0]);
- u = 0;
- i = ioctl(fd, DIOCSKERNELDUMP, &u);
- u = 1;
- i = ioctl(fd, DIOCSKERNELDUMP, &u);
+ kda.kda_enable = 0;
+ i = ioctl(fd, DIOCSKERNELDUMP, &kda);
+ if (pubkeyfile != NULL)
+ genkey(pubkeyfile, &kda);
+ kda.kda_enable = 1;
+ i = ioctl(fd, DIOCSKERNELDUMP, &kda);
+ free(kda.kda_encryptedkey);
+ bzero(&kda, sizeof(kda));
if (i == 0 && verbose)
printf("kernel dumps on %s\n", argv[0]);
} else {
fd = open(_PATH_DEVNULL, O_RDONLY);
if (fd < 0)
err(EX_OSFILE, "%s", _PATH_DEVNULL);
- u = 0;
- i = ioctl(fd, DIOCSKERNELDUMP, &u);
+ kda.kda_enable = 0;
+ i = ioctl(fd, DIOCSKERNELDUMP, &kda);
if (i == 0 && verbose)
printf("kernel dumps disabled\n");
}
Modified: soc2013/def/crashdump-head/sbin/savecore/savecore.c
==============================================================================
--- soc2013/def/crashdump-head/sbin/savecore/savecore.c Mon Oct 26 03:55:13 2015 (r293058)
+++ soc2013/def/crashdump-head/sbin/savecore/savecore.c Mon Oct 26 04:19:08 2015 (r293059)
@@ -185,7 +185,7 @@
}
static bool
-writekey(const char *keyname, struct kerneldumpkey *kdk)
+writekey(const char *keyname, uint8_t *dumpkey, uint32_t dumpkeysize)
{
int fd;
@@ -195,8 +195,7 @@
return (false);
}
- if (write(fd, kdk, kerneldumpkey_size(kdk)) !=
- (ssize_t)kerneldumpkey_size(kdk)) {
+ if (write(fd, dumpkey, dumpkeysize) != (ssize_t)dumpkeysize) {
syslog(LOG_ERR, "Unable to write the key to %s.", keyname);
close(fd);
return (false);
@@ -457,12 +456,12 @@
static void
DoFile(const char *savedir, const char *device)
{
- struct kerneldumpkey *kdk;
xo_handle_t *xostdout, *xoinfo;
static char infoname[PATH_MAX], corename[PATH_MAX], linkname[PATH_MAX];
static char keyname[PATH_MAX];
static char *buf = NULL;
struct kerneldumpheader kdhf, kdhl;
+ uint8_t *dumpkey;
off_t mediasize, dumpsize, firsthd, lasthd;
FILE *info, *fp;
mode_t oumask;
@@ -709,24 +708,24 @@
isencrypted = false;
if (dumpkeysize > 0) {
isencrypted = true;
- kdk = (struct kerneldumpkey *)calloc(1, dumpkeysize);
- if (kdk == NULL) {
+ dumpkey = calloc(1, dumpkeysize);
+ if (dumpkey == NULL) {
syslog(LOG_ERR, "Unable to allocate kernel dump key.");
nerr++;
goto closefd;
}
- error = read(fd, kdk, dumpkeysize);
+ error = read(fd, dumpkey, dumpkeysize);
if (error != (int)dumpkeysize) {
syslog(LOG_ERR, "Unable to read kernel dump key.");
nerr++;
- goto closefd;
+ goto closeall;
}
snprintf(keyname, sizeof(keyname), "key.%d", bounds);
- if (!writekey(keyname, kdk)) {
+ if (!writekey(keyname, dumpkey, dumpkeysize)) {
nerr++;
- goto closefd;
+ goto closeall;
}
}
Modified: soc2013/def/crashdump-head/sys/amd64/amd64/minidump_machdep.c
==============================================================================
--- soc2013/def/crashdump-head/sys/amd64/amd64/minidump_machdep.c Mon Oct 26 03:55:13 2015 (r293058)
+++ soc2013/def/crashdump-head/sys/amd64/amd64/minidump_machdep.c Mon Oct 26 04:19:08 2015 (r293059)
@@ -321,13 +321,13 @@
/* Determine dump offset on device. */
if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2 +
- kerneldumpkey_size(di->kdk)) {
+ kerneldumpcrypto_dumpkeysize(di->kdc)) {
error = E2BIG;
goto fail;
}
dumplo = di->mediaoffset + di->mediasize - dumpsize;
dumplo -= sizeof(kdh) * 2;
- dumplo -= kerneldumpkey_size(di->kdk);
+ dumplo -= kerneldumpcrypto_dumpkeysize(di->kdc);
progress = dumpsize;
/* Initialize mdhdr */
@@ -342,7 +342,7 @@
mdhdr.dmapend = DMAP_MAX_ADDRESS;
mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_AMD64_VERSION, dumpsize,
- kerneldumpkey_size(di->kdk), di->blocksize);
+ kerneldumpcrypto_dumpkeysize(di->kdc), di->blocksize);
printf("Dumping %llu out of %ju MB:", (long long)dumpsize >> 20,
ptoa((uintmax_t)physmem) / 1048576);
@@ -354,10 +354,10 @@
dumplo += sizeof(kdh);
/* Dump key */
- error = dump_write_key(di, di->kdk, 0, dumplo);
+ error = dump_write_key(di, 0, dumplo);
if (error)
goto fail;
- dumplo += kerneldumpkey_size(di->kdk);
+ dumplo += kerneldumpcrypto_dumpkeysize(di->kdc);
/* Dump my header */
bzero(&fakepd, sizeof(fakepd));
Modified: soc2013/def/crashdump-head/sys/ddb/db_textdump.c
==============================================================================
--- soc2013/def/crashdump-head/sys/ddb/db_textdump.c Mon Oct 26 03:55:13 2015 (r293058)
+++ soc2013/def/crashdump-head/sys/ddb/db_textdump.c Mon Oct 26 04:19:08 2015 (r293059)
@@ -427,7 +427,7 @@
void
textdump_dumpsys(struct dumperinfo *di)
{
- struct kerneldumpkey *kdk;
+ struct kerneldumpcrypto *kdc;
off_t dumplen, trailer_offset;
if (di->blocksize != TEXTDUMP_BLOCKSIZE) {
@@ -452,8 +452,8 @@
/*
* Disable EKCD because we don't provide encrypted textdumps.
*/
- kdk = di->kdk;
- di->kdk = NULL;
+ kdc = di->kdc;
+ di->kdc = NULL;
/*
* Position the start of the dump so that we'll write the kernel dump
@@ -511,7 +511,7 @@
/*
* Restore EKCD status.
*/
- di->kdk = kdk;
+ di->kdc = kdc;
}
/*-
Modified: soc2013/def/crashdump-head/sys/dev/null/null.c
==============================================================================
--- soc2013/def/crashdump-head/sys/dev/null/null.c Mon Oct 26 03:55:13 2015 (r293058)
+++ soc2013/def/crashdump-head/sys/dev/null/null.c Mon Oct 26 04:19:08 2015 (r293059)
@@ -109,7 +109,7 @@
switch (cmd) {
case DIOCSKERNELDUMP:
- error = set_dumper(NULL, NULL, td);
+ error = set_dumper(NULL, NULL, td, 0, NULL, 0, NULL);
break;
case FIONBIO:
break;
Modified: soc2013/def/crashdump-head/sys/geom/geom_dev.c
==============================================================================
--- soc2013/def/crashdump-head/sys/geom/geom_dev.c Mon Oct 26 03:55:13 2015 (r293058)
+++ soc2013/def/crashdump-head/sys/geom/geom_dev.c Mon Oct 26 04:19:08 2015 (r293059)
@@ -127,26 +127,32 @@
}
static int
-g_dev_setdumpdev(struct cdev *dev, struct thread *td)
+g_dev_setdumpdev(struct cdev *dev, struct diocskerneldump_arg *kda,
+ struct thread *td)
{
struct g_kerneldump kd;
struct g_consumer *cp;
int error, len;
if (dev == NULL)
- return (set_dumper(NULL, NULL, td));
+ return (set_dumper(NULL, NULL, td, 0, NULL, 0, NULL));
cp = dev->si_drv2;
len = sizeof(kd);
kd.offset = 0;
kd.length = OFF_MAX;
error = g_io_getattr("GEOM::kerneldump", cp, &len, &kd);
- if (error == 0) {
- error = set_dumper(&kd.di, devtoname(dev), td);
- if (error == 0)
- dev->si_flags |= SI_DUMPDEV;
- }
- return (error);
+ if (error != 0)
+ return (error);
+
+ error = set_dumper(&kd.di, devtoname(dev), td, kda->kda_encrypt,
+ kda->kda_key, kda->kda_encryptedkeysize,
+ kda->kda_encryptedkey);
+ if (error != 0)
+ return (error);
+
+ dev->si_flags |= SI_DUMPDEV;
+ return (0);
}
static void
@@ -157,7 +163,7 @@
return;
if (strcmp(devtoname(dev), dumpdev) != 0)
return;
- if (g_dev_setdumpdev(dev, curthread) == 0) {
+ if (g_dev_setdumpdev(dev, NULL, curthread) == 0) {
freeenv(dumpdev);
dumpdev = NULL;
}
@@ -459,12 +465,15 @@
case DIOCGFRONTSTUFF:
error = g_io_getattr("GEOM::frontstuff", cp, &i, data);
break;
- case DIOCSKERNELDUMP:
- if (*(u_int *)data == 0)
- error = g_dev_setdumpdev(NULL, td);
+ case DIOCSKERNELDUMP: {
+ struct diocskerneldump_arg *kda;
+ kda = (struct diocskerneldump_arg *)data;
+ if (kda->kda_enable == 0)
+ error = g_dev_setdumpdev(NULL, NULL, td);
else
- error = g_dev_setdumpdev(dev, td);
+ error = g_dev_setdumpdev(dev, kda, td);
break;
+ }
case DIOCGFLUSH:
error = g_io_flush(cp);
break;
@@ -681,7 +690,7 @@
/* Reset any dump-area set on this device */
if (dev->si_flags & SI_DUMPDEV)
- (void)set_dumper(NULL, NULL, curthread);
+ (void)set_dumper(NULL, NULL, curthread, 0, NULL, 0, NULL);
/* Destroy the struct cdev *so we get no more requests */
destroy_dev_sched_cb(dev, g_dev_callback, cp);
Modified: soc2013/def/crashdump-head/sys/kern/kern_dump.c
==============================================================================
--- soc2013/def/crashdump-head/sys/kern/kern_dump.c Mon Oct 26 03:55:13 2015 (r293058)
+++ soc2013/def/crashdump-head/sys/kern/kern_dump.c Mon Oct 26 04:19:08 2015 (r293059)
@@ -349,16 +349,16 @@
/* Determine dump offset on device. */
if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2 +
- kerneldumpkey_size(di->kdk)) {
+ kerneldumpcrypto_dumpkeysize(di->kdc)) {
error = ENOSPC;
goto fail;
}
dumplo = di->mediaoffset + di->mediasize - dumpsize;
dumplo -= sizeof(kdh) * 2;
- dumplo -= kerneldumpkey_size(di->kdk);
+ dumplo -= kerneldumpcrypto_dumpkeysize(di->kdc);
mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARCH_VERSION, dumpsize,
- kerneldumpkey_size(di->kdk), di->blocksize);
+ kerneldumpcrypto_dumpkeysize(di->kdc), di->blocksize);
printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20,
ehdr.e_phnum - DUMPSYS_NUM_AUX_HDRS);
@@ -370,10 +370,10 @@
dumplo += sizeof(kdh);
/* Dump key */
- error = dump_write_key(di, di->kdk, 0, dumplo);
+ error = dump_write_key(di, 0, dumplo);
if (error)
goto fail;
- dumplo += kerneldumpkey_size(di->kdk);
+ dumplo += kerneldumpcrypto_dumpkeysize(di->kdc);
/* Dump ELF header */
error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr));
Modified: soc2013/def/crashdump-head/sys/kern/kern_shutdown.c
==============================================================================
--- soc2013/def/crashdump-head/sys/kern/kern_shutdown.c Mon Oct 26 03:55:13 2015 (r293058)
+++ soc2013/def/crashdump-head/sys/kern/kern_shutdown.c Mon Oct 26 04:19:08 2015 (r293059)
@@ -144,29 +144,18 @@
#ifdef EKCD
FEATURE(ekcd, "Encrypted kernel crash dumps support");
-MALLOC_DEFINE(M_KDK, "kerneldumpkey", "Kernel dump key structure");
+MALLOC_DEFINE(M_EKCD, "ekcd", "Encrypted kernel crash dumps data");
-static struct kerneldumpcrypto {
- uint8_t kdc_key[KERNELDUMP_KEY_SIZE];
+struct kerneldumpcrypto {
+ uint8_t kdc_algorithm;
uint8_t kdc_iv[KERNELDUMP_IV_SIZE];
keyInstance kdc_ki;
cipherInstance kdc_ci;
off_t kdc_nextoffset;
-} dumpcrypto;
-
-static struct kerneldumpkey *dumpkey;
-
-static int kerneldump_sysctl_enable(SYSCTL_HANDLER_ARGS);
-static int kerneldump_sysctl_setup(SYSCTL_HANDLER_ARGS);
-
-SYSCTL_NODE(_security, OID_AUTO, ekcd, CTLFLAG_RW, 0,
- "Encrypted kernel crash dumps");
-
-SYSCTL_PROC(_security_ekcd, OID_AUTO, enable, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
- kerneldump_sysctl_enable, "I", "Enable encrypted kernel crash dumps");
-
-SYSCTL_PROC(_security_ekcd, OID_AUTO, setup, CTLTYPE_OPAQUE | CTLFLAG_WR, NULL,
- 0, kerneldump_sysctl_setup, "", "Setup");
+ uint8_t kdc_dumpkeysize;
+ uint32_t kdc_encryptedkeysize;
+ uint8_t kdc_encryptedkey[];
+};
#endif /* EKCD */
/*
@@ -854,108 +843,66 @@
printf("done\n");
}
+static char dumpdevname[sizeof(((struct cdev*)NULL)->si_name)];
+SYSCTL_STRING(_kern_shutdown, OID_AUTO, dumpdevname, CTLFLAG_RD,
+ dumpdevname, 0, "Device for kernel dumps");
+
#ifdef EKCD
-static int
-kerneldump_crypto_init(struct dumperinfo *di, struct kerneldumpcrypto *kdc,
- struct kerneldumpkey *kdk)
+static struct kerneldumpcrypto *
+kerneldumpcrypto_create(uint8_t *key, uint32_t encryptedkeysize,
+ uint8_t *encryptedkey)
{
+ struct kerneldumpcrypto *kdc;
int error;
+ kdc = malloc(sizeof(*kdc) + encryptedkeysize, M_EKCD,
+ M_WAITOK | M_ZERO);
+
+ kdc->kdc_algorithm = CRYPTO_AES_CBC;
error = rijndael_makeKey(&kdc->kdc_ki, DIR_ENCRYPT,
- 8 * KERNELDUMP_KEY_SIZE, kdc->kdc_key);
+ 8 * KERNELDUMP_KEY_SIZE, key);
+ bzero(key, KERNELDUMP_KEY_SIZE);
if (error <= 0)
- return (EINVAL);
+ goto failed;
+ arc4rand(kdc->kdc_iv, sizeof(kdc->kdc_iv), 0);
error = rijndael_cipherInit(&kdc->kdc_ci, MODE_CBC, kdc->kdc_iv);
if (error <= 0)
- return (EINVAL);
-
- kdc->kdc_nextoffset = 0;
+ goto failed;
- di->kdc = kdc;
- di->kdk = kdk;
+ kdc->kdc_encryptedkeysize = encryptedkeysize;
+ bcopy(encryptedkey, kdc->kdc_encryptedkey, kdc->kdc_encryptedkeysize);
- return (0);
-}
-
-static int
-kerneldump_sysctl_enable(SYSCTL_HANDLER_ARGS)
-{
- int enable, error;
-
- if (dumper.kdk != NULL)
- enable = 1;
- else
- enable = 0;
-
- error = sysctl_handle_opaque(oidp, &enable, sizeof(enable), req);
- if (error != 0)
- return (error);
-
- if (enable == 0) {
- free(dumpkey, M_KDK);
- dumpkey = NULL;
- dumper.kdk = NULL;
- }
-
- return (0);
+ kdc->kdc_nextoffset = 0;
+ kdc->kdc_dumpkeysize = (sizeof(kdc->kdc_algorithm) +
+ sizeof(kdc->kdc_iv) + sizeof(kdc->kdc_encryptedkeysize) +
+ kdc->kdc_encryptedkeysize + KERNELDUMP_BLOCK_SIZE - 1) /
+ KERNELDUMP_BLOCK_SIZE * KERNELDUMP_BLOCK_SIZE;
+ kdc->kdc_dumpkeysize = (sizeof(struct kerneldumpkey) +
+ kdc->kdc_encryptedkeysize + KERNELDUMP_BLOCK_SIZE - 1) /
+ KERNELDUMP_BLOCK_SIZE * KERNELDUMP_BLOCK_SIZE;
+
+ return (kdc);
+failed:
+ free(kdc, M_EKCD);
+ return (NULL);
}
+#endif /* EKCD */
-static int
-kerneldump_sysctl_setup(SYSCTL_HANDLER_ARGS)
+uint32_t
+kerneldumpcrypto_dumpkeysize(const struct kerneldumpcrypto *kdc)
{
- struct kerneldumpsetup kds;
- struct kerneldumpkey *kdk;
- size_t kdksize;
- int error;
-
- if (req->newptr == NULL)
- return (EPERM);
-
- error = sysctl_handle_opaque(oidp, &kds, sizeof(kds), req);
- if (error != 0)
- return (error);
- bcopy(kds.kds_key, dumpcrypto.kdc_key, sizeof(dumpcrypto.kdc_key));
- bzero(kds.kds_key, sizeof(kds.kds_key));
- arc4rand(dumpcrypto.kdc_iv, sizeof(dumpcrypto.kdc_iv), 0);
-
- kdksize = ((sizeof(*kdk) + kds.kds_encryptedkeylen +
- KERNELDUMP_BLOCK_SIZE - 1) / KERNELDUMP_BLOCK_SIZE) *
- KERNELDUMP_BLOCK_SIZE;
- kdk = malloc(kdksize, M_KDK, M_WAITOK | M_ZERO);
- kdk->kdk_size = kdksize;
- kdk->kdk_algorithm = CRYPTO_AES_CBC;
- kdk->kdk_keysize = KERNELDUMP_KEY_SIZE;
- bcopy(dumpcrypto.kdc_iv, kdk->kdk_iv, sizeof(kdk->kdk_iv));
- kdk->kdk_encryptedkeylen = kds.kds_encryptedkeylen;
-
- error = sysctl_handle_opaque(oidp, kdk->kdk_encryptedkey,
- kdk->kdk_encryptedkeylen, req);
- if (error != 0) {
- free(kdk, M_KDK);
- return (error);
- }
-
- error = kerneldump_crypto_init(&dumper, &dumpcrypto, kdk);
- if (error != 0) {
- free(kdk, M_KDK);
- return (error);
- }
-
- free(dumpkey, M_KDK);
- dumpkey = kdk;
- return (0);
+ if (kdc == NULL)
+ return (0);
+ return (kdc->kdc_dumpkeysize);
}
-#endif /* EKCD */
-
-static char dumpdevname[sizeof(((struct cdev*)NULL)->si_name)];
-SYSCTL_STRING(_kern_shutdown, OID_AUTO, dumpdevname, CTLFLAG_RD,
- dumpdevname, 0, "Device for kernel dumps");
/* Registration of dumpers */
int
-set_dumper(struct dumperinfo *di, const char *devname, struct thread *td)
+set_dumper(struct dumperinfo *di, const char *devname, struct thread *td,
+ uint8_t encrypt, uint8_t *key, uint32_t encryptedkeysize,
+ uint8_t *encryptedkey)
{
size_t wantcopy;
int error;
@@ -965,6 +912,7 @@
return (error);
if (di == NULL) {
+ free(dumper.kdc, M_EKCD);
bzero(&dumper, sizeof dumper);
dumpdevname[0] = '\0';
return (0);
@@ -973,12 +921,14 @@
return (EBUSY);
dumper = *di;
dumper.kdc = NULL;
- dumper.kdk = NULL;
#ifdef EKCD
- error = kerneldump_crypto_init(&dumper, &dumpcrypto, dumpkey);
- if (error != 0)
- return (error);
+ if (encrypt == 1) {
+ dumper.kdc = kerneldumpcrypto_create(key, encryptedkeysize,
+ encryptedkey);
+ if (dumper.kdc == NULL)
+ return (EINVAL);
+ }
#endif
wantcopy = strlcpy(dumpdevname, devname, sizeof(dumpdevname));
@@ -986,6 +936,7 @@
printf("set_dumper: device name truncated from '%s' -> '%s'\n",
devname, dumpdevname);
}
+
return (0);
}
@@ -1090,7 +1041,7 @@
{
#ifdef EKCD
- if (di->kdk != NULL) {
+ if (di->kdc != NULL) {
return (dump_encrypted_write(di, virtual, physical, offset,
length));
}
@@ -1108,12 +1059,26 @@
}
int
-dump_write_key(struct dumperinfo *di, struct kerneldumpkey *kdk,
- vm_offset_t physical, off_t offset)
+dump_write_key(struct dumperinfo *di, vm_offset_t physical, off_t offset)
{
+ struct kerneldumpcrypto *kdc;
+ struct kerneldumpkey *kdk;
+ int ret;
+
+ kdc = di->kdc;
+ if (kdc == NULL)
+ return (0);
- return (dump_raw_write(di, kdk, physical, offset,
- kerneldumpkey_size(kdk)));
+ kdk = malloc(kdc->kdc_dumpkeysize, M_EKCD, M_WAITOK | M_ZERO);
+ kdk->kdk_algorithm = kdc->kdc_algorithm;
+ bcopy(kdc->kdc_iv, kdk->kdk_iv, sizeof(kdk->kdk_iv));
+ kdk->kdk_encryptedkeysize = kdc->kdc_encryptedkeysize;
+ bcopy(kdc->kdc_encryptedkey, kdk->kdk_encryptedkey,
+ kdk->kdk_encryptedkeysize);
+
+ ret = dump_raw_write(di, kdk, physical, offset, kdc->kdc_dumpkeysize);
+ free(kdk, M_EKCD);
+ return (ret);
}
void
Modified: soc2013/def/crashdump-head/sys/sys/conf.h
==============================================================================
--- soc2013/def/crashdump-head/sys/sys/conf.h Mon Oct 26 03:55:13 2015 (r293058)
+++ soc2013/def/crashdump-head/sys/sys/conf.h Mon Oct 26 04:19:08 2015 (r293059)
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-soc-all
mailing list