Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153414247
D18458.id51941.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
25 KB
Referenced Files
None
Subscribers
None
D18458.id51941.diff
View Options
Index: sbin/savecore/Makefile
===================================================================
--- sbin/savecore/Makefile
+++ sbin/savecore/Makefile
@@ -6,7 +6,14 @@
VAR_CRASH_MODE= 0750
CONFSDIR= VAR_CRASH
PROG= savecore
-LIBADD= z xo
+LIBADD= xo z
MAN= savecore.8
+.include <src.opts.mk>
+
+.if ${MK_CASPER} != "no" && !defined(RESCUE)
+CFLAGS+= -DWITH_CASPER
+LIBADD+= casper cap_fileargs cap_syslog
+.endif
+
.include <bsd.prog.mk>
Index: sbin/savecore/savecore.c
===================================================================
--- sbin/savecore/savecore.c
+++ sbin/savecore/savecore.c
@@ -70,6 +70,8 @@
#include <sys/kerneldump.h>
#include <sys/mount.h>
#include <sys/stat.h>
+
+#include <capsicum_helpers.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -84,6 +86,11 @@
#include <syslog.h>
#include <time.h>
#include <unistd.h>
+
+#include <libcasper.h>
+#include <casper/cap_fileargs.h>
+#include <casper/cap_syslog.h>
+
#include <libxo/xo.h>
/* The size of the buffer used for I/O. */
@@ -93,15 +100,57 @@
#define STATUS_GOOD 1
#define STATUS_UNKNOWN 2
+static cap_channel_t *capsyslog;
+static fileargs_t *capfa;
static int checkfor, compress, clear, force, keep, verbose; /* flags */
static int nfound, nsaved, nerr; /* statistics */
static int maxdumps;
-extern FILE *zopen(const char *, const char *);
+extern FILE *zdopen(int, const char *);
static sig_atomic_t got_siginfo;
static void infohandler(int);
+static void
+logmsg(int pri, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (capsyslog != NULL)
+ cap_vsyslog(capsyslog, pri, fmt, ap);
+ else
+ vsyslog(pri, fmt, ap);
+ va_end(ap);
+}
+
+static FILE *
+xfopenat(int dirfd, const char *path, int flags, const char *modestr, ...)
+{
+ va_list ap;
+ FILE *fp;
+ mode_t mode;
+ int error, fd;
+
+ if ((flags & O_CREAT) == O_CREAT) {
+ va_start(ap, modestr);
+ mode = (mode_t)va_arg(ap, int);
+ va_end(ap);
+ } else
+ mode = 0;
+
+ fd = openat(dirfd, path, flags, mode);
+ if (fd < 0)
+ return (NULL);
+ fp = fdopen(fd, modestr);
+ if (fp == NULL) {
+ error = errno;
+ (void)close(fd);
+ errno = error;
+ }
+ return (fp);
+}
+
static void
printheader(xo_handle_t *xo, const struct kerneldumpheader *h,
const char *device, int bounds, const int status)
@@ -166,7 +215,7 @@
}
static int
-getbounds(void)
+getbounds(int savedirfd)
{
FILE *fp;
char buf[6];
@@ -181,17 +230,16 @@
ret = 0;
- if ((fp = fopen("bounds", "r")) == NULL) {
+ if ((fp = xfopenat(savedirfd, "bounds", O_RDONLY, "r")) == NULL) {
if (verbose)
printf("unable to open bounds file, using 0\n");
return (ret);
}
-
- if (fgets(buf, sizeof buf, fp) == NULL) {
+ if (fgets(buf, sizeof(buf), fp) == NULL) {
if (feof(fp))
- syslog(LOG_WARNING, "bounds file is empty, using 0");
+ logmsg(LOG_WARNING, "bounds file is empty, using 0");
else
- syslog(LOG_WARNING, "bounds file: %s", strerror(errno));
+ logmsg(LOG_WARNING, "bounds file: %s", strerror(errno));
fclose(fp);
return (ret);
}
@@ -199,18 +247,19 @@
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");
+ logmsg(LOG_WARNING, "invalid value found in bounds, using 0");
fclose(fp);
return (ret);
}
static void
-writebounds(int bounds)
+writebounds(int savedirfd, int bounds)
{
FILE *fp;
- if ((fp = fopen("bounds", "w")) == NULL) {
- syslog(LOG_WARNING, "unable to write to bounds file: %m");
+ if ((fp = xfopenat(savedirfd, "bounds", O_WRONLY | O_CREAT | O_TRUNC,
+ "w", 0644)) < 0) {
+ logmsg(LOG_WARNING, "unable to write to bounds file: %m");
return;
}
@@ -222,19 +271,20 @@
}
static bool
-writekey(const char *keyname, uint8_t *dumpkey, uint32_t dumpkeysize)
+writekey(int savedirfd, const char *keyname, uint8_t *dumpkey,
+ uint32_t dumpkeysize)
{
int fd;
- fd = open(keyname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ fd = openat(savedirfd, keyname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd == -1) {
- syslog(LOG_ERR, "Unable to open %s to write the key: %m.",
+ logmsg(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);
+ logmsg(LOG_ERR, "Unable to write the key to %s: %m.", keyname);
close(fd);
return (false);
}
@@ -244,18 +294,18 @@
}
static off_t
-file_size(const char *path)
+file_size(int savedirfd, const char *path)
{
struct stat sb;
- /* Ignore all errors, those file may not exists. */
- if (stat(path, &sb) == -1)
+ /* Ignore all errors, this file may not exist. */
+ if (fstatat(savedirfd, path, &sb, 0) == -1)
return (0);
return (sb.st_size);
}
static off_t
-saved_dump_size(int bounds)
+saved_dump_size(int savedirfd, int bounds)
{
static char path[PATH_MAX];
off_t dumpsize;
@@ -263,53 +313,53 @@
dumpsize = 0;
(void)snprintf(path, sizeof(path), "info.%d", bounds);
- dumpsize += file_size(path);
+ dumpsize += file_size(savedirfd, path);
(void)snprintf(path, sizeof(path), "vmcore.%d", bounds);
- dumpsize += file_size(path);
+ dumpsize += file_size(savedirfd, path);
(void)snprintf(path, sizeof(path), "vmcore.%d.gz", bounds);
- dumpsize += file_size(path);
+ dumpsize += file_size(savedirfd, path);
(void)snprintf(path, sizeof(path), "vmcore.%d.zst", bounds);
- dumpsize += file_size(path);
+ dumpsize += file_size(savedirfd, path);
(void)snprintf(path, sizeof(path), "textdump.tar.%d", bounds);
- dumpsize += file_size(path);
+ dumpsize += file_size(savedirfd, path);
(void)snprintf(path, sizeof(path), "textdump.tar.%d.gz", bounds);
- dumpsize += file_size(path);
+ dumpsize += file_size(savedirfd, path);
return (dumpsize);
}
static void
-saved_dump_remove(int bounds)
+saved_dump_remove(int savedirfd, int bounds)
{
static char path[PATH_MAX];
(void)snprintf(path, sizeof(path), "info.%d", bounds);
- (void)unlink(path);
+ (void)unlinkat(savedirfd, path, 0);
(void)snprintf(path, sizeof(path), "vmcore.%d", bounds);
- (void)unlink(path);
+ (void)unlinkat(savedirfd, path, 0);
(void)snprintf(path, sizeof(path), "vmcore.%d.gz", bounds);
- (void)unlink(path);
+ (void)unlinkat(savedirfd, path, 0);
(void)snprintf(path, sizeof(path), "vmcore.%d.zst", bounds);
- (void)unlink(path);
+ (void)unlinkat(savedirfd, path, 0);
(void)snprintf(path, sizeof(path), "textdump.tar.%d", bounds);
- (void)unlink(path);
+ (void)unlinkat(savedirfd, path, 0);
(void)snprintf(path, sizeof(path), "textdump.tar.%d.gz", bounds);
- (void)unlink(path);
+ (void)unlinkat(savedirfd, path, 0);
}
static void
-symlinks_remove(void)
+symlinks_remove(int savedirfd)
{
- (void)unlink("info.last");
- (void)unlink("key.last");
- (void)unlink("vmcore.last");
- (void)unlink("vmcore.last.gz");
- (void)unlink("vmcore.last.zst");
- (void)unlink("vmcore_encrypted.last");
- (void)unlink("vmcore_encrypted.last.gz");
- (void)unlink("textdump.tar.last");
- (void)unlink("textdump.tar.last.gz");
+ (void)unlinkat(savedirfd, "info.last", 0);
+ (void)unlinkat(savedirfd, "key.last", 0);
+ (void)unlinkat(savedirfd, "vmcore.last", 0);
+ (void)unlinkat(savedirfd, "vmcore.last.gz", 0);
+ (void)unlinkat(savedirfd, "vmcore.last.zst", 0);
+ (void)unlinkat(savedirfd, "vmcore_encrypted.last", 0);
+ (void)unlinkat(savedirfd, "vmcore_encrypted.last.gz", 0);
+ (void)unlinkat(savedirfd, "textdump.tar.last", 0);
+ (void)unlinkat(savedirfd, "textdump.tar.last.gz", 0);
}
/*
@@ -317,21 +367,21 @@
* save directory.
*/
static int
-check_space(const char *savedir, off_t dumpsize, int bounds)
+check_space(const char *savedir, int savedirfd, off_t dumpsize, int bounds)
{
+ char buf[100];
+ struct statfs fsbuf;
FILE *fp;
off_t available, minfree, spacefree, totfree, needed;
- struct statfs fsbuf;
- char buf[100];
- if (statfs(".", &fsbuf) < 0) {
- syslog(LOG_ERR, "%s: %m", savedir);
+ if (fstatfs(savedirfd, &fsbuf) < 0) {
+ logmsg(LOG_ERR, "%s: %m", savedir);
exit(1);
}
spacefree = ((off_t) fsbuf.f_bavail * fsbuf.f_bsize) / 1024;
totfree = ((off_t) fsbuf.f_bfree * fsbuf.f_bsize) / 1024;
- if ((fp = fopen("minfree", "r")) == NULL)
+ if ((fp = xfopenat(savedirfd, "minfree", O_RDONLY, "r")) == NULL)
minfree = 0;
else {
if (fgets(buf, sizeof(buf), fp) == NULL)
@@ -350,7 +400,7 @@
minfree = -1;
}
if (minfree < 0)
- syslog(LOG_WARNING,
+ logmsg(LOG_WARNING,
"`minfree` didn't contain a valid size "
"(`%s`). Defaulting to 0", buf);
}
@@ -359,9 +409,9 @@
available = minfree > 0 ? spacefree - minfree : totfree;
needed = dumpsize / 1024 + 2; /* 2 for info file */
- needed -= saved_dump_size(bounds);
+ needed -= saved_dump_size(savedirfd, bounds);
if (available < needed) {
- syslog(LOG_WARNING,
+ logmsg(LOG_WARNING,
"no dump: not enough free space on device (need at least "
"%jdkB for dump; %jdkB available; %jdkB reserved)",
(intmax_t)needed,
@@ -370,7 +420,7 @@
return (0);
}
if (spacefree - needed < 0)
- syslog(LOG_WARNING,
+ logmsg(LOG_WARNING,
"dump performed, but free space threshold crossed");
return (1);
}
@@ -402,10 +452,10 @@
nr = read(fd, buf, roundup(wl, sectorsize));
if (nr != (int)roundup(wl, sectorsize)) {
if (nr == 0)
- syslog(LOG_WARNING,
+ logmsg(LOG_WARNING,
"WARNING: EOF on dump device");
else
- syslog(LOG_ERR, "read error on %s: %m", device);
+ logmsg(LOG_ERR, "read error on %s: %m", device);
nerr++;
return (-1);
}
@@ -451,9 +501,9 @@
}
}
if (nw != wl) {
- syslog(LOG_ERR,
+ logmsg(LOG_ERR,
"write error on %s file: %m", filename);
- syslog(LOG_WARNING,
+ logmsg(LOG_WARNING,
"WARNING: vmcore may be incomplete");
nerr++;
return (-1);
@@ -490,7 +540,7 @@
dmpcnt = 0;
wl = 512;
if ((dumpsize % wl) != 0) {
- syslog(LOG_ERR, "textdump uneven multiple of 512 on %s",
+ logmsg(LOG_ERR, "textdump uneven multiple of 512 on %s",
device);
nerr++;
return (-1);
@@ -499,18 +549,18 @@
nr = pread(fd, buf, wl, lasthd - (totsize - dumpsize) - wl);
if (nr != wl) {
if (nr == 0)
- syslog(LOG_WARNING,
+ logmsg(LOG_WARNING,
"WARNING: EOF on dump device");
else
- syslog(LOG_ERR, "read error on %s: %m", device);
+ logmsg(LOG_ERR, "read error on %s: %m", device);
nerr++;
return (-1);
}
nw = fwrite(buf, 1, wl, fp);
if (nw != wl) {
- syslog(LOG_ERR,
+ logmsg(LOG_ERR,
"write error on %s file: %m", filename);
- syslog(LOG_WARNING,
+ logmsg(LOG_WARNING,
"WARNING: textdump may be incomplete");
nerr++;
return (-1);
@@ -526,7 +576,7 @@
}
static void
-DoFile(const char *savedir, const char *device)
+DoFile(const char *savedir, int savedirfd, const char *device)
{
xo_handle_t *xostdout, *xoinfo;
static char infoname[PATH_MAX], corename[PATH_MAX], linkname[PATH_MAX];
@@ -536,22 +586,21 @@
struct kerneldumpheader kdhf, kdhl;
uint8_t *dumpkey;
off_t mediasize, dumpextent, dumplength, firsthd, lasthd;
- FILE *info, *fp;
- mode_t oumask;
- int fd, fdinfo, error;
+ FILE *core, *info;
+ int fdcore, fddev, error;
int bounds, status;
u_int sectorsize, xostyle;
uint32_t dumpkeysize;
bool iscompressed, isencrypted, istextdump, ret;
- bounds = getbounds();
+ bounds = getbounds(savedirfd);
dumpkey = NULL;
mediasize = 0;
status = STATUS_UNKNOWN;
xostdout = xo_create_to_file(stdout, XO_STYLE_TEXT, 0);
if (xostdout == NULL) {
- syslog(LOG_ERR, "%s: %m", infoname);
+ logmsg(LOG_ERR, "%s: %m", infoname);
return;
}
@@ -561,7 +610,7 @@
if (buf == NULL) {
buf = malloc(BUFFERSIZE);
if (buf == NULL) {
- syslog(LOG_ERR, "%m");
+ logmsg(LOG_ERR, "%m");
return;
}
}
@@ -569,17 +618,17 @@
if (verbose)
printf("checking for kernel dump on device %s\n", device);
- fd = open(device, (checkfor || keep) ? O_RDONLY : O_RDWR);
- if (fd < 0) {
- syslog(LOG_ERR, "%s: %m", device);
+ fddev = fileargs_open(capfa, device);
+ if (fddev < 0) {
+ logmsg(LOG_ERR, "%s: %m", device);
return;
}
- error = ioctl(fd, DIOCGMEDIASIZE, &mediasize);
+ error = ioctl(fddev, DIOCGMEDIASIZE, &mediasize);
if (!error)
- error = ioctl(fd, DIOCGSECTORSIZE, §orsize);
+ error = ioctl(fddev, DIOCGSECTORSIZE, §orsize);
if (error) {
- syslog(LOG_ERR,
+ logmsg(LOG_ERR,
"couldn't find media and/or sector size of %s: %m", device);
goto closefd;
}
@@ -590,7 +639,7 @@
}
if (sectorsize < sizeof(kdhl)) {
- syslog(LOG_ERR,
+ logmsg(LOG_ERR,
"Sector size is less the kernel dump header %zu",
sizeof(kdhl));
goto closefd;
@@ -599,12 +648,12 @@
lasthd = mediasize - sectorsize;
temp = malloc(sectorsize);
if (temp == NULL) {
- syslog(LOG_ERR, "%m");
+ logmsg(LOG_ERR, "%m");
goto closefd;
}
- if (lseek(fd, lasthd, SEEK_SET) != lasthd ||
- read(fd, temp, sectorsize) != (ssize_t)sectorsize) {
- syslog(LOG_ERR,
+ if (lseek(fddev, lasthd, SEEK_SET) != lasthd ||
+ read(fddev, temp, sectorsize) != (ssize_t)sectorsize) {
+ logmsg(LOG_ERR,
"error reading last dump header at offset %lld in %s: %m",
(long long)lasthd, device);
goto closefd;
@@ -617,7 +666,7 @@
device);
istextdump = true;
if (dtoh32(kdhl.version) != KERNELDUMP_TEXT_VERSION) {
- syslog(LOG_ERR,
+ logmsg(LOG_ERR,
"unknown version (%d) in last dump header on %s",
dtoh32(kdhl.version), device);
@@ -627,7 +676,7 @@
}
} else if (compare_magic(&kdhl, KERNELDUMPMAGIC)) {
if (dtoh32(kdhl.version) != KERNELDUMPVERSION) {
- syslog(LOG_ERR,
+ logmsg(LOG_ERR,
"unknown version (%d) in last dump header on %s",
dtoh32(kdhl.version), device);
@@ -646,7 +695,7 @@
iscompressed = true;
break;
default:
- syslog(LOG_ERR, "unknown compression type %d on %s",
+ logmsg(LOG_ERR, "unknown compression type %d on %s",
kdhl.compression, device);
break;
}
@@ -664,11 +713,11 @@
printf("forcing magic on %s\n", device);
memcpy(kdhl.magic, KERNELDUMPMAGIC, sizeof(kdhl.magic));
} else {
- syslog(LOG_ERR, "unable to force dump - bad magic");
+ logmsg(LOG_ERR, "unable to force dump - bad magic");
goto closefd;
}
if (dtoh32(kdhl.version) != KERNELDUMPVERSION) {
- syslog(LOG_ERR,
+ logmsg(LOG_ERR,
"unknown version (%d) in last dump header on %s",
dtoh32(kdhl.version), device);
@@ -683,7 +732,7 @@
goto nuke;
if (kerneldump_parity(&kdhl)) {
- syslog(LOG_ERR,
+ logmsg(LOG_ERR,
"parity error on last dump header on %s", device);
nerr++;
status = STATUS_BAD;
@@ -694,9 +743,9 @@
dumplength = dtoh64(kdhl.dumplength);
dumpkeysize = dtoh32(kdhl.dumpkeysize);
firsthd = lasthd - dumpextent - sectorsize - dumpkeysize;
- if (lseek(fd, firsthd, SEEK_SET) != firsthd ||
- read(fd, temp, sectorsize) != (ssize_t)sectorsize) {
- syslog(LOG_ERR,
+ if (lseek(fddev, firsthd, SEEK_SET) != firsthd ||
+ read(fddev, temp, sectorsize) != (ssize_t)sectorsize) {
+ logmsg(LOG_ERR,
"error reading first dump header at offset %lld in %s: %m",
(long long)firsthd, device);
nerr++;
@@ -714,7 +763,7 @@
}
if (memcmp(&kdhl, &kdhf, sizeof(kdhl))) {
- syslog(LOG_ERR,
+ logmsg(LOG_ERR,
"first and last dump headers disagree on %s", device);
nerr++;
status = STATUS_BAD;
@@ -726,77 +775,79 @@
if (checkfor) {
printf("A dump exists on %s\n", device);
- close(fd);
+ close(fddev);
exit(0);
}
if (kdhl.panicstring[0] != '\0')
- syslog(LOG_ALERT, "reboot after panic: %.*s",
+ logmsg(LOG_ALERT, "reboot after panic: %.*s",
(int)sizeof(kdhl.panicstring), kdhl.panicstring);
else
- syslog(LOG_ALERT, "reboot");
+ logmsg(LOG_ALERT, "reboot");
if (verbose)
printf("Checking for available free space\n");
- if (!check_space(savedir, dumplength, bounds)) {
+ if (!check_space(savedir, savedirfd, dumplength, bounds)) {
nerr++;
goto closefd;
}
- writebounds(bounds + 1);
+ writebounds(savedirfd, bounds + 1);
- saved_dump_remove(bounds);
+ saved_dump_remove(savedirfd, bounds);
snprintf(infoname, sizeof(infoname), "info.%d", bounds);
/*
* Create or overwrite any existing dump header files.
*/
- fdinfo = open(infoname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
- if (fdinfo < 0) {
- syslog(LOG_ERR, "%s: %m", infoname);
+ if ((info = xfopenat(savedirfd, infoname,
+ O_WRONLY | O_CREAT | O_TRUNC, "w", 0600)) == NULL) {
+ logmsg(LOG_ERR, "open(%s): %m", infoname);
nerr++;
goto closefd;
}
- 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",
istextdump ? "textdump.tar" :
(isencrypted ? "vmcore_encrypted" : "vmcore"), bounds);
- fp = zopen(corename, "w");
- } else if (iscompressed && !isencrypted) {
+ else if (iscompressed && !isencrypted)
snprintf(corename, sizeof(corename), "vmcore.%d.%s", bounds,
(kdhl.compression == KERNELDUMP_COMP_GZIP) ? "gz" : "zst");
- fp = fopen(corename, "w");
- } else {
+ else
snprintf(corename, sizeof(corename), "%s.%d",
istextdump ? "textdump.tar" :
(isencrypted ? "vmcore_encrypted" : "vmcore"), bounds);
- fp = fopen(corename, "w");
- }
- if (fp == NULL) {
- syslog(LOG_ERR, "%s: %m", corename);
- close(fdinfo);
+ fdcore = openat(savedirfd, corename, O_WRONLY | O_CREAT | O_TRUNC,
+ 0600);
+ if (fdcore < 0) {
+ logmsg(LOG_ERR, "open(%s): %m", corename);
+ fclose(info);
nerr++;
goto closefd;
}
- (void)umask(oumask);
- info = fdopen(fdinfo, "w");
-
- if (info == NULL) {
- syslog(LOG_ERR, "fdopen failed: %m");
+ if (compress)
+ core = zdopen(fdcore, "w");
+ else
+ core = fdopen(fdcore, "w");
+ if (core == NULL) {
+ logmsg(LOG_ERR, "%s: %m", corename);
+ (void)close(fdcore);
+ (void)fclose(info);
nerr++;
- goto closeall;
+ goto closefd;
}
+ fdcore = -1;
xostyle = xo_get_style(NULL);
xoinfo = xo_create_to_file(info, xostyle, 0);
if (xoinfo == NULL) {
- syslog(LOG_ERR, "%s: %m", infoname);
+ logmsg(LOG_ERR, "%s: %m", infoname);
+ fclose(info);
nerr++;
goto closeall;
}
@@ -814,19 +865,19 @@
if (isencrypted) {
dumpkey = calloc(1, dumpkeysize);
if (dumpkey == NULL) {
- syslog(LOG_ERR, "Unable to allocate kernel dump key.");
+ logmsg(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.");
+ if (read(fddev, dumpkey, dumpkeysize) != (ssize_t)dumpkeysize) {
+ logmsg(LOG_ERR, "Unable to read kernel dump key: %m.");
nerr++;
goto closeall;
}
snprintf(keyname, sizeof(keyname), "key.%d", bounds);
- ret = writekey(keyname, dumpkey, dumpkeysize);
+ ret = writekey(savedirfd, keyname, dumpkey, dumpkeysize);
explicit_bzero(dumpkey, dumpkeysize);
if (!ret) {
nerr++;
@@ -834,38 +885,38 @@
}
}
- syslog(LOG_NOTICE, "writing %s%score to %s/%s",
+ logmsg(LOG_NOTICE, "writing %s%score to %s/%s",
isencrypted ? "encrypted " : "", compress ? "compressed " : "",
savedir, corename);
if (istextdump) {
- if (DoTextdumpFile(fd, dumplength, lasthd, buf, device,
- corename, fp) < 0)
+ if (DoTextdumpFile(fddev, dumplength, lasthd, buf, device,
+ corename, core) < 0)
goto closeall;
} else {
- if (DoRegularFile(fd, dumplength, sectorsize,
+ if (DoRegularFile(fddev, dumplength, sectorsize,
!(compress || iscompressed || isencrypted), buf, device,
- corename, fp) < 0) {
+ corename, core) < 0) {
goto closeall;
}
}
if (verbose)
printf("\n");
- if (fclose(fp) < 0) {
- syslog(LOG_ERR, "error on %s: %m", corename);
+ if (fclose(core) < 0) {
+ logmsg(LOG_ERR, "error on %s: %m", corename);
nerr++;
goto closefd;
}
- symlinks_remove();
- if (symlink(infoname, "info.last") == -1) {
- syslog(LOG_WARNING, "unable to create symlink %s/%s: %m",
+ symlinks_remove(savedirfd);
+ if (symlinkat(infoname, savedirfd, "info.last") == -1) {
+ logmsg(LOG_WARNING, "unable to create symlink %s/%s: %m",
savedir, "info.last");
}
if (isencrypted) {
- if (symlink(keyname, "key.last") == -1) {
- syslog(LOG_WARNING,
+ if (symlinkat(keyname, savedirfd, "key.last") == -1) {
+ logmsg(LOG_WARNING,
"unable to create symlink %s/%s: %m", savedir,
"key.last");
}
@@ -880,8 +931,8 @@
istextdump ? "textdump.tar" :
(isencrypted ? "vmcore_encrypted" : "vmcore"));
}
- if (symlink(corename, linkname) == -1) {
- syslog(LOG_WARNING, "unable to create symlink %s/%s: %m",
+ if (symlinkat(corename, savedirfd, linkname) == -1) {
+ logmsg(LOG_WARNING, "unable to create symlink %s/%s: %m",
savedir, linkname);
}
@@ -896,25 +947,106 @@
printf("clearing dump header\n");
memcpy(kdhl.magic, KERNELDUMPMAGIC_CLEARED, sizeof(kdhl.magic));
memcpy(temp, &kdhl, sizeof(kdhl));
- if (lseek(fd, lasthd, SEEK_SET) != lasthd ||
- write(fd, temp, sectorsize) != (ssize_t)sectorsize)
- syslog(LOG_ERR,
+ if (lseek(fddev, lasthd, SEEK_SET) != lasthd ||
+ write(fddev, temp, sectorsize) != (ssize_t)sectorsize)
+ logmsg(LOG_ERR,
"error while clearing the dump header: %m");
}
xo_close_container_h(xostdout, "crashdump");
xo_finish_h(xostdout);
free(dumpkey);
free(temp);
- close(fd);
+ close(fddev);
return;
closeall:
- fclose(fp);
+ fclose(core);
closefd:
free(dumpkey);
free(temp);
- close(fd);
+ close(fddev);
+}
+
+static char **
+enum_dumpdevs(int *argcp)
+{
+ struct fstab *fsp;
+ char **argv;
+ int argc, n;
+
+ /*
+ * We cannot use getfsent(3) in capability mode, so we must
+ * scan /etc/fstab and build up a list of candidate devices
+ * before proceeding.
+ */
+ argc = 0;
+ n = 8;
+ argv = malloc(n * sizeof(*argv));
+ if (argv == NULL) {
+ logmsg(LOG_ERR, "malloc(): %m");
+ exit(1);
+ }
+ for (;;) {
+ fsp = getfsent();
+ if (fsp == NULL)
+ break;
+ if (strcmp(fsp->fs_vfstype, "swap") != 0 &&
+ strcmp(fsp->fs_vfstype, "dump") != 0)
+ continue;
+ if (argc >= n) {
+ n *= 2;
+ argv = realloc(argv, n * sizeof(*argv));
+ if (argv == NULL) {
+ logmsg(LOG_ERR, "realloc(): %m");
+ exit(1);
+ }
+ }
+ argv[argc] = strdup(fsp->fs_spec);
+ if (argv[argc] == NULL) {
+ logmsg(LOG_ERR, "strdup(): %m");
+ exit(1);
+ }
+ argc++;
+ }
+ *argcp = argc;
+ return (argv);
+}
+
+static void
+init_caps(int argc, char **argv)
+{
+ cap_rights_t rights;
+ cap_channel_t *capcas;
+
+ capcas = cap_init();
+ if (capcas == NULL) {
+ logmsg(LOG_ERR, "cap_init(): %m");
+ exit(1);
+ }
+ /*
+ * The fileargs capability does not currently provide a way to limit
+ * ioctls.
+ */
+ (void)cap_rights_init(&rights, CAP_PREAD, CAP_WRITE, CAP_IOCTL);
+ capfa = fileargs_init(argc, argv, checkfor || keep ? O_RDONLY : O_RDWR,
+ 0, &rights);
+ if (capfa == NULL) {
+ logmsg(LOG_ERR, "fileargs_init(): %m");
+ exit(1);
+ }
+ caph_cache_catpages();
+ caph_cache_tzdata();
+ if (caph_enter_casper() != 0) {
+ logmsg(LOG_ERR, "caph_enter_casper(): %m");
+ exit(1);
+ }
+ capsyslog = cap_service_open(capcas, "system.syslog");
+ if (capsyslog == NULL) {
+ logmsg(LOG_ERR, "cap_service_open(system.syslog): %m");
+ exit(1);
+ }
+ cap_close(capcas);
}
static void
@@ -930,12 +1062,13 @@
int
main(int argc, char **argv)
{
- const char *savedir = ".";
- struct fstab *fsp;
- int i, ch, error;
+ cap_rights_t rights;
+ const char *savedir;
+ int i, ch, error, savedirfd;
checkfor = compress = clear = force = keep = verbose = 0;
nfound = nsaved = nerr = 0;
+ savedir = ".";
openlog("savecore", LOG_PERROR, LOG_DAEMON);
signal(SIGINFO, infohandler);
@@ -961,7 +1094,7 @@
case 'm':
maxdumps = atoi(optarg);
if (maxdumps <= 0) {
- syslog(LOG_ERR, "Invalid maxdump value");
+ logmsg(LOG_ERR, "Invalid maxdump value");
exit(1);
}
break;
@@ -986,28 +1119,34 @@
if (argc >= 1 && !checkfor && !clear) {
error = chdir(argv[0]);
if (error) {
- syslog(LOG_ERR, "chdir(%s): %m", argv[0]);
+ logmsg(LOG_ERR, "chdir(%s): %m", argv[0]);
exit(1);
}
savedir = argv[0];
argc--;
argv++;
}
- if (argc == 0) {
- for (;;) {
- fsp = getfsent();
- if (fsp == NULL)
- break;
- if (strcmp(fsp->fs_vfstype, "swap") &&
- strcmp(fsp->fs_vfstype, "dump"))
- continue;
- DoFile(savedir, fsp->fs_spec);
- }
- endfsent();
- } else {
- for (i = 0; i < argc; i++)
- DoFile(savedir, argv[i]);
+ if (argc == 0)
+ argv = enum_dumpdevs(&argc);
+
+ savedirfd = open(savedir, O_RDONLY | O_DIRECTORY);
+ if (savedirfd < 0) {
+ logmsg(LOG_ERR, "open(%s): %m", savedir);
+ exit(1);
}
+ (void)cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL, CAP_FSTATAT,
+ CAP_FSTATFS, CAP_PREAD, CAP_SYMLINKAT, CAP_FTRUNCATE, CAP_UNLINKAT,
+ CAP_WRITE);
+ if (caph_rights_limit(savedirfd, &rights) < 0) {
+ logmsg(LOG_ERR, "cap_rights_limit(): %m");
+ exit(1);
+ }
+
+ /* Enter capability mode. */
+ init_caps(argc, argv);
+
+ for (i = 0; i < argc; i++)
+ DoFile(savedir, savedirfd, argv[i]);
/* Emit minimal output. */
if (nfound == 0) {
@@ -1017,15 +1156,15 @@
exit(1);
}
if (verbose)
- syslog(LOG_WARNING, "no dumps found");
+ logmsg(LOG_WARNING, "no dumps found");
} else if (nsaved == 0) {
if (nerr != 0) {
if (verbose)
- syslog(LOG_WARNING,
+ logmsg(LOG_WARNING,
"unsaved dumps found but not saved");
exit(1);
} else if (verbose)
- syslog(LOG_WARNING, "no unsaved dumps found");
+ logmsg(LOG_WARNING, "no unsaved dumps found");
}
return (0);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 22, 12:58 AM (2 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31943344
Default Alt Text
D18458.id51941.diff (25 KB)
Attached To
Mode
D18458: Capsicumize savecore(8).
Attached
Detach File
Event Timeline
Log In to Comment