Date: Sun, 28 Jul 2013 17:49:06 GMT From: def@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r255272 - in soc2013/def/crashdump-head: sbin/savecore sys/kern sys/sys Message-ID: <201307281749.r6SHn6sq072534@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: def Date: Sun Jul 28 17:49:06 2013 New Revision: 255272 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=255272 Log: Save a decrypted crash dump using funopen(3). Encrypt with offset set to 0 in the beginning. Added: soc2013/def/crashdump-head/sbin/savecore/decryptfile.c soc2013/def/crashdump-head/sbin/savecore/decryptfile.h Modified: soc2013/def/crashdump-head/sbin/savecore/Makefile soc2013/def/crashdump-head/sbin/savecore/savecore.c soc2013/def/crashdump-head/sys/kern/kern_shutdown.c soc2013/def/crashdump-head/sys/sys/conf.h Modified: soc2013/def/crashdump-head/sbin/savecore/Makefile ============================================================================== --- soc2013/def/crashdump-head/sbin/savecore/Makefile Sun Jul 28 17:24:37 2013 (r255271) +++ soc2013/def/crashdump-head/sbin/savecore/Makefile Sun Jul 28 17:49:06 2013 (r255272) @@ -4,7 +4,7 @@ .PATH: ${SYS}/crypto/camellia ${SYS}/crypto/rijndael ${SYS}/crypto PROG= savecore -SRCS= ${PROG}.c +SRCS= ${PROG}.c decryptfile.c SRCS+= rijndael-api.c rijndael-api-fst.c rijndael-alg-fst.c SRCS+= camellia.c SRCS+= xts.c Added: soc2013/def/crashdump-head/sbin/savecore/decryptfile.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2013/def/crashdump-head/sbin/savecore/decryptfile.c Sun Jul 28 17:49:06 2013 (r255272) @@ -0,0 +1,99 @@ +#include <sys/param.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "decryptfile.h" + +int +dwrite(void *cookie, const char *data, int size) +{ + decFile *fd = (decFile *)cookie; + int resid, saved; + + saved = 0; + + while (size + fd->buf_used >= PEFS_SECTOR_SIZE) { + resid = PEFS_SECTOR_SIZE - fd->buf_used; + memcpy(fd->buf + fd->buf_used, data, resid); + fd->buf_used += resid; + + xts_block_decrypt(&xts_alg_aes, (struct xts_ctx *)&fd->tweak_ctx, (struct xts_ctx *)&fd->data_ctx, + fd->offset, fd->tweak, PEFS_SECTOR_SIZE, + fd->buf, fd->buf); + + if (fwrite(fd->buf, 1, PEFS_SECTOR_SIZE, fd->fp) != PEFS_SECTOR_SIZE) + return (0); + + data += resid; + size -= resid; + fd->buf_used = 0; + fd->offset += PEFS_SECTOR_SIZE; + saved += resid; + } + + if (size > 0) { + memcpy(fd->buf + fd->buf_used, data, size); + fd->buf_used += size; + saved += size; + } + + return (saved); +} + +FILE * +dopen(const char *fname, const char *mode, const struct kerneldumpheader *h) +{ + decFile *fd; + FILE *fp; + + /* Currently other modes are not implemented. */ + if (*mode != 'w') + return (NULL); + + fp = fopen(fname, mode); + + if (fp == NULL) + return (NULL); + + fd = (decFile *)malloc(sizeof(decFile)); + fd->fp = fp; + fd->keysize = h->keysize; + memcpy(fd->key, h->key, KERNELDUMP_KEY_SIZE); + fd->tweaksize = h->tweaksize; + memcpy(fd->tweak, h->tweak, KERNELDUMP_TWEAK_SIZE); + fd->offset = 0; + fd->buf_used = 0; + + rijndael_set_key(&fd->tweak_ctx, fd->key, fd->keysize << 3); + rijndael_set_key(&fd->data_ctx, fd->key, fd->keysize << 3); + + return (funopen(fd, NULL, dwrite, NULL, dclose)); +} + +int +dclose(void *cookie) +{ + decFile *fd = (decFile *)cookie; + int error; + + if (fd->buf_used > 0) { + xts_block_decrypt(&xts_alg_aes, (struct xts_ctx *)&fd->tweak_ctx, (struct xts_ctx *)&fd->data_ctx, + fd->offset, fd->tweak, fd->buf_used, + fd->buf, fd->buf); + + if (fwrite(fd->buf, 1, fd->buf_used, fd->fp) != 1) + return (0); + + fd->offset += fd->buf_used; + fd->buf_used = 0; + } + + error = fclose(fd->fp); + + if (error < 0) + return (error); + + free(fd); + + return (error); +} Added: soc2013/def/crashdump-head/sbin/savecore/decryptfile.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2013/def/crashdump-head/sbin/savecore/decryptfile.h Sun Jul 28 17:49:06 2013 (r255272) @@ -0,0 +1,25 @@ +#ifndef _FILEDECRYPT_H +#define _FILEDECRYPT_H + +#include <sys/kerneldump.h> +#include <crypto/xts.h> + +typedef struct _decFile { + FILE *fp; + int keysize; + char key[KERNELDUMP_KEY_SIZE]; + int tweaksize; + char tweak[KERNELDUMP_TWEAK_SIZE]; + rijndael_ctx tweak_ctx; + rijndael_ctx data_ctx; + off_t offset; +#define PEFS_SECTOR_SIZE 4096 + char buf[PEFS_SECTOR_SIZE]; + int buf_used; +} decFile; + +int dwrite(void *cookie, const char *data, int size); +FILE *dopen(const char *fname, const char *mode, const struct kerneldumpheader *h); +int dclose(void *cookie); + +#endif /* _FILEDECRYPT_H */ Modified: soc2013/def/crashdump-head/sbin/savecore/savecore.c ============================================================================== --- soc2013/def/crashdump-head/sbin/savecore/savecore.c Sun Jul 28 17:24:37 2013 (r255271) +++ soc2013/def/crashdump-head/sbin/savecore/savecore.c Sun Jul 28 17:49:06 2013 (r255272) @@ -68,7 +68,6 @@ #include <sys/kerneldump.h> #include <sys/mount.h> #include <sys/stat.h> -#include <crypto/xts.h> #include <errno.h> #include <fcntl.h> #include <fstab.h> @@ -81,6 +80,7 @@ #include <syslog.h> #include <time.h> #include <unistd.h> +#include "decryptfile.h" /* The size of the buffer used for I/O. */ #define BUFFERSIZE (1024*1024) @@ -89,7 +89,7 @@ #define STATUS_GOOD 1 #define STATUS_UNKNOWN 2 -static int checkfor, compress, clear, force, keep, verbose; /* flags */ +static int checkfor, compress, clear, decrypt, force, keep, verbose; /* flags */ static int nfound, nsaved, nerr; /* statistics */ static int maxdumps; @@ -292,22 +292,16 @@ static int DoRegularFile(int fd, off_t dumpsize, char *buf, const char *device, - const char *filename, FILE *fp, FILE *fp_enc, struct kerneldumpheader *kdh, - off_t offset) + const char *filename, FILE *fp) { int he, hs, nr, nw, wl; off_t dmpcnt, origsize; - rijndael_ctx tweak_ctx, data_ctx; - - rijndael_set_key(&tweak_ctx, kdh->key, kdh->keysize << 3); - rijndael_set_key(&data_ctx, kdh->key, kdh->keysize << 3); dmpcnt = 0; origsize = dumpsize; he = 0; while (dumpsize > 0) { - // wl = BUFFERSIZE; - wl = 512; + wl = BUFFERSIZE; if (wl > dumpsize) wl = dumpsize; nr = read(fd, buf, wl); @@ -322,6 +316,8 @@ } if (compress) { nw = fwrite(buf, 1, wl, fp); + } else if (decrypt) { + nw = fwrite(buf, 1, wl, fp); } else { for (nw = 0; nw < nr; nw = he) { /* find a contiguous block of zeroes */ @@ -352,18 +348,10 @@ * If hs > nw, buf[nw..hs] contains non-zero data. * If he > hs, buf[hs..he] is all zeroes. */ - if (hs > nw) { - if (fwrite(buf + nw, hs - nw, 1, fp_enc) - != 1) - break; - xts_block_decrypt(&xts_alg_aes, (struct xts_ctx *)&tweak_ctx, (struct xts_ctx *)&data_ctx, - offset, kdh->tweak, hs - nw, - buf + nw, buf + nw); - offset += hs - nw; + if (hs > nw) if (fwrite(buf + nw, hs - nw, 1, fp) != 1) break; - } if (he > hs) if (fseeko(fp, he - hs, SEEK_CUR) == -1) break; @@ -447,12 +435,11 @@ static void DoFile(const char *savedir, const char *device) { - static char infoname[PATH_MAX], corename[PATH_MAX], - corename_enc[PATH_MAX], linkname[PATH_MAX]; + static char infoname[PATH_MAX], corename[PATH_MAX], linkname[PATH_MAX]; static char *buf = NULL; struct kerneldumpheader kdhf, kdhl; off_t mediasize, dumpsize, firsthd, lasthd; - FILE *info, *fp, *fp_enc; + FILE *info, *fp; mode_t oumask; int fd, fdinfo, error; int bounds, status; @@ -645,15 +632,16 @@ snprintf(corename, sizeof(corename), "%s.%d.gz", istextdump ? "textdump.tar" : "vmcore", bounds); fp = zopen(corename, "w"); - } else { + } else if (decrypt) { snprintf(corename, sizeof(corename), "%s.%d", istextdump ? "textdump.tar" : "vmcore", bounds); - snprintf(corename_enc, sizeof(corename_enc), "%s_encrypted.%d", + fp = dopen(corename, "w", &kdhl); + } else { + snprintf(corename, sizeof(corename), "%s.%d", istextdump ? "textdump.tar" : "vmcore", bounds); fp = fopen(corename, "w"); - fp_enc = fopen(corename_enc, "w"); } - if (fp == NULL || fp_enc == NULL) { + if (fp == NULL) { syslog(LOG_ERR, "%s: %m", corename); close(fdinfo); nerr++; @@ -676,15 +664,14 @@ fclose(info); syslog(LOG_NOTICE, "writing %score to %s/%s", - compress ? "compressed " : "", savedir, corename); + compress ? "compressed " : (decrypt ? "decrypted " : ""), savedir, corename); if (istextdump) { if (DoTextdumpFile(fd, dumpsize, lasthd, buf, device, corename, fp) < 0) goto closeall; } else { - if (DoRegularFile(fd, dumpsize, buf, device, corename, - fp, fp_enc, &kdhl, firsthd + sizeof(kdhf)) + if (DoRegularFile(fd, dumpsize, buf, device, corename, fp) < 0) goto closeall; } @@ -697,12 +684,6 @@ goto closeall; } - if (fp_enc != NULL && fclose(fp_enc) < 0) { - syslog(LOG_ERR, "error on %s: %m", corename_enc); - nerr++; - goto closeall; - } - symlinks_remove(); if (symlink(infoname, "info.last") == -1) { syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", @@ -711,6 +692,9 @@ if (compress) { snprintf(linkname, sizeof(linkname), "%s.last.gz", istextdump ? "textdump.tar" : "vmcore"); + } else if (decrypt) { + snprintf(linkname, sizeof(linkname), "%s.last", + istextdump ? "textdump.tar" : "vmcore"); } else { snprintf(linkname, sizeof(linkname), "%s.last", istextdump ? "textdump.tar" : "vmcore"); @@ -741,7 +725,6 @@ closeall: fclose(fp); - fclose(fp_enc); closefd: close(fd); @@ -753,7 +736,7 @@ fprintf(stderr, "%s\n%s\n%s\n", "usage: savecore -c [-v] [device ...]", " savecore -C [-v] [device ...]", - " savecore [-fkvz] [-m maxdumps] [directory [device ...]]"); + " savecore [-dfkvz] [-m maxdumps] [directory [device ...]]"); exit(1); } @@ -764,13 +747,13 @@ struct fstab *fsp; int i, ch, error; - checkfor = compress = clear = force = keep = verbose = 0; + checkfor = compress = clear = decrypt = force = keep = verbose = 0; nfound = nsaved = nerr = 0; openlog("savecore", LOG_PERROR, LOG_DAEMON); signal(SIGINFO, infohandler); - while ((ch = getopt(argc, argv, "Ccfkm:vz")) != -1) + while ((ch = getopt(argc, argv, "Ccdfkm:vz")) != -1) switch(ch) { case 'C': checkfor = 1; @@ -778,6 +761,9 @@ case 'c': clear = 1; break; + case 'd': + decrypt = 1; + break; case 'f': force = 1; break; Modified: soc2013/def/crashdump-head/sys/kern/kern_shutdown.c ============================================================================== --- soc2013/def/crashdump-head/sys/kern/kern_shutdown.c Sun Jul 28 17:24:37 2013 (r255271) +++ soc2013/def/crashdump-head/sys/kern/kern_shutdown.c Sun Jul 28 17:49:06 2013 (r255272) @@ -880,8 +880,9 @@ } /* Write kernel dump headers. */ - if (di->offset == 0 || offset == di->kdhoffset) { - di->offset = offset + length; + if (di->realoffset == 0 || offset == di->mediaoffset + di->mediasize - + sizeof(struct kerneldumpheader)) { + di->realoffset = offset + length; return (di->dumper(di->priv, virtual, physical, offset, length)); } @@ -890,28 +891,28 @@ xts_block_encrypt(&xts_alg_aes, di->tweak_ctx, di->data_ctx, di->offset, di->tweak, di->buf_used, di->buf, di->buf); - return (di->dumper(di->priv, di->buf, physical, di->offset, di->buf_used)); + return (di->dumper(di->priv, di->buf, physical, di->realoffset, di->buf_used)); } - offset = di->offset; - - while (length + di->buf_used >= di->blocksize) { - resid = qmin(length, di->blocksize - di->buf_used); + while (length + di->buf_used >= DUMPER_BUFSIZE) { + resid = DUMPER_BUFSIZE - di->buf_used; memcpy(di->buf + di->buf_used, virtual, resid); di->buf_used += resid; + xts_block_encrypt(&xts_alg_aes, di->tweak_ctx, di->data_ctx, - offset, di->tweak, di->blocksize, + di->offset, di->tweak, DUMPER_BUFSIZE, di->buf, di->buf); - error = (di->dumper(di->priv, di->buf, physical, offset, di->buf_used)); + + error = (di->dumper(di->priv, di->buf, physical, di->realoffset, DUMPER_BUFSIZE)); if (error) return (error); virtual = (void *)((char *)virtual + resid); - offset += resid; length -= resid; di->buf_used = 0; - di->offset = offset; + di->realoffset += resid; + di->offset += DUMPER_BUFSIZE; } /* We still have less than blocksize of data to dump. */ @@ -933,8 +934,8 @@ di->tweak_ctx = &dumper_tweak_ctx; di->data_ctx = &dumper_data_ctx; di->buf_used = 0; + di->realoffset = 0; di->offset = 0; - di->kdhoffset = 0; rijndael_set_key(di->tweak_ctx, di->key, KERNELDUMP_KEY_SIZE << 3); rijndael_set_key(di->data_ctx, di->key, KERNELDUMP_KEY_SIZE << 3); } @@ -961,6 +962,4 @@ kdh->tweaksize = KERNELDUMP_TWEAK_SIZE; strncpy(kdh->tweak, dumper.tweak, kdh->tweaksize); kdh->parity = kerneldump_parity(kdh); - - dumper.kdhoffset = dumper.mediaoffset + dumper.mediasize - sizeof(*kdh); } Modified: soc2013/def/crashdump-head/sys/sys/conf.h ============================================================================== --- soc2013/def/crashdump-head/sys/sys/conf.h Sun Jul 28 17:24:37 2013 (r255271) +++ soc2013/def/crashdump-head/sys/sys/conf.h Sun Jul 28 17:49:06 2013 (r255272) @@ -323,22 +323,23 @@ EVENTHANDLER_DECLARE(dev_clone, dev_clone_fn); /* Stuff relating to kernel-dump */ +#define DUMPER_BUFSIZE 4096 struct dumperinfo { - dumper_t *dumper; /* Dumping function. */ - void *priv; /* Private parts. */ - u_int blocksize; /* Size of block in bytes. */ - u_int maxiosize; /* Max size allowed for an individual I/O */ - off_t mediaoffset; /* Initial offset in bytes. */ - off_t mediasize; /* Space available in bytes. */ - char *key; /* Key information. */ - char *tweak; /* Tweak. */ - void *tweak_ctx; /* Tweak context. */ - void *data_ctx; /* Data context. */ - uint8_t buf[512]; /* Raw data buffer. */ - u_int buf_used; /* Number of bytes used in the buffer. */ - off_t offset; /* Last used offset in a dump_write call. */ - off_t kdhoffset; /* Offset of the second kernel dump header. */ + dumper_t *dumper; /* Dumping function. */ + void *priv; /* Private parts. */ + u_int blocksize; /* Size of block in bytes. */ + u_int maxiosize; /* Max size allowed for an individual I/O */ + off_t mediaoffset; /* Initial offset in bytes. */ + off_t mediasize; /* Space available in bytes. */ + char *key; /* Key information. */ + char *tweak; /* Tweak. */ + void *tweak_ctx; /* Tweak context. */ + void *data_ctx; /* Data context. */ + uint8_t buf[DUMPER_BUFSIZE]; /* Raw data buffer. */ + u_int buf_used; /* Number of bytes used in the buffer. */ + off_t offset; /* Last used offset in a xts_block_encrypt call. */ + off_t realoffset; /* Last used offset in a dump_write call. */ }; int set_dumper(struct dumperinfo *, const char *_devname);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201307281749.r6SHn6sq072534>