socsvn commit: r255272 - in soc2013/def/crashdump-head: sbin/savecore sys/kern sys/sys

def at FreeBSD.org def at FreeBSD.org
Sun Jul 28 17:49:07 UTC 2013


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);


More information about the svn-soc-all mailing list