Changeset View
Changeset View
Standalone View
Standalone View
sbin/savecore/savecore.c
Context not available. | |||||
#include <paths.h> | #include <paths.h> | ||||
#include <signal.h> | #include <signal.h> | ||||
#include <stdarg.h> | #include <stdarg.h> | ||||
#include <stdbool.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
Context not available. | |||||
fclose(fp); | fclose(fp); | ||||
} | } | ||||
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); | |||||
} | |||||
static off_t | static off_t | ||||
file_size(const char *path) | file_size(const char *path) | ||||
{ | { | ||||
Context not available. | |||||
{ | { | ||||
(void)unlink("info.last"); | (void)unlink("info.last"); | ||||
(void)unlink("key.last"); | |||||
(void)unlink("vmcore.last"); | (void)unlink("vmcore.last"); | ||||
(void)unlink("vmcore.last.gz"); | (void)unlink("vmcore.last.gz"); | ||||
(void)unlink("vmcore_encrypted.last"); | |||||
(void)unlink("vmcore_encrypted.last.gz"); | |||||
(void)unlink("textdump.tar.last"); | (void)unlink("textdump.tar.last"); | ||||
(void)unlink("textdump.tar.last.gz"); | (void)unlink("textdump.tar.last.gz"); | ||||
} | } | ||||
Context not available. | |||||
#define BLOCKMASK (~(BLOCKSIZE-1)) | #define BLOCKMASK (~(BLOCKSIZE-1)) | ||||
static int | static int | ||||
DoRegularFile(int fd, off_t dumpsize, char *buf, const char *device, | DoRegularFile(int fd, bool isencrypted, off_t dumpsize, char *buf, | ||||
const char *filename, FILE *fp) | const char *device, const char *filename, FILE *fp) | ||||
{ | { | ||||
int he, hs, nr, nw, wl; | int he, hs, nr, nw, wl; | ||||
off_t dmpcnt, origsize; | off_t dmpcnt, origsize; | ||||
Context not available. | |||||
nerr++; | nerr++; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
if (compress) { | if (compress || isencrypted) { | ||||
nw = fwrite(buf, 1, wl, fp); | nw = fwrite(buf, 1, wl, fp); | ||||
} else { | } else { | ||||
for (nw = 0; nw < nr; nw = he) { | for (nw = 0; nw < nr; nw = he) { | ||||
Context not available. | |||||
{ | { | ||||
xo_handle_t *xostdout, *xoinfo; | xo_handle_t *xostdout, *xoinfo; | ||||
static char infoname[PATH_MAX], corename[PATH_MAX], linkname[PATH_MAX]; | static char infoname[PATH_MAX], corename[PATH_MAX], linkname[PATH_MAX]; | ||||
static char keyname[PATH_MAX]; | |||||
static char *buf = NULL; | static char *buf = NULL; | ||||
struct kerneldumpheader kdhf, kdhl; | struct kerneldumpheader kdhf, kdhl; | ||||
uint8_t *dumpkey; | |||||
off_t mediasize, dumpsize, firsthd, lasthd; | off_t mediasize, dumpsize, firsthd, lasthd; | ||||
FILE *info, *fp; | FILE *info, *fp; | ||||
mode_t oumask; | mode_t oumask; | ||||
Context not available. | |||||
int bounds, status; | int bounds, status; | ||||
u_int sectorsize, xostyle; | u_int sectorsize, xostyle; | ||||
int istextdump; | int istextdump; | ||||
uint32_t dumpkeysize; | |||||
bool isencrypted, ret; | |||||
bounds = getbounds(); | bounds = getbounds(); | ||||
mediasize = 0; | mediasize = 0; | ||||
Context not available. | |||||
goto closefd; | goto closefd; | ||||
} | } | ||||
jhb: While here, please fix 's/sizeof kdhf/sizeof(kdhf)/' | |||||
dumpsize = dtoh64(kdhl.dumplength); | dumpsize = dtoh64(kdhl.dumplength); | ||||
firsthd = lasthd - dumpsize - sizeof kdhf; | dumpkeysize = dtoh32(kdhl.dumpkeysize); | ||||
firsthd = lasthd - dumpsize - sizeof(kdhf) - dumpkeysize; | |||||
if (lseek(fd, firsthd, SEEK_SET) != firsthd || | if (lseek(fd, firsthd, SEEK_SET) != firsthd || | ||||
read(fd, &kdhf, sizeof(kdhf)) != sizeof(kdhf)) { | read(fd, &kdhf, sizeof(kdhf)) != sizeof(kdhf)) { | ||||
syslog(LOG_ERR, | syslog(LOG_ERR, | ||||
Context not available. | |||||
} | } | ||||
oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/ | oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/ | ||||
isencrypted = (dumpkeysize > 0); | |||||
if (compress) { | if (compress) { | ||||
snprintf(corename, sizeof(corename), "%s.%d.gz", | snprintf(corename, sizeof(corename), "%s.%d.gz", | ||||
istextdump ? "textdump.tar" : "vmcore", bounds); | istextdump ? "textdump.tar" : | ||||
(isencrypted ? "vmcore_encrypted" : "vmcore"), bounds); | |||||
fp = zopen(corename, "w"); | fp = zopen(corename, "w"); | ||||
} else { | } else { | ||||
snprintf(corename, sizeof(corename), "%s.%d", | snprintf(corename, sizeof(corename), "%s.%d", | ||||
istextdump ? "textdump.tar" : "vmcore", bounds); | istextdump ? "textdump.tar" : | ||||
(isencrypted ? "vmcore_encrypted" : "vmcore"), bounds); | |||||
fp = fopen(corename, "w"); | fp = fopen(corename, "w"); | ||||
} | } | ||||
if (fp == NULL) { | if (fp == NULL) { | ||||
Done Inline ActionsJust a personal preference: isencrypted = (dumpkeysize == 0); delphij: Just a personal preference:
isencrypted = (dumpkeysize == 0);
if (isencrypted) {
... | |||||
Done Inline ActionsYou would need: pjd: You would need:
isencrypted = (dumpkeysize > 0); | |||||
Context not available. | |||||
xo_finish_h(xoinfo); | xo_finish_h(xoinfo); | ||||
fclose(info); | fclose(info); | ||||
syslog(LOG_NOTICE, "writing %score to %s/%s", | if (isencrypted) { | ||||
compress ? "compressed " : "", savedir, corename); | 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; | |||||
} | |||||
Done Inline ActionsI don't think it's a big deal (because the key is still encrypted), but we should probably wipe dumpkey after writing it to disk to reduce exposure and for consistency. delphij: I don't think it's a big deal (because the key is still encrypted), but we should probably wipe… | |||||
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); | |||||
if (istextdump) { | if (istextdump) { | ||||
if (DoTextdumpFile(fd, dumpsize, lasthd, buf, device, | if (DoTextdumpFile(fd, dumpsize, lasthd, buf, device, | ||||
corename, fp) < 0) | corename, fp) < 0) | ||||
goto closeall; | goto closeall; | ||||
} else { | } else { | ||||
if (DoRegularFile(fd, dumpsize, buf, device, corename, fp) | if (DoRegularFile(fd, isencrypted, dumpsize, buf, device, | ||||
< 0) | corename, fp) < 0) { | ||||
goto closeall; | goto closeall; | ||||
} | |||||
} | } | ||||
if (verbose) | if (verbose) | ||||
printf("\n"); | printf("\n"); | ||||
Context not available. | |||||
syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", | syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", | ||||
savedir, "info.last"); | savedir, "info.last"); | ||||
} | } | ||||
if (isencrypted) { | |||||
if (symlink(keyname, "key.last") == -1) { | |||||
syslog(LOG_WARNING, | |||||
"unable to create symlink %s/%s: %m", savedir, | |||||
"key.last"); | |||||
} | |||||
Done Inline ActionsThis should create a "key.last" symlink as well (and symlinks_remove() needs to be updated to remove any preexisting key.last symlink). jhb: This should create a "key.last" symlink as well (and symlinks_remove() needs to be updated to… | |||||
} | |||||
if (compress) { | if (compress) { | ||||
snprintf(linkname, sizeof(linkname), "%s.last.gz", | snprintf(linkname, sizeof(linkname), "%s.last.gz", | ||||
istextdump ? "textdump.tar" : "vmcore"); | istextdump ? "textdump.tar" : | ||||
(isencrypted ? "vmcore_encrypted" : "vmcore")); | |||||
} else { | } else { | ||||
snprintf(linkname, sizeof(linkname), "%s.last", | snprintf(linkname, sizeof(linkname), "%s.last", | ||||
istextdump ? "textdump.tar" : "vmcore"); | istextdump ? "textdump.tar" : | ||||
(isencrypted ? "vmcore_encrypted" : "vmcore")); | |||||
} | } | ||||
if (symlink(corename, linkname) == -1) { | if (symlink(corename, linkname) == -1) { | ||||
syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", | syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", | ||||
Context not available. |
While here, please fix 's/sizeof kdhf/sizeof(kdhf)/'