1994-05-26 06:35:07 +00:00
|
|
|
/*-
|
2002-03-31 22:26:56 +00:00
|
|
|
* Copyright (c) 2002 Poul-Henning Kamp
|
|
|
|
* Copyright (c) 2002 Networks Associates Technology, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This software was developed for the FreeBSD Project by Poul-Henning Kamp
|
|
|
|
* and NAI Labs, the Security Research Division of Network Associates, Inc.
|
|
|
|
* under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
|
|
|
|
* DARPA CHATS research program.
|
1994-05-26 06:35:07 +00:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2002-03-31 22:26:56 +00:00
|
|
|
* 3. The names of the authors may not be used to endorse or promote
|
|
|
|
* products derived from this software without specific prior written
|
|
|
|
* permission.
|
1994-05-26 06:35:07 +00:00
|
|
|
*
|
2002-03-31 22:26:56 +00:00
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
1994-05-26 06:35:07 +00:00
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
2002-03-31 22:26:56 +00:00
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
1994-05-26 06:35:07 +00:00
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
2002-05-05 01:04:00 +00:00
|
|
|
*
|
|
|
|
* Copyright (c) 1986, 1992, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
1994-05-26 06:35:07 +00:00
|
|
|
*/
|
|
|
|
|
2002-04-21 07:18:16 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
2002-05-05 01:04:00 +00:00
|
|
|
#include <sys/param.h>
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
#include <sys/disk.h>
|
|
|
|
#include <sys/kerneldump.h>
|
2002-05-04 10:36:35 +00:00
|
|
|
#include <sys/mount.h>
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <errno.h>
|
2002-03-31 22:26:56 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <fstab.h>
|
2002-05-04 10:36:35 +00:00
|
|
|
#include <paths.h>
|
2012-04-09 20:55:23 +00:00
|
|
|
#include <signal.h>
|
2002-05-05 01:04:00 +00:00
|
|
|
#include <stdarg.h>
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
#include <stdbool.h>
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2002-05-05 01:04:00 +00:00
|
|
|
#include <syslog.h>
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
#include <time.h>
|
2002-03-31 22:26:56 +00:00
|
|
|
#include <unistd.h>
|
2015-03-22 17:29:14 +00:00
|
|
|
#include <libxo/xo.h>
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
2002-06-02 19:20:37 +00:00
|
|
|
/* The size of the buffer used for I/O. */
|
|
|
|
#define BUFFERSIZE (1024*1024)
|
|
|
|
|
2005-02-26 01:19:21 +00:00
|
|
|
#define STATUS_BAD 0
|
|
|
|
#define STATUS_GOOD 1
|
|
|
|
#define STATUS_UNKNOWN 2
|
2005-02-24 02:45:10 +00:00
|
|
|
|
2004-08-16 07:02:14 +00:00
|
|
|
static int checkfor, compress, clear, force, keep, verbose; /* flags */
|
|
|
|
static int nfound, nsaved, nerr; /* statistics */
|
2012-12-16 23:06:12 +00:00
|
|
|
static int maxdumps;
|
2002-05-05 01:04:00 +00:00
|
|
|
|
|
|
|
extern FILE *zopen(const char *, const char *);
|
2002-03-31 22:26:56 +00:00
|
|
|
|
2009-08-25 06:21:45 +00:00
|
|
|
static sig_atomic_t got_siginfo;
|
|
|
|
static void infohandler(int);
|
|
|
|
|
2002-03-31 22:26:56 +00:00
|
|
|
static void
|
2015-03-22 17:29:14 +00:00
|
|
|
printheader(xo_handle_t *xo, const struct kerneldumpheader *h, const char *device,
|
2005-02-24 02:45:10 +00:00
|
|
|
int bounds, const int status)
|
2002-03-31 22:26:56 +00:00
|
|
|
{
|
2002-04-03 07:24:12 +00:00
|
|
|
uint64_t dumplen;
|
2002-03-31 22:26:56 +00:00
|
|
|
time_t t;
|
2005-02-24 02:45:10 +00:00
|
|
|
const char *stat_str;
|
2002-03-31 22:26:56 +00:00
|
|
|
|
2015-03-22 17:29:14 +00:00
|
|
|
xo_flush_h(xo);
|
|
|
|
xo_emit_h(xo, "{Lwc:Dump header from device}{:dump_device/%s}\n", device);
|
|
|
|
xo_emit_h(xo, "{P: }{Lwc:Architecture}{:architecture/%s}\n", h->architecture);
|
|
|
|
xo_emit_h(xo, "{P: }{Lwc:Architecture Version}{:architecture_version/%u}\n", dtoh32(h->architectureversion));
|
2002-04-03 07:24:12 +00:00
|
|
|
dumplen = dtoh64(h->dumplength);
|
2015-03-22 17:29:14 +00:00
|
|
|
xo_emit_h(xo, "{P: }{Lwc:Dump Length}{:dump_length_bytes/%lld}\n", (long long)dumplen);
|
|
|
|
xo_emit_h(xo, "{P: }{Lwc:Blocksize}{:blocksize/%d}\n", dtoh32(h->blocksize));
|
2002-04-03 07:24:12 +00:00
|
|
|
t = dtoh64(h->dumptime);
|
2015-03-22 17:29:14 +00:00
|
|
|
xo_emit_h(xo, "{P: }{Lwc:Dumptime}{:dumptime/%s}", ctime(&t));
|
|
|
|
xo_emit_h(xo, "{P: }{Lwc:Hostname}{:hostname/%s}\n", h->hostname);
|
|
|
|
xo_emit_h(xo, "{P: }{Lwc:Magic}{:magic/%s}\n", h->magic);
|
|
|
|
xo_emit_h(xo, "{P: }{Lwc:Version String}{:version_string/%s}", h->versionstring);
|
|
|
|
xo_emit_h(xo, "{P: }{Lwc:Panic String}{:panic_string/%s}\n", h->panicstring);
|
|
|
|
xo_emit_h(xo, "{P: }{Lwc:Dump Parity}{:dump_parity/%u}\n", h->parity);
|
|
|
|
xo_emit_h(xo, "{P: }{Lwc:Bounds}{:bounds/%d}\n", bounds);
|
2005-02-24 02:45:10 +00:00
|
|
|
|
|
|
|
switch(status) {
|
|
|
|
case STATUS_BAD:
|
2005-02-26 01:19:21 +00:00
|
|
|
stat_str = "bad";
|
|
|
|
break;
|
2005-02-24 02:45:10 +00:00
|
|
|
case STATUS_GOOD:
|
2005-02-26 01:19:21 +00:00
|
|
|
stat_str = "good";
|
|
|
|
break;
|
2005-02-24 02:45:10 +00:00
|
|
|
default:
|
2005-02-26 01:19:21 +00:00
|
|
|
stat_str = "unknown";
|
2005-02-24 02:45:10 +00:00
|
|
|
}
|
2015-03-22 17:29:14 +00:00
|
|
|
xo_emit_h(xo, "{P: }{Lwc:Dump Status}{:dump_status/%s}\n", stat_str);
|
|
|
|
xo_flush_h(xo);
|
2002-03-31 22:26:56 +00:00
|
|
|
}
|
2002-04-03 07:24:12 +00:00
|
|
|
|
2002-05-05 01:04:00 +00:00
|
|
|
static int
|
|
|
|
getbounds(void) {
|
|
|
|
FILE *fp;
|
|
|
|
char buf[6];
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
if ((fp = fopen("bounds", "r")) == NULL) {
|
2005-09-13 19:15:28 +00:00
|
|
|
if (verbose)
|
|
|
|
printf("unable to open bounds file, using 0\n");
|
2005-06-20 20:01:29 +00:00
|
|
|
return (ret);
|
2002-05-05 01:04:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fgets(buf, sizeof buf, fp) == NULL) {
|
2014-09-17 19:09:58 +00:00
|
|
|
if (feof(fp))
|
|
|
|
syslog(LOG_WARNING, "bounds file is empty, using 0");
|
|
|
|
else
|
|
|
|
syslog(LOG_WARNING, "bounds file: %s", strerror(errno));
|
2002-05-05 01:04:00 +00:00
|
|
|
fclose(fp);
|
2005-06-20 20:01:29 +00:00
|
|
|
return (ret);
|
2002-05-05 01:04:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
ret = (int)strtol(buf, NULL, 10);
|
|
|
|
if (ret == 0 && (errno == EINVAL || errno == ERANGE))
|
|
|
|
syslog(LOG_WARNING, "invalid value found in bounds, using 0");
|
2014-09-17 19:09:58 +00:00
|
|
|
fclose(fp);
|
2005-06-20 20:01:29 +00:00
|
|
|
return (ret);
|
|
|
|
}
|
2002-05-05 01:04:00 +00:00
|
|
|
|
2005-06-20 20:01:29 +00:00
|
|
|
static void
|
|
|
|
writebounds(int bounds) {
|
|
|
|
FILE *fp;
|
2002-05-05 01:04:00 +00:00
|
|
|
|
|
|
|
if ((fp = fopen("bounds", "w")) == NULL) {
|
|
|
|
syslog(LOG_WARNING, "unable to write to bounds file: %m");
|
2005-06-20 20:01:29 +00:00
|
|
|
return;
|
2002-05-05 01:04:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (verbose)
|
2005-06-20 20:01:29 +00:00
|
|
|
printf("bounds number: %d\n", bounds);
|
2002-05-05 01:04:00 +00:00
|
|
|
|
2005-06-20 20:01:29 +00:00
|
|
|
fprintf(fp, "%d\n", bounds);
|
2002-05-05 01:04:00 +00:00
|
|
|
fclose(fp);
|
|
|
|
}
|
|
|
|
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
static bool
|
|
|
|
writekey(const char *keyname, uint8_t *dumpkey, uint32_t dumpkeysize)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
fd = open(keyname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
|
|
|
if (fd == -1) {
|
|
|
|
syslog(LOG_ERR, "Unable to open %s to write the key: %m.",
|
|
|
|
keyname);
|
|
|
|
return (false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (write(fd, dumpkey, dumpkeysize) != (ssize_t)dumpkeysize) {
|
|
|
|
syslog(LOG_ERR, "Unable to write the key to %s: %m.", keyname);
|
|
|
|
close(fd);
|
|
|
|
return (false);
|
|
|
|
}
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
return (true);
|
|
|
|
}
|
|
|
|
|
2012-12-16 23:06:12 +00:00
|
|
|
static off_t
|
|
|
|
file_size(const char *path)
|
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
|
|
|
|
/* Ignore all errors, those file may not exists. */
|
|
|
|
if (stat(path, &sb) == -1)
|
|
|
|
return (0);
|
|
|
|
return (sb.st_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static off_t
|
|
|
|
saved_dump_size(int bounds)
|
|
|
|
{
|
|
|
|
static char path[PATH_MAX];
|
|
|
|
off_t dumpsize;
|
|
|
|
|
|
|
|
dumpsize = 0;
|
|
|
|
|
|
|
|
(void)snprintf(path, sizeof(path), "info.%d", bounds);
|
|
|
|
dumpsize += file_size(path);
|
|
|
|
(void)snprintf(path, sizeof(path), "vmcore.%d", bounds);
|
|
|
|
dumpsize += file_size(path);
|
|
|
|
(void)snprintf(path, sizeof(path), "vmcore.%d.gz", bounds);
|
|
|
|
dumpsize += file_size(path);
|
|
|
|
(void)snprintf(path, sizeof(path), "textdump.tar.%d", bounds);
|
|
|
|
dumpsize += file_size(path);
|
|
|
|
(void)snprintf(path, sizeof(path), "textdump.tar.%d.gz", bounds);
|
|
|
|
dumpsize += file_size(path);
|
|
|
|
|
|
|
|
return (dumpsize);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
saved_dump_remove(int bounds)
|
|
|
|
{
|
|
|
|
static char path[PATH_MAX];
|
|
|
|
|
|
|
|
(void)snprintf(path, sizeof(path), "info.%d", bounds);
|
|
|
|
(void)unlink(path);
|
|
|
|
(void)snprintf(path, sizeof(path), "vmcore.%d", bounds);
|
|
|
|
(void)unlink(path);
|
|
|
|
(void)snprintf(path, sizeof(path), "vmcore.%d.gz", bounds);
|
|
|
|
(void)unlink(path);
|
|
|
|
(void)snprintf(path, sizeof(path), "textdump.tar.%d", bounds);
|
|
|
|
(void)unlink(path);
|
|
|
|
(void)snprintf(path, sizeof(path), "textdump.tar.%d.gz", bounds);
|
|
|
|
(void)unlink(path);
|
|
|
|
}
|
|
|
|
|
2012-12-16 23:09:27 +00:00
|
|
|
static void
|
|
|
|
symlinks_remove(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
(void)unlink("info.last");
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
(void)unlink("key.last");
|
2012-12-16 23:09:27 +00:00
|
|
|
(void)unlink("vmcore.last");
|
|
|
|
(void)unlink("vmcore.last.gz");
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
(void)unlink("vmcore_encrypted.last");
|
|
|
|
(void)unlink("vmcore_encrypted.last.gz");
|
2012-12-16 23:09:27 +00:00
|
|
|
(void)unlink("textdump.tar.last");
|
|
|
|
(void)unlink("textdump.tar.last.gz");
|
|
|
|
}
|
|
|
|
|
2002-05-04 10:36:35 +00:00
|
|
|
/*
|
|
|
|
* Check that sufficient space is available on the disk that holds the
|
|
|
|
* save directory.
|
|
|
|
*/
|
|
|
|
static int
|
2012-12-16 23:06:12 +00:00
|
|
|
check_space(const char *savedir, off_t dumpsize, int bounds)
|
2002-05-04 10:36:35 +00:00
|
|
|
{
|
|
|
|
FILE *fp;
|
2002-05-05 01:04:00 +00:00
|
|
|
off_t minfree, spacefree, totfree, needed;
|
2002-05-04 10:36:35 +00:00
|
|
|
struct statfs fsbuf;
|
2012-12-16 23:04:31 +00:00
|
|
|
char buf[100];
|
2002-05-04 10:36:35 +00:00
|
|
|
|
2012-12-16 23:04:31 +00:00
|
|
|
if (statfs(".", &fsbuf) < 0) {
|
2002-05-05 01:04:00 +00:00
|
|
|
syslog(LOG_ERR, "%s: %m", savedir);
|
|
|
|
exit(1);
|
|
|
|
}
|
2012-12-14 15:01:23 +00:00
|
|
|
spacefree = ((off_t) fsbuf.f_bavail * fsbuf.f_bsize) / 1024;
|
2002-05-04 10:36:35 +00:00
|
|
|
totfree = ((off_t) fsbuf.f_bfree * fsbuf.f_bsize) / 1024;
|
|
|
|
|
2012-12-16 23:04:31 +00:00
|
|
|
if ((fp = fopen("minfree", "r")) == NULL)
|
2002-05-04 10:36:35 +00:00
|
|
|
minfree = 0;
|
|
|
|
else {
|
|
|
|
if (fgets(buf, sizeof(buf), fp) == NULL)
|
|
|
|
minfree = 0;
|
|
|
|
else
|
|
|
|
minfree = atoi(buf);
|
|
|
|
(void)fclose(fp);
|
|
|
|
}
|
|
|
|
|
2002-05-05 01:04:00 +00:00
|
|
|
needed = dumpsize / 1024 + 2; /* 2 for info file */
|
2012-12-16 23:06:12 +00:00
|
|
|
needed -= saved_dump_size(bounds);
|
|
|
|
if ((minfree > 0 ? spacefree : totfree) - needed < minfree) {
|
2002-05-05 01:04:00 +00:00
|
|
|
syslog(LOG_WARNING,
|
|
|
|
"no dump, not enough free space on device (%lld available, need %lld)",
|
2002-05-04 10:36:35 +00:00
|
|
|
(long long)(minfree > 0 ? spacefree : totfree),
|
|
|
|
(long long)needed);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
if (spacefree - needed < 0)
|
2002-05-05 01:04:00 +00:00
|
|
|
syslog(LOG_WARNING,
|
|
|
|
"dump performed, but free space threshold crossed");
|
2002-05-04 10:36:35 +00:00
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
2002-05-05 01:04:00 +00:00
|
|
|
#define BLOCKSIZE (1<<12)
|
|
|
|
#define BLOCKMASK (~(BLOCKSIZE-1))
|
2002-03-31 22:26:56 +00:00
|
|
|
|
2007-12-26 11:42:10 +00:00
|
|
|
static int
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
DoRegularFile(int fd, bool isencrypted, off_t dumpsize, char *buf,
|
|
|
|
const char *device, const char *filename, FILE *fp)
|
2007-12-26 11:42:10 +00:00
|
|
|
{
|
|
|
|
int he, hs, nr, nw, wl;
|
2009-08-25 06:21:45 +00:00
|
|
|
off_t dmpcnt, origsize;
|
2007-12-26 11:42:10 +00:00
|
|
|
|
|
|
|
dmpcnt = 0;
|
2009-08-25 06:21:45 +00:00
|
|
|
origsize = dumpsize;
|
2007-12-26 11:42:10 +00:00
|
|
|
he = 0;
|
|
|
|
while (dumpsize > 0) {
|
|
|
|
wl = BUFFERSIZE;
|
|
|
|
if (wl > dumpsize)
|
|
|
|
wl = dumpsize;
|
|
|
|
nr = read(fd, buf, wl);
|
|
|
|
if (nr != wl) {
|
|
|
|
if (nr == 0)
|
|
|
|
syslog(LOG_WARNING,
|
|
|
|
"WARNING: EOF on dump device");
|
|
|
|
else
|
|
|
|
syslog(LOG_ERR, "read error on %s: %m", device);
|
|
|
|
nerr++;
|
|
|
|
return (-1);
|
|
|
|
}
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
if (compress || isencrypted) {
|
2007-12-26 11:42:10 +00:00
|
|
|
nw = fwrite(buf, 1, wl, fp);
|
|
|
|
} else {
|
|
|
|
for (nw = 0; nw < nr; nw = he) {
|
|
|
|
/* find a contiguous block of zeroes */
|
|
|
|
for (hs = nw; hs < nr; hs += BLOCKSIZE) {
|
|
|
|
for (he = hs; he < nr && buf[he] == 0;
|
|
|
|
++he)
|
|
|
|
/* nothing */ ;
|
|
|
|
/* is the hole long enough to matter? */
|
|
|
|
if (he >= hs + BLOCKSIZE)
|
|
|
|
break;
|
|
|
|
}
|
2012-12-14 15:01:23 +00:00
|
|
|
|
2007-12-26 11:42:10 +00:00
|
|
|
/* back down to a block boundary */
|
|
|
|
he &= BLOCKMASK;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 1) Don't go beyond the end of the buffer.
|
|
|
|
* 2) If the end of the buffer is less than
|
|
|
|
* BLOCKSIZE bytes away, we're at the end
|
|
|
|
* of the file, so just grab what's left.
|
|
|
|
*/
|
|
|
|
if (hs + BLOCKSIZE > nr)
|
|
|
|
hs = he = nr;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* At this point, we have a partial ordering:
|
|
|
|
* nw <= hs <= he <= nr
|
|
|
|
* 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)
|
|
|
|
!= 1)
|
|
|
|
break;
|
|
|
|
if (he > hs)
|
|
|
|
if (fseeko(fp, he - hs, SEEK_CUR) == -1)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nw != wl) {
|
|
|
|
syslog(LOG_ERR,
|
|
|
|
"write error on %s file: %m", filename);
|
|
|
|
syslog(LOG_WARNING,
|
|
|
|
"WARNING: vmcore may be incomplete");
|
|
|
|
nerr++;
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if (verbose) {
|
|
|
|
dmpcnt += wl;
|
|
|
|
printf("%llu\r", (unsigned long long)dmpcnt);
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
dumpsize -= wl;
|
2009-08-25 06:21:45 +00:00
|
|
|
if (got_siginfo) {
|
|
|
|
printf("%s %.1lf%%\n", filename, (100.0 - (100.0 *
|
|
|
|
(double)dumpsize / (double)origsize)));
|
|
|
|
got_siginfo = 0;
|
|
|
|
}
|
2007-12-26 11:42:10 +00:00
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Specialized version of dump-reading logic for use with textdumps, which
|
|
|
|
* are written backwards from the end of the partition, and must be reversed
|
|
|
|
* before being written to the file. Textdumps are small, so do a bit less
|
|
|
|
* work to optimize/sparsify.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
DoTextdumpFile(int fd, off_t dumpsize, off_t lasthd, char *buf,
|
|
|
|
const char *device, const char *filename, FILE *fp)
|
|
|
|
{
|
|
|
|
int nr, nw, wl;
|
|
|
|
off_t dmpcnt, totsize;
|
|
|
|
|
|
|
|
totsize = dumpsize;
|
|
|
|
dmpcnt = 0;
|
|
|
|
wl = 512;
|
|
|
|
if ((dumpsize % wl) != 0) {
|
|
|
|
syslog(LOG_ERR, "textdump uneven multiple of 512 on %s",
|
|
|
|
device);
|
|
|
|
nerr++;
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
while (dumpsize > 0) {
|
|
|
|
nr = pread(fd, buf, wl, lasthd - (totsize - dumpsize) - wl);
|
|
|
|
if (nr != wl) {
|
|
|
|
if (nr == 0)
|
|
|
|
syslog(LOG_WARNING,
|
|
|
|
"WARNING: EOF on dump device");
|
|
|
|
else
|
|
|
|
syslog(LOG_ERR, "read error on %s: %m", device);
|
|
|
|
nerr++;
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
nw = fwrite(buf, 1, wl, fp);
|
|
|
|
if (nw != wl) {
|
|
|
|
syslog(LOG_ERR,
|
|
|
|
"write error on %s file: %m", filename);
|
|
|
|
syslog(LOG_WARNING,
|
|
|
|
"WARNING: textdump may be incomplete");
|
|
|
|
nerr++;
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if (verbose) {
|
|
|
|
dmpcnt += wl;
|
|
|
|
printf("%llu\r", (unsigned long long)dmpcnt);
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
dumpsize -= wl;
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2002-03-31 22:26:56 +00:00
|
|
|
static void
|
2005-05-29 16:28:07 +00:00
|
|
|
DoFile(const char *savedir, const char *device)
|
2002-03-31 22:26:56 +00:00
|
|
|
{
|
2015-03-22 17:29:14 +00:00
|
|
|
xo_handle_t *xostdout, *xoinfo;
|
2012-12-16 23:09:27 +00:00
|
|
|
static char infoname[PATH_MAX], corename[PATH_MAX], linkname[PATH_MAX];
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
static char keyname[PATH_MAX];
|
2016-10-06 05:16:44 +00:00
|
|
|
static char *buf = NULL;
|
|
|
|
char *temp = NULL;
|
2002-03-31 22:26:56 +00:00
|
|
|
struct kerneldumpheader kdhf, kdhl;
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
uint8_t *dumpkey;
|
2007-12-26 11:42:10 +00:00
|
|
|
off_t mediasize, dumpsize, firsthd, lasthd;
|
2002-05-05 01:04:00 +00:00
|
|
|
FILE *info, *fp;
|
2005-02-26 01:19:21 +00:00
|
|
|
mode_t oumask;
|
2007-12-26 11:42:10 +00:00
|
|
|
int fd, fdinfo, error;
|
2005-02-24 02:45:10 +00:00
|
|
|
int bounds, status;
|
2015-03-22 17:29:14 +00:00
|
|
|
u_int sectorsize, xostyle;
|
2007-12-26 11:42:10 +00:00
|
|
|
int istextdump;
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
uint32_t dumpkeysize;
|
|
|
|
bool isencrypted, ret;
|
2002-05-05 01:04:00 +00:00
|
|
|
|
2005-02-24 02:45:10 +00:00
|
|
|
bounds = getbounds();
|
2002-05-05 01:04:00 +00:00
|
|
|
mediasize = 0;
|
2005-02-24 02:45:10 +00:00
|
|
|
status = STATUS_UNKNOWN;
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
2015-03-22 17:29:14 +00:00
|
|
|
xostdout = xo_create_to_file(stdout, XO_STYLE_TEXT, 0);
|
|
|
|
if (xostdout == NULL) {
|
|
|
|
syslog(LOG_ERR, "%s: %m", infoname);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-12-16 23:06:12 +00:00
|
|
|
if (maxdumps > 0 && bounds == maxdumps)
|
|
|
|
bounds = 0;
|
|
|
|
|
2002-05-27 07:54:43 +00:00
|
|
|
if (buf == NULL) {
|
2002-06-02 19:20:37 +00:00
|
|
|
buf = malloc(BUFFERSIZE);
|
2002-05-27 07:54:43 +00:00
|
|
|
if (buf == NULL) {
|
|
|
|
syslog(LOG_ERR, "%m");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
if (verbose)
|
2002-05-05 01:04:00 +00:00
|
|
|
printf("checking for kernel dump on device %s\n", device);
|
2002-03-31 22:26:56 +00:00
|
|
|
|
2012-12-14 15:03:12 +00:00
|
|
|
fd = open(device, (checkfor || keep) ? O_RDONLY : O_RDWR);
|
2002-03-31 22:26:56 +00:00
|
|
|
if (fd < 0) {
|
2002-05-05 01:04:00 +00:00
|
|
|
syslog(LOG_ERR, "%s: %m", device);
|
2002-03-31 22:26:56 +00:00
|
|
|
return;
|
1994-05-26 06:35:07 +00:00
|
|
|
}
|
2002-05-27 07:54:43 +00:00
|
|
|
|
2002-03-31 22:26:56 +00:00
|
|
|
error = ioctl(fd, DIOCGMEDIASIZE, &mediasize);
|
|
|
|
if (!error)
|
|
|
|
error = ioctl(fd, DIOCGSECTORSIZE, §orsize);
|
|
|
|
if (error) {
|
2002-05-05 01:04:00 +00:00
|
|
|
syslog(LOG_ERR,
|
|
|
|
"couldn't find media and/or sector size of %s: %m", device);
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
goto closefd;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (verbose) {
|
2002-05-05 01:04:00 +00:00
|
|
|
printf("mediasize = %lld\n", (long long)mediasize);
|
|
|
|
printf("sectorsize = %u\n", sectorsize);
|
1999-05-13 04:29:09 +00:00
|
|
|
}
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
2016-04-15 17:45:12 +00:00
|
|
|
if (sectorsize < sizeof(kdhl)) {
|
|
|
|
syslog(LOG_ERR,
|
|
|
|
"Sector size is less the kernel dump header %zu",
|
|
|
|
sizeof(kdhl));
|
|
|
|
goto closefd;
|
|
|
|
}
|
|
|
|
|
2002-03-31 22:26:56 +00:00
|
|
|
lasthd = mediasize - sectorsize;
|
2016-10-06 05:16:44 +00:00
|
|
|
temp = malloc(sectorsize);
|
2016-04-15 17:45:12 +00:00
|
|
|
if (temp == NULL) {
|
2016-10-06 05:16:44 +00:00
|
|
|
syslog(LOG_ERR, "%m");
|
|
|
|
goto closefd;
|
2016-04-15 17:45:12 +00:00
|
|
|
}
|
2015-11-06 19:18:20 +00:00
|
|
|
if (lseek(fd, lasthd, SEEK_SET) != lasthd ||
|
2016-04-15 20:19:32 +00:00
|
|
|
read(fd, temp, sectorsize) != (ssize_t)sectorsize) {
|
2002-05-05 01:04:00 +00:00
|
|
|
syslog(LOG_ERR,
|
|
|
|
"error reading last dump header at offset %lld in %s: %m",
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
(long long)lasthd, device);
|
|
|
|
goto closefd;
|
1994-05-26 06:35:07 +00:00
|
|
|
}
|
2016-04-15 17:45:12 +00:00
|
|
|
memcpy(&kdhl, temp, sizeof(kdhl));
|
2007-12-26 11:42:10 +00:00
|
|
|
istextdump = 0;
|
2007-12-27 21:28:48 +00:00
|
|
|
if (strncmp(kdhl.magic, TEXTDUMPMAGIC, sizeof kdhl) == 0) {
|
2007-12-26 11:42:10 +00:00
|
|
|
if (verbose)
|
|
|
|
printf("textdump magic on last dump header on %s\n",
|
|
|
|
device);
|
|
|
|
istextdump = 1;
|
2007-12-27 21:28:48 +00:00
|
|
|
if (dtoh32(kdhl.version) != KERNELDUMP_TEXT_VERSION) {
|
|
|
|
syslog(LOG_ERR,
|
|
|
|
"unknown version (%d) in last dump header on %s",
|
|
|
|
dtoh32(kdhl.version), device);
|
2012-12-14 15:01:23 +00:00
|
|
|
|
2007-12-27 21:28:48 +00:00
|
|
|
status = STATUS_BAD;
|
|
|
|
if (force == 0)
|
|
|
|
goto closefd;
|
|
|
|
}
|
|
|
|
} else if (memcmp(kdhl.magic, KERNELDUMPMAGIC, sizeof kdhl.magic) ==
|
|
|
|
0) {
|
|
|
|
if (dtoh32(kdhl.version) != KERNELDUMPVERSION) {
|
|
|
|
syslog(LOG_ERR,
|
|
|
|
"unknown version (%d) in last dump header on %s",
|
|
|
|
dtoh32(kdhl.version), device);
|
2012-12-14 15:01:23 +00:00
|
|
|
|
2007-12-27 21:28:48 +00:00
|
|
|
status = STATUS_BAD;
|
|
|
|
if (force == 0)
|
|
|
|
goto closefd;
|
|
|
|
}
|
|
|
|
} else {
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
if (verbose)
|
2002-05-05 01:04:00 +00:00
|
|
|
printf("magic mismatch on last dump header on %s\n",
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
device);
|
2002-05-05 01:04:00 +00:00
|
|
|
|
2005-02-24 02:45:10 +00:00
|
|
|
status = STATUS_BAD;
|
2002-05-05 01:04:00 +00:00
|
|
|
if (force == 0)
|
|
|
|
goto closefd;
|
|
|
|
|
|
|
|
if (memcmp(kdhl.magic, KERNELDUMPMAGIC_CLEARED,
|
|
|
|
sizeof kdhl.magic) == 0) {
|
|
|
|
if (verbose)
|
|
|
|
printf("forcing magic on %s\n", device);
|
|
|
|
memcpy(kdhl.magic, KERNELDUMPMAGIC,
|
|
|
|
sizeof kdhl.magic);
|
|
|
|
} else {
|
|
|
|
syslog(LOG_ERR, "unable to force dump - bad magic");
|
|
|
|
goto closefd;
|
|
|
|
}
|
2007-12-27 21:28:48 +00:00
|
|
|
if (dtoh32(kdhl.version) != KERNELDUMPVERSION) {
|
|
|
|
syslog(LOG_ERR,
|
|
|
|
"unknown version (%d) in last dump header on %s",
|
|
|
|
dtoh32(kdhl.version), device);
|
2012-12-14 15:01:23 +00:00
|
|
|
|
2007-12-27 21:28:48 +00:00
|
|
|
status = STATUS_BAD;
|
|
|
|
if (force == 0)
|
|
|
|
goto closefd;
|
|
|
|
}
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nfound++;
|
|
|
|
if (clear)
|
|
|
|
goto nuke;
|
|
|
|
|
|
|
|
if (kerneldump_parity(&kdhl)) {
|
2002-05-05 01:04:00 +00:00
|
|
|
syslog(LOG_ERR,
|
|
|
|
"parity error on last dump header on %s", device);
|
2002-05-04 10:36:35 +00:00
|
|
|
nerr++;
|
2005-02-24 02:45:10 +00:00
|
|
|
status = STATUS_BAD;
|
|
|
|
if (force == 0)
|
|
|
|
goto closefd;
|
1994-05-26 06:35:07 +00:00
|
|
|
}
|
2002-04-03 07:24:12 +00:00
|
|
|
dumpsize = dtoh64(kdhl.dumplength);
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
dumpkeysize = dtoh32(kdhl.dumpkeysize);
|
|
|
|
firsthd = lasthd - dumpsize - sectorsize - dumpkeysize;
|
2015-11-06 19:18:20 +00:00
|
|
|
if (lseek(fd, firsthd, SEEK_SET) != firsthd ||
|
2016-04-15 20:19:32 +00:00
|
|
|
read(fd, temp, sectorsize) != (ssize_t)sectorsize) {
|
2002-05-05 01:04:00 +00:00
|
|
|
syslog(LOG_ERR,
|
|
|
|
"error reading first dump header at offset %lld in %s: %m",
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
(long long)firsthd, device);
|
2002-05-04 10:36:35 +00:00
|
|
|
nerr++;
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
goto closefd;
|
2000-09-28 20:09:36 +00:00
|
|
|
}
|
2016-04-15 17:45:12 +00:00
|
|
|
memcpy(&kdhf, temp, sizeof(kdhf));
|
2005-02-24 02:45:10 +00:00
|
|
|
|
|
|
|
if (verbose >= 2) {
|
|
|
|
printf("First dump headers:\n");
|
2015-03-22 17:29:14 +00:00
|
|
|
printheader(xostdout, &kdhf, device, bounds, -1);
|
2005-02-24 02:45:10 +00:00
|
|
|
|
|
|
|
printf("\nLast dump headers:\n");
|
2015-03-22 17:29:14 +00:00
|
|
|
printheader(xostdout, &kdhl, device, bounds, -1);
|
2005-02-24 02:45:10 +00:00
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
2016-04-15 17:45:12 +00:00
|
|
|
if (memcmp(&kdhl, &kdhf, sizeof(kdhl))) {
|
2002-05-05 01:04:00 +00:00
|
|
|
syslog(LOG_ERR,
|
|
|
|
"first and last dump headers disagree on %s", device);
|
2002-05-04 10:36:35 +00:00
|
|
|
nerr++;
|
2005-02-24 02:45:10 +00:00
|
|
|
status = STATUS_BAD;
|
|
|
|
if (force == 0)
|
|
|
|
goto closefd;
|
|
|
|
} else {
|
|
|
|
status = STATUS_GOOD;
|
1994-05-26 06:35:07 +00:00
|
|
|
}
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
2003-09-04 10:07:01 +00:00
|
|
|
if (checkfor) {
|
|
|
|
printf("A dump exists on %s\n", device);
|
|
|
|
close(fd);
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
2016-04-15 17:45:12 +00:00
|
|
|
if (kdhl.panicstring[0] != '\0')
|
2015-10-23 19:28:24 +00:00
|
|
|
syslog(LOG_ALERT, "reboot after panic: %*s",
|
|
|
|
(int)sizeof(kdhl.panicstring), kdhl.panicstring);
|
2002-05-05 01:04:00 +00:00
|
|
|
else
|
|
|
|
syslog(LOG_ALERT, "reboot");
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
2002-05-05 01:04:00 +00:00
|
|
|
if (verbose)
|
|
|
|
printf("Checking for available free space\n");
|
2012-12-16 23:06:12 +00:00
|
|
|
|
|
|
|
if (!check_space(savedir, dumpsize, bounds)) {
|
2002-05-04 10:36:35 +00:00
|
|
|
nerr++;
|
|
|
|
goto closefd;
|
|
|
|
}
|
2002-05-05 01:04:00 +00:00
|
|
|
|
2005-06-20 20:01:29 +00:00
|
|
|
writebounds(bounds + 1);
|
|
|
|
|
2012-12-16 23:06:12 +00:00
|
|
|
saved_dump_remove(bounds);
|
|
|
|
|
|
|
|
snprintf(infoname, sizeof(infoname), "info.%d", bounds);
|
2002-05-05 01:04:00 +00:00
|
|
|
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
/*
|
2005-02-24 02:45:10 +00:00
|
|
|
* Create or overwrite any existing dump header files.
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
*/
|
2012-12-16 23:06:12 +00:00
|
|
|
fdinfo = open(infoname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
2002-03-31 22:26:56 +00:00
|
|
|
if (fdinfo < 0) {
|
2014-03-05 04:15:17 +00:00
|
|
|
syslog(LOG_ERR, "%s: %m", infoname);
|
2002-05-04 10:36:35 +00:00
|
|
|
nerr++;
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
goto closefd;
|
1994-05-26 06:35:07 +00:00
|
|
|
}
|
2015-03-22 17:29:14 +00:00
|
|
|
|
2002-05-05 01:04:00 +00:00
|
|
|
oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
isencrypted = (dumpkeysize > 0);
|
2002-05-05 01:04:00 +00:00
|
|
|
if (compress) {
|
2012-12-16 23:06:12 +00:00
|
|
|
snprintf(corename, sizeof(corename), "%s.%d.gz",
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
istextdump ? "textdump.tar" :
|
|
|
|
(isencrypted ? "vmcore_encrypted" : "vmcore"), bounds);
|
2012-12-16 23:06:12 +00:00
|
|
|
fp = zopen(corename, "w");
|
2002-05-05 01:04:00 +00:00
|
|
|
} else {
|
2012-12-16 23:06:12 +00:00
|
|
|
snprintf(corename, sizeof(corename), "%s.%d",
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
istextdump ? "textdump.tar" :
|
|
|
|
(isencrypted ? "vmcore_encrypted" : "vmcore"), bounds);
|
2012-12-16 23:06:12 +00:00
|
|
|
fp = fopen(corename, "w");
|
2002-05-05 01:04:00 +00:00
|
|
|
}
|
|
|
|
if (fp == NULL) {
|
2012-12-16 23:06:12 +00:00
|
|
|
syslog(LOG_ERR, "%s: %m", corename);
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
close(fdinfo);
|
2002-05-04 10:36:35 +00:00
|
|
|
nerr++;
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
goto closefd;
|
1994-05-26 06:35:07 +00:00
|
|
|
}
|
2002-05-05 01:04:00 +00:00
|
|
|
(void)umask(oumask);
|
|
|
|
|
2002-03-31 22:26:56 +00:00
|
|
|
info = fdopen(fdinfo, "w");
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
2007-05-28 09:48:25 +00:00
|
|
|
if (info == NULL) {
|
|
|
|
syslog(LOG_ERR, "fdopen failed: %m");
|
|
|
|
nerr++;
|
2015-10-23 19:28:24 +00:00
|
|
|
goto closeall;
|
2007-05-28 09:48:25 +00:00
|
|
|
}
|
|
|
|
|
2015-03-22 17:29:14 +00:00
|
|
|
xostyle = xo_get_style(NULL);
|
|
|
|
xoinfo = xo_create_to_file(info, xostyle, 0);
|
|
|
|
if (xoinfo == NULL) {
|
|
|
|
syslog(LOG_ERR, "%s: %m", infoname);
|
|
|
|
nerr++;
|
2015-10-23 19:28:24 +00:00
|
|
|
goto closeall;
|
2015-03-22 17:29:14 +00:00
|
|
|
}
|
|
|
|
xo_open_container_h(xoinfo, "crashdump");
|
|
|
|
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
if (verbose)
|
2015-03-22 17:29:14 +00:00
|
|
|
printheader(xostdout, &kdhl, device, bounds, status);
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
2015-03-22 17:29:14 +00:00
|
|
|
printheader(xoinfo, &kdhl, device, bounds, status);
|
|
|
|
xo_close_container_h(xoinfo, "crashdump");
|
|
|
|
xo_flush_h(xoinfo);
|
|
|
|
xo_finish_h(xoinfo);
|
2002-05-05 01:04:00 +00:00
|
|
|
fclose(info);
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
if (isencrypted) {
|
|
|
|
dumpkey = calloc(1, dumpkeysize);
|
|
|
|
if (dumpkey == NULL) {
|
|
|
|
syslog(LOG_ERR, "Unable to allocate kernel dump key.");
|
|
|
|
nerr++;
|
|
|
|
goto closeall;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read(fd, dumpkey, dumpkeysize) != (ssize_t)dumpkeysize) {
|
|
|
|
syslog(LOG_ERR, "Unable to read kernel dump key: %m.");
|
|
|
|
nerr++;
|
|
|
|
goto closeall;
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(keyname, sizeof(keyname), "key.%d", bounds);
|
|
|
|
ret = writekey(keyname, dumpkey, dumpkeysize);
|
|
|
|
explicit_bzero(dumpkey, dumpkeysize);
|
|
|
|
if (!ret) {
|
|
|
|
nerr++;
|
|
|
|
goto closeall;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
syslog(LOG_NOTICE, "writing %s%score to %s/%s",
|
|
|
|
isencrypted ? "encrypted " : "", compress ? "compressed " : "",
|
|
|
|
savedir, corename);
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
2007-12-26 11:42:10 +00:00
|
|
|
if (istextdump) {
|
|
|
|
if (DoTextdumpFile(fd, dumpsize, lasthd, buf, device,
|
2012-12-16 23:06:12 +00:00
|
|
|
corename, fp) < 0)
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
goto closeall;
|
2007-12-26 11:42:10 +00:00
|
|
|
} else {
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
if (DoRegularFile(fd, isencrypted, dumpsize, buf, device,
|
|
|
|
corename, fp) < 0) {
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
goto closeall;
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
}
|
1994-05-26 06:35:07 +00:00
|
|
|
}
|
2002-05-05 01:04:00 +00:00
|
|
|
if (verbose)
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
if (fclose(fp) < 0) {
|
2012-12-16 23:06:12 +00:00
|
|
|
syslog(LOG_ERR, "error on %s: %m", corename);
|
2002-05-05 01:04:00 +00:00
|
|
|
nerr++;
|
2014-04-14 21:44:34 +00:00
|
|
|
goto closefd;
|
2002-05-05 01:04:00 +00:00
|
|
|
}
|
2012-12-16 23:06:12 +00:00
|
|
|
|
2012-12-16 23:09:27 +00:00
|
|
|
symlinks_remove();
|
|
|
|
if (symlink(infoname, "info.last") == -1) {
|
|
|
|
syslog(LOG_WARNING, "unable to create symlink %s/%s: %m",
|
|
|
|
savedir, "info.last");
|
|
|
|
}
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
if (isencrypted) {
|
|
|
|
if (symlink(keyname, "key.last") == -1) {
|
|
|
|
syslog(LOG_WARNING,
|
|
|
|
"unable to create symlink %s/%s: %m", savedir,
|
|
|
|
"key.last");
|
|
|
|
}
|
|
|
|
}
|
2012-12-16 23:09:27 +00:00
|
|
|
if (compress) {
|
|
|
|
snprintf(linkname, sizeof(linkname), "%s.last.gz",
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
istextdump ? "textdump.tar" :
|
|
|
|
(isencrypted ? "vmcore_encrypted" : "vmcore"));
|
2012-12-16 23:09:27 +00:00
|
|
|
} else {
|
|
|
|
snprintf(linkname, sizeof(linkname), "%s.last",
|
Add support for encrypted kernel crash dumps.
Changes include modifications in kernel crash dump routines, dumpon(8) and
savecore(8). A new tool called decryptcore(8) was added.
A new DIOCSKERNELDUMP I/O control was added to send a kernel crash dump
configuration in the diocskerneldump_arg structure to the kernel.
The old DIOCSKERNELDUMP I/O control was renamed to DIOCSKERNELDUMP_FREEBSD11 for
backward ABI compatibility.
dumpon(8) generates an one-time random symmetric key and encrypts it using
an RSA public key in capability mode. Currently only AES-256-CBC is supported
but EKCD was designed to implement support for other algorithms in the future.
The public key is chosen using the -k flag. The dumpon rc(8) script can do this
automatically during startup using the dumppubkey rc.conf(5) variable. Once the
keys are calculated dumpon sends them to the kernel via DIOCSKERNELDUMP I/O
control.
When the kernel receives the DIOCSKERNELDUMP I/O control it generates a random
IV and sets up the key schedule for the specified algorithm. Each time the
kernel tries to write a crash dump to the dump device, the IV is replaced by
a SHA-256 hash of the previous value. This is intended to make a possible
differential cryptanalysis harder since it is possible to write multiple crash
dumps without reboot by repeating the following commands:
# sysctl debug.kdb.enter=1
db> call doadump(0)
db> continue
# savecore
A kernel dump key consists of an algorithm identifier, an IV and an encrypted
symmetric key. The kernel dump key size is included in a kernel dump header.
The size is an unsigned 32-bit integer and it is aligned to a block size.
The header structure has 512 bytes to match the block size so it was required to
make a panic string 4 bytes shorter to add a new field to the header structure.
If the kernel dump key size in the header is nonzero it is assumed that the
kernel dump key is placed after the first header on the dump device and the core
dump is encrypted.
Separate functions were implemented to write the kernel dump header and the
kernel dump key as they need to be unencrypted. The dump_write function encrypts
data if the kernel was compiled with the EKCD option. Encrypted kernel textdumps
are not supported due to the way they are constructed which makes it impossible
to use the CBC mode for encryption. It should be also noted that textdumps don't
contain sensitive data by design as a user decides what information should be
dumped.
savecore(8) writes the kernel dump key to a key.# file if its size in the header
is nonzero. # is the number of the current core dump.
decryptcore(8) decrypts the core dump using a private RSA key and the kernel
dump key. This is performed by a child process in capability mode.
If the decryption was not successful the parent process removes a partially
decrypted core dump.
Description on how to encrypt crash dumps was added to the decryptcore(8),
dumpon(8), rc.conf(5) and savecore(8) manual pages.
EKCD was tested on amd64 using bhyve and i386, mipsel and sparc64 using QEMU.
The feature still has to be tested on arm and arm64 as it wasn't possible to run
FreeBSD due to the problems with QEMU emulation and lack of hardware.
Designed by: def, pjd
Reviewed by: cem, oshogbo, pjd
Partial review: delphij, emaste, jhb, kib
Approved by: pjd (mentor)
Differential Revision: https://reviews.freebsd.org/D4712
2016-12-10 16:20:39 +00:00
|
|
|
istextdump ? "textdump.tar" :
|
|
|
|
(isencrypted ? "vmcore_encrypted" : "vmcore"));
|
2012-12-16 23:09:27 +00:00
|
|
|
}
|
|
|
|
if (symlink(corename, linkname) == -1) {
|
|
|
|
syslog(LOG_WARNING, "unable to create symlink %s/%s: %m",
|
|
|
|
savedir, linkname);
|
|
|
|
}
|
|
|
|
|
2002-05-04 10:36:35 +00:00
|
|
|
nsaved++;
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
|
|
|
if (verbose)
|
2002-05-05 01:04:00 +00:00
|
|
|
printf("dump saved\n");
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
2002-05-05 01:04:00 +00:00
|
|
|
nuke:
|
2012-12-14 15:03:12 +00:00
|
|
|
if (!keep) {
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
if (verbose)
|
2002-05-05 01:04:00 +00:00
|
|
|
printf("clearing dump header\n");
|
2016-04-15 17:45:12 +00:00
|
|
|
memcpy(kdhl.magic, KERNELDUMPMAGIC_CLEARED, sizeof(kdhl.magic));
|
|
|
|
memcpy(temp, &kdhl, sizeof(kdhl));
|
2015-10-23 19:28:24 +00:00
|
|
|
if (lseek(fd, lasthd, SEEK_SET) != lasthd ||
|
2016-04-15 20:19:32 +00:00
|
|
|
write(fd, temp, sectorsize) != (ssize_t)sectorsize)
|
2002-05-05 01:04:00 +00:00
|
|
|
syslog(LOG_ERR,
|
|
|
|
"error while clearing the dump header: %m");
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
}
|
2015-03-22 17:29:14 +00:00
|
|
|
xo_close_container_h(xostdout, "crashdump");
|
|
|
|
xo_finish_h(xostdout);
|
2016-10-06 05:16:44 +00:00
|
|
|
free(temp);
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
close(fd);
|
|
|
|
return;
|
|
|
|
|
2002-05-05 01:04:00 +00:00
|
|
|
closeall:
|
|
|
|
fclose(fp);
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
2002-05-05 01:04:00 +00:00
|
|
|
closefd:
|
2016-10-06 05:16:44 +00:00
|
|
|
free(temp);
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
close(fd);
|
1994-05-26 06:35:07 +00:00
|
|
|
}
|
|
|
|
|
2002-03-31 22:26:56 +00:00
|
|
|
static void
|
|
|
|
usage(void)
|
1994-05-26 06:35:07 +00:00
|
|
|
{
|
2015-03-22 17:29:14 +00:00
|
|
|
xo_error("%s\n%s\n%s\n",
|
2012-12-14 15:12:08 +00:00
|
|
|
"usage: savecore -c [-v] [device ...]",
|
|
|
|
" savecore -C [-v] [device ...]",
|
2012-12-16 23:06:12 +00:00
|
|
|
" savecore [-fkvz] [-m maxdumps] [directory [device ...]]");
|
|
|
|
exit(1);
|
1994-05-26 06:35:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2002-03-31 22:26:56 +00:00
|
|
|
main(int argc, char **argv)
|
1999-08-31 18:12:44 +00:00
|
|
|
{
|
2005-05-29 16:28:07 +00:00
|
|
|
const char *savedir = ".";
|
2005-02-26 01:19:21 +00:00
|
|
|
struct fstab *fsp;
|
|
|
|
int i, ch, error;
|
1999-08-31 18:12:44 +00:00
|
|
|
|
2005-02-24 02:45:10 +00:00
|
|
|
checkfor = compress = clear = force = keep = verbose = 0;
|
|
|
|
nfound = nsaved = nerr = 0;
|
|
|
|
|
2002-05-05 01:04:00 +00:00
|
|
|
openlog("savecore", LOG_PERROR, LOG_DAEMON);
|
2009-08-25 06:21:45 +00:00
|
|
|
signal(SIGINFO, infohandler);
|
2002-05-05 01:04:00 +00:00
|
|
|
|
2015-03-22 17:29:14 +00:00
|
|
|
argc = xo_parse_args(argc, argv);
|
|
|
|
if (argc < 0)
|
|
|
|
exit(1);
|
|
|
|
|
2012-12-16 23:06:12 +00:00
|
|
|
while ((ch = getopt(argc, argv, "Ccfkm:vz")) != -1)
|
2002-03-31 22:26:56 +00:00
|
|
|
switch(ch) {
|
2003-09-04 10:07:01 +00:00
|
|
|
case 'C':
|
|
|
|
checkfor = 1;
|
|
|
|
break;
|
2002-03-31 22:26:56 +00:00
|
|
|
case 'c':
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
clear = 1;
|
|
|
|
break;
|
2012-12-16 22:59:58 +00:00
|
|
|
case 'f':
|
|
|
|
force = 1;
|
|
|
|
break;
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
case 'k':
|
|
|
|
keep = 1;
|
|
|
|
break;
|
2012-12-16 23:06:12 +00:00
|
|
|
case 'm':
|
|
|
|
maxdumps = atoi(optarg);
|
|
|
|
if (maxdumps <= 0) {
|
|
|
|
syslog(LOG_ERR, "Invalid maxdump value");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
2002-03-31 22:26:56 +00:00
|
|
|
case 'v':
|
2005-02-24 02:45:10 +00:00
|
|
|
verbose++;
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
break;
|
2002-05-05 01:04:00 +00:00
|
|
|
case 'z':
|
|
|
|
compress = 1;
|
|
|
|
break;
|
2002-03-31 22:26:56 +00:00
|
|
|
case '?':
|
|
|
|
default:
|
|
|
|
usage();
|
|
|
|
}
|
2003-09-04 10:07:01 +00:00
|
|
|
if (checkfor && (clear || force || keep))
|
|
|
|
usage();
|
2012-12-14 15:04:39 +00:00
|
|
|
if (clear && (compress || keep))
|
|
|
|
usage();
|
2012-12-16 23:06:12 +00:00
|
|
|
if (maxdumps > 0 && (checkfor || clear))
|
|
|
|
usage();
|
2002-03-31 22:26:56 +00:00
|
|
|
argc -= optind;
|
|
|
|
argv += optind;
|
2012-12-14 15:12:08 +00:00
|
|
|
if (argc >= 1 && !checkfor && !clear) {
|
2002-03-31 22:26:56 +00:00
|
|
|
error = chdir(argv[0]);
|
2002-05-05 01:04:00 +00:00
|
|
|
if (error) {
|
|
|
|
syslog(LOG_ERR, "chdir(%s): %m", argv[0]);
|
|
|
|
exit(1);
|
|
|
|
}
|
2002-05-04 10:36:35 +00:00
|
|
|
savedir = argv[0];
|
2002-03-31 22:26:56 +00:00
|
|
|
argc--;
|
|
|
|
argv++;
|
|
|
|
}
|
|
|
|
if (argc == 0) {
|
|
|
|
for (;;) {
|
|
|
|
fsp = getfsent();
|
|
|
|
if (fsp == NULL)
|
|
|
|
break;
|
|
|
|
if (strcmp(fsp->fs_vfstype, "swap") &&
|
|
|
|
strcmp(fsp->fs_vfstype, "dump"))
|
|
|
|
continue;
|
2002-05-04 10:36:35 +00:00
|
|
|
DoFile(savedir, fsp->fs_spec);
|
2002-03-31 22:26:56 +00:00
|
|
|
}
|
2016-04-20 00:49:49 +00:00
|
|
|
endfsent();
|
2002-03-31 22:26:56 +00:00
|
|
|
} else {
|
|
|
|
for (i = 0; i < argc; i++)
|
2002-05-04 10:36:35 +00:00
|
|
|
DoFile(savedir, argv[i]);
|
1994-05-26 06:35:07 +00:00
|
|
|
}
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
|
|
|
/* Emit minimal output. */
|
2003-09-04 10:07:01 +00:00
|
|
|
if (nfound == 0) {
|
|
|
|
if (checkfor) {
|
2015-11-07 23:27:03 +00:00
|
|
|
if (verbose)
|
|
|
|
printf("No dump exists\n");
|
2003-09-04 10:07:01 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
2015-11-07 23:27:03 +00:00
|
|
|
if (verbose)
|
|
|
|
syslog(LOG_WARNING, "no dumps found");
|
|
|
|
} else if (nsaved == 0) {
|
|
|
|
if (nerr != 0) {
|
|
|
|
if (verbose)
|
|
|
|
syslog(LOG_WARNING, "unsaved dumps found but not saved");
|
|
|
|
exit(1);
|
|
|
|
} else if (verbose)
|
2002-05-05 01:04:00 +00:00
|
|
|
syslog(LOG_WARNING, "no unsaved dumps found");
|
2002-05-04 10:36:35 +00:00
|
|
|
}
|
High-level changes (user visible):
o Implement -c (clear) to clear previously kept headers (note that
dumps not cleared will remain until -c is used),
o Implement -f (force) to allow re-saving a previously saved dump,
o Implement -k (keep) and make clearing the dump header the default,
o Implement -v (verbose) and make most output conditional upon it,
o Emit minimal output for the non-verbose case with the assumption
that savecore is run mostly from within /etc/rc,
o Update usage message to reflect what is and what's not,
o mark -d as obsolete.
Low-level changes:
o Rename devname to device, for devname mirrors a global declaration
and GCC 3.x warns about it,
o Open the dump device R/W for clear and !keep to work,
o Reorder the locals of DoFile according to style(9),
o Remove newlines from strings passed to warn* and err*,
o Use stat(2) to check if a dump has been saved before,
o Truncate existing core and info files to support force,
o First check for the magic and the version before we complain about
parity errors. This prevents emitting parity error messages when
there's no dump,
o Keep track of the number of headers found and the number of headers
saved to support the minimal output,
o Close files we opened in DoFile. Not critical, but cleaner.
2002-04-13 08:20:15 +00:00
|
|
|
|
2002-03-31 22:26:56 +00:00
|
|
|
return (0);
|
1994-05-26 06:35:07 +00:00
|
|
|
}
|
2009-08-25 06:21:45 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
infohandler(int sig __unused)
|
|
|
|
{
|
|
|
|
got_siginfo = 1;
|
|
|
|
}
|