aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/man/man5/core.525
-rw-r--r--sys/conf/files2
-rw-r--r--sys/ddb/db_textdump.c6
-rw-r--r--sys/kern/imgact_elf.c60
-rw-r--r--sys/kern/kern_shutdown.c140
-rw-r--r--sys/kern/kern_sig.c40
-rw-r--r--sys/kern/subr_compressor.c (renamed from sys/kern/kern_gzio.c)282
-rw-r--r--sys/sys/compressor.h (renamed from sys/sys/gzio.h)31
-rw-r--r--sys/sys/conf.h4
-rw-r--r--sys/sys/imgact.h2
10 files changed, 324 insertions, 268 deletions
diff --git a/share/man/man5/core.5 b/share/man/man5/core.5
index dcc57baa1f39..e050cf80d56c 100644
--- a/share/man/man5/core.5
+++ b/share/man/man5/core.5
@@ -28,7 +28,7 @@
.\" @(#)core.5 8.3 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
-.Dd October 5, 2015
+.Dd January 8, 2018
.Dt CORE 5
.Os
.Sh NAME
@@ -67,8 +67,8 @@ generating it).
.Pp
The following format specifiers may be used in the
.Va kern.corefile
-sysctl to insert additional information into the resulting core file
-name:
+sysctl to insert additional information into the resulting core
+filename:
.Bl -tag -width "1234567890" -compact -offset "12345"
.It Em \&%H
Machine hostname.
@@ -108,17 +108,17 @@ is included in the kernel configuration file:
GZIO
.El
.Pp
-When the GZIO option is included, the following sysctls control whether core
-files will be compressed:
-.Bl -tag -width "kern.compress_user_cores_gzlevel" -compact -offset "12345"
-.It Em kern.compress_user_cores_gzlevel
-Gzip compression level.
-Defaults to 6.
+The following sysctl control core file compression:
+.Bl -tag -width "kern.compress_user_cores_level" -compact -offset "12345"
.It Em kern.compress_user_cores
-Actually compress user cores.
-Compressed core files will have a suffix of
+Enable compression of user cores.
+A value of 1 configures gzip compression.
+gzip-compressed core files will have a suffix of
.Ql .gz
-appended to them.
+appended to their filenames.
+.It Em kern.compress_user_cores_level
+Compression level.
+Defaults to 6.
.El
.Sh NOTES
Corefiles are written with open file descriptor information as an ELF note.
@@ -153,6 +153,7 @@ command can be used:
.Dl sysctl kern.corefile=/var/coredumps/\&%U/\&%N.core
.Sh SEE ALSO
.Xr gdb 1 ,
+.Xr gzip 1 ,
.Xr kgdb 1 ,
.Xr setrlimit 2 ,
.Xr sigaction 2 ,
diff --git a/sys/conf/files b/sys/conf/files
index b0524efbd77e..b723aa52f691 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -3767,7 +3767,6 @@ kern/kern_exit.c standard
kern/kern_fail.c standard
kern/kern_ffclock.c standard
kern/kern_fork.c standard
-kern/kern_gzio.c optional gzio
kern/kern_hhook.c standard
kern/kern_idle.c standard
kern/kern_intr.c standard
@@ -3843,6 +3842,7 @@ kern/subr_bus_dma.c standard
kern/subr_bufring.c standard
kern/subr_capability.c standard
kern/subr_clock.c standard
+kern/subr_compressor.c standard
kern/subr_counter.c standard
kern/subr_devstat.c standard
kern/subr_disk.c standard
diff --git a/sys/ddb/db_textdump.c b/sys/ddb/db_textdump.c
index 8845781621f7..a85d1ddca3eb 100644
--- a/sys/ddb/db_textdump.c
+++ b/sys/ddb/db_textdump.c
@@ -454,8 +454,8 @@ textdump_dumpsys(struct dumperinfo *di)
/*
* Disable EKCD because we don't provide encrypted textdumps.
*/
- kdc = di->kdc;
- di->kdc = NULL;
+ kdc = di->kdcrypto;
+ di->kdcrypto = NULL;
/*
* Position the start of the dump so that we'll write the kernel dump
@@ -512,7 +512,7 @@ textdump_dumpsys(struct dumperinfo *di)
/*
* Restore EKCD status.
*/
- di->kdc = kdc;
+ di->kdcrypto = kdc;
}
/*-
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index bec8e9d9ef97..28ebfff62577 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -36,13 +36,12 @@ __FBSDID("$FreeBSD$");
#include "opt_capsicum.h"
#include "opt_compat.h"
-#include "opt_gzio.h"
#include <sys/param.h>
#include <sys/capsicum.h>
+#include <sys/compressor.h>
#include <sys/exec.h>
#include <sys/fcntl.h>
-#include <sys/gzio.h>
#include <sys/imgact.h>
#include <sys/imgact_elf.h>
#include <sys/jail.h>
@@ -1185,9 +1184,12 @@ struct coredump_params {
struct ucred *file_cred;
struct thread *td;
struct vnode *vp;
- struct gzio_stream *gzs;
+ struct compressor *comp;
};
+extern int compress_user_cores;
+extern int compress_user_cores_level;
+
static void cb_put_phdr(vm_map_entry_t, void *);
static void cb_size_segment(vm_map_entry_t, void *);
static int core_write(struct coredump_params *, const void *, size_t, off_t,
@@ -1219,9 +1221,6 @@ static void note_procstat_rlimit(void *, struct sbuf *, size_t *);
static void note_procstat_umask(void *, struct sbuf *, size_t *);
static void note_procstat_vmmap(void *, struct sbuf *, size_t *);
-#ifdef GZIO
-extern int compress_user_cores_gzlevel;
-
/*
* Write out a core segment to the compression stream.
*/
@@ -1241,7 +1240,7 @@ compress_chunk(struct coredump_params *p, char *base, char *buf, u_int len)
error = copyin(base, buf, chunk_len);
if (error != 0)
bzero(buf, chunk_len);
- error = gzio_write(p->gzs, buf, chunk_len);
+ error = compressor_write(p->comp, buf, chunk_len);
if (error != 0)
break;
base += chunk_len;
@@ -1251,13 +1250,12 @@ compress_chunk(struct coredump_params *p, char *base, char *buf, u_int len)
}
static int
-core_gz_write(void *base, size_t len, off_t offset, void *arg)
+core_compressed_write(void *base, size_t len, off_t offset, void *arg)
{
return (core_write((struct coredump_params *)arg, base, len, offset,
UIO_SYSSPACE));
}
-#endif /* GZIO */
static int
core_write(struct coredump_params *p, const void *base, size_t len,
@@ -1275,10 +1273,9 @@ core_output(void *base, size_t len, off_t offset, struct coredump_params *p,
{
int error;
-#ifdef GZIO
- if (p->gzs != NULL)
+ if (p->comp != NULL)
return (compress_chunk(p, base, tmpbuf, len));
-#endif
+
/*
* EFAULT is a non-fatal error that we can get, for example,
* if the segment is backed by a file but extends beyond its
@@ -1323,11 +1320,9 @@ sbuf_drain_core_output(void *arg, const char *data, int len)
locked = PROC_LOCKED(p->td->td_proc);
if (locked)
PROC_UNLOCK(p->td->td_proc);
-#ifdef GZIO
- if (p->gzs != NULL)
- error = gzio_write(p->gzs, __DECONST(char *, data), len);
+ if (p->comp != NULL)
+ error = compressor_write(p->comp, __DECONST(char *, data), len);
else
-#endif
error = core_write(p, __DECONST(void *, data), len, p->offset,
UIO_SYSSPACE);
if (locked)
@@ -1362,11 +1357,7 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
struct note_info *ninfo;
void *hdr, *tmpbuf;
size_t hdrsize, notesz, coresize;
-#ifdef GZIO
- boolean_t compress;
- compress = (flags & IMGACT_CORE_COMPRESS) != 0;
-#endif
hdr = NULL;
tmpbuf = NULL;
TAILQ_INIT(&notelst);
@@ -1391,7 +1382,7 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
params.file_cred = NOCRED;
params.td = td;
params.vp = vp;
- params.gzs = NULL;
+ params.comp = NULL;
#ifdef RACCT
if (racct_enable) {
@@ -1409,18 +1400,17 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
goto done;
}
-#ifdef GZIO
/* Create a compression stream if necessary. */
- if (compress) {
- params.gzs = gzio_init(core_gz_write, GZIO_DEFLATE,
- CORE_BUF_SIZE, compress_user_cores_gzlevel, &params);
- if (params.gzs == NULL) {
+ if (compress_user_cores != 0) {
+ params.comp = compressor_init(core_compressed_write,
+ compress_user_cores, CORE_BUF_SIZE,
+ compress_user_cores_level, &params);
+ if (params.comp == NULL) {
error = EFAULT;
goto done;
}
tmpbuf = malloc(CORE_BUF_SIZE, M_TEMP, M_WAITOK | M_ZERO);
}
-#endif
/*
* Allocate memory for building the header, fill it up,
@@ -1446,10 +1436,8 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
offset += php->p_filesz;
php++;
}
-#ifdef GZIO
- if (error == 0 && compress)
- error = gzio_flush(params.gzs);
-#endif
+ if (error == 0 && params.comp != NULL)
+ error = compressor_flush(params.comp);
}
if (error) {
log(LOG_WARNING,
@@ -1458,13 +1446,9 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
}
done:
-#ifdef GZIO
- if (compress) {
- free(tmpbuf, M_TEMP);
- if (params.gzs != NULL)
- gzio_fini(params.gzs);
- }
-#endif
+ free(tmpbuf, M_TEMP);
+ if (params.comp != NULL)
+ compressor_fini(params.comp);
while ((ninfo = TAILQ_FIRST(&notelst)) != NULL) {
TAILQ_REMOVE(&notelst, ninfo, link);
free(ninfo, M_TEMP);
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
index d51a4c5aa76c..0979b3081286 100644
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include "opt_ekcd.h"
-#include "opt_gzio.h"
#include "opt_kdb.h"
#include "opt_panic.h"
#include "opt_sched.h"
@@ -52,10 +51,10 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/conf.h>
+#include <sys/compressor.h>
#include <sys/cons.h>
#include <sys/eventhandler.h>
#include <sys/filedesc.h>
-#include <sys/gzio.h>
#include <sys/jail.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
@@ -174,23 +173,21 @@ struct kerneldumpcrypto {
};
#endif
-#ifdef GZIO
-struct kerneldumpgz {
- struct gzio_stream *kdgz_stream;
- uint8_t *kdgz_buf;
- size_t kdgz_resid;
+struct kerneldumpcomp {
+ struct compressor *kdc_stream;
+ uint8_t *kdc_buf;
+ size_t kdc_resid;
};
-static struct kerneldumpgz *kerneldumpgz_create(struct dumperinfo *di,
+static struct kerneldumpcomp *kerneldumpcomp_create(struct dumperinfo *di,
uint8_t compression);
-static void kerneldumpgz_destroy(struct dumperinfo *di);
-static int kerneldumpgz_write_cb(void *cb, size_t len, off_t off, void *arg);
+static void kerneldumpcomp_destroy(struct dumperinfo *di);
+static int kerneldumpcomp_write_cb(void *base, size_t len, off_t off, void *arg);
static int kerneldump_gzlevel = 6;
SYSCTL_INT(_kern, OID_AUTO, kerneldump_gzlevel, CTLFLAG_RWTUN,
&kerneldump_gzlevel, 0,
- "Kernel crash dump gzip compression level");
-#endif /* GZIO */
+ "Kernel crash dump compression level");
/*
* Variable panicstr contains argument to first call to panic; used as flag
@@ -986,39 +983,37 @@ kerneldumpcrypto_dumpkeysize(const struct kerneldumpcrypto *kdc)
}
#endif /* EKCD */
-#ifdef GZIO
-static struct kerneldumpgz *
-kerneldumpgz_create(struct dumperinfo *di, uint8_t compression)
+static struct kerneldumpcomp *
+kerneldumpcomp_create(struct dumperinfo *di, uint8_t compression)
{
- struct kerneldumpgz *kdgz;
+ struct kerneldumpcomp *kdcomp;
if (compression != KERNELDUMP_COMP_GZIP)
return (NULL);
- kdgz = malloc(sizeof(*kdgz), M_DUMPER, M_WAITOK | M_ZERO);
- kdgz->kdgz_stream = gzio_init(kerneldumpgz_write_cb, GZIO_DEFLATE,
- di->maxiosize, kerneldump_gzlevel, di);
- if (kdgz->kdgz_stream == NULL) {
- free(kdgz, M_DUMPER);
+ kdcomp = malloc(sizeof(*kdcomp), M_DUMPER, M_WAITOK | M_ZERO);
+ kdcomp->kdc_stream = compressor_init(kerneldumpcomp_write_cb,
+ COMPRESS_GZIP, di->maxiosize, kerneldump_gzlevel, di);
+ if (kdcomp->kdc_stream == NULL) {
+ free(kdcomp, M_DUMPER);
return (NULL);
}
- kdgz->kdgz_buf = malloc(di->maxiosize, M_DUMPER, M_WAITOK | M_NODUMP);
- return (kdgz);
+ kdcomp->kdc_buf = malloc(di->maxiosize, M_DUMPER, M_WAITOK | M_NODUMP);
+ return (kdcomp);
}
static void
-kerneldumpgz_destroy(struct dumperinfo *di)
+kerneldumpcomp_destroy(struct dumperinfo *di)
{
- struct kerneldumpgz *kdgz;
+ struct kerneldumpcomp *kdcomp;
- kdgz = di->kdgz;
- if (kdgz == NULL)
+ kdcomp = di->kdcomp;
+ if (kdcomp == NULL)
return;
- gzio_fini(kdgz->kdgz_stream);
- explicit_bzero(kdgz->kdgz_buf, di->maxiosize);
- free(kdgz->kdgz_buf, M_DUMPER);
- free(kdgz, M_DUMPER);
+ compressor_fini(kdcomp->kdc_stream);
+ explicit_bzero(kdcomp->kdc_buf, di->maxiosize);
+ free(kdcomp->kdc_buf, M_DUMPER);
+ free(kdcomp, M_DUMPER);
}
-#endif /* GZIO */
/* Registration of dumpers */
int
@@ -1041,14 +1036,14 @@ set_dumper(struct dumperinfo *di, const char *devname, struct thread *td,
return (EBUSY);
dumper = *di;
dumper.blockbuf = NULL;
- dumper.kdc = NULL;
- dumper.kdgz = NULL;
+ dumper.kdcrypto = NULL;
+ dumper.kdcomp = NULL;
if (encryption != KERNELDUMP_ENC_NONE) {
#ifdef EKCD
- dumper.kdc = kerneldumpcrypto_create(di->blocksize, encryption,
- key, encryptedkeysize, encryptedkey);
- if (dumper.kdc == NULL) {
+ dumper.kdcrypto = kerneldumpcrypto_create(di->blocksize,
+ encryption, key, encryptedkeysize, encryptedkey);
+ if (dumper.kdcrypto == NULL) {
error = EINVAL;
goto cleanup;
}
@@ -1065,7 +1060,6 @@ set_dumper(struct dumperinfo *di, const char *devname, struct thread *td,
}
if (compression != KERNELDUMP_COMP_NONE) {
-#ifdef GZIO
/*
* We currently can't support simultaneous encryption and
* compression.
@@ -1074,31 +1068,25 @@ set_dumper(struct dumperinfo *di, const char *devname, struct thread *td,
error = EOPNOTSUPP;
goto cleanup;
}
- dumper.kdgz = kerneldumpgz_create(&dumper, compression);
- if (dumper.kdgz == NULL) {
+ dumper.kdcomp = kerneldumpcomp_create(&dumper, compression);
+ if (dumper.kdcomp == NULL) {
error = EINVAL;
goto cleanup;
}
-#else
- error = EOPNOTSUPP;
- goto cleanup;
-#endif
}
dumper.blockbuf = malloc(di->blocksize, M_DUMPER, M_WAITOK | M_ZERO);
return (0);
cleanup:
#ifdef EKCD
- if (dumper.kdc != NULL) {
- explicit_bzero(dumper.kdc, sizeof(*dumper.kdc) +
- dumper.kdc->kdc_dumpkeysize);
- free(dumper.kdc, M_EKCD);
+ if (dumper.kdcrypto != NULL) {
+ explicit_bzero(dumper.kdcrypto, sizeof(*dumper.kdcrypto) +
+ dumper.kdcrypto->kdc_dumpkeysize);
+ free(dumper.kdcrypto, M_EKCD);
}
#endif
-#ifdef GZIO
- kerneldumpgz_destroy(&dumper);
-#endif
+ kerneldumpcomp_destroy(&dumper);
if (dumper.blockbuf != NULL) {
explicit_bzero(dumper.blockbuf, dumper.blocksize);
@@ -1168,7 +1156,7 @@ dump_encrypted_write(struct dumperinfo *di, void *virtual,
int error;
size_t nbytes;
- kdc = di->kdc;
+ kdc = di->kdcrypto;
while (length > 0) {
nbytes = MIN(length, sizeof(buf));
@@ -1194,7 +1182,7 @@ dump_write_key(struct dumperinfo *di, off_t offset)
{
struct kerneldumpcrypto *kdc;
- kdc = di->kdc;
+ kdc = di->kdcrypto;
if (kdc == NULL)
return (0);
return (dump_write(di, kdc->kdc_dumpkey, 0, offset,
@@ -1202,9 +1190,8 @@ dump_write_key(struct dumperinfo *di, off_t offset)
}
#endif /* EKCD */
-#ifdef GZIO
static int
-kerneldumpgz_write_cb(void *base, size_t length, off_t offset, void *arg)
+kerneldumpcomp_write_cb(void *base, size_t length, off_t offset, void *arg)
{
struct dumperinfo *di;
size_t resid, rlength;
@@ -1227,12 +1214,11 @@ kerneldumpgz_write_cb(void *base, size_t length, off_t offset, void *arg)
}
resid = length - rlength;
memmove(di->blockbuf, (uint8_t *)base + rlength, resid);
- di->kdgz->kdgz_resid = resid;
+ di->kdcomp->kdc_resid = resid;
return (EAGAIN);
}
return (_dump_append(di, base, 0, length));
}
-#endif /* GZIO */
/*
* Write a kerneldumpheader at the specified offset. The header structure is 512
@@ -1290,10 +1276,10 @@ dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh)
uint32_t keysize;
#ifdef EKCD
- int error = kerneldumpcrypto_init(di->kdc);
+ int error = kerneldumpcrypto_init(di->kdcrypto);
if (error != 0)
return (error);
- keysize = kerneldumpcrypto_dumpkeysize(di->kdc);
+ keysize = kerneldumpcrypto_dumpkeysize(di->kdcrypto);
#else
keysize = 0;
#endif
@@ -1301,8 +1287,7 @@ dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh)
dumpextent = dtoh64(kdh->dumpextent);
if (di->mediasize < SIZEOF_METADATA + dumpextent + 2 * di->blocksize +
keysize) {
-#ifdef GZIO
- if (di->kdgz != NULL) {
+ if (di->kdcomp != NULL) {
/*
* We don't yet know how much space the compressed dump
* will occupy, so try to use the whole swap partition
@@ -1315,7 +1300,6 @@ dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh)
2 * di->blocksize - keysize;
kdh->dumpextent = htod64(dumpextent);
} else
-#endif
return (E2BIG);
}
@@ -1333,7 +1317,7 @@ _dump_append(struct dumperinfo *di, void *virtual, vm_offset_t physical,
int error;
#ifdef EKCD
- if (di->kdc != NULL)
+ if (di->kdcrypto != NULL)
error = dump_encrypted_write(di, virtual, physical, di->dumpoff,
length);
else
@@ -1353,18 +1337,16 @@ int
dump_append(struct dumperinfo *di, void *virtual, vm_offset_t physical,
size_t length)
{
-#ifdef GZIO
void *buf;
- if (di->kdgz != NULL) {
- /* Bounce through a buffer to avoid gzip CRC errors. */
+ if (di->kdcomp != NULL) {
+ /* Bounce through a buffer to avoid CRC errors. */
if (length > di->maxiosize)
return (EINVAL);
- buf = di->kdgz->kdgz_buf;
+ buf = di->kdcomp->kdc_buf;
memmove(buf, virtual, length);
- return (gzio_write(di->kdgz->kdgz_stream, buf, length));
+ return (compressor_write(di->kdcomp->kdc_stream, buf, length));
}
-#endif
return (_dump_append(di, virtual, physical, length));
}
@@ -1399,20 +1381,19 @@ dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh)
extent = dtoh64(kdh->dumpextent);
#ifdef EKCD
- keysize = kerneldumpcrypto_dumpkeysize(di->kdc);
+ keysize = kerneldumpcrypto_dumpkeysize(di->kdcrypto);
#else
keysize = 0;
#endif
-#ifdef GZIO
- if (di->kdgz != NULL) {
- error = gzio_flush(di->kdgz->kdgz_stream);
+ if (di->kdcomp != NULL) {
+ error = compressor_flush(di->kdcomp->kdc_stream);
if (error == EAGAIN) {
/* We have residual data in di->blockbuf. */
error = dump_write(di, di->blockbuf, 0, di->dumpoff,
di->blocksize);
- di->dumpoff += di->kdgz->kdgz_resid;
- di->kdgz->kdgz_resid = 0;
+ di->dumpoff += di->kdcomp->kdc_resid;
+ di->kdcomp->kdc_resid = 0;
}
if (error != 0)
return (error);
@@ -1426,9 +1407,8 @@ dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh)
kdh->parity = 0;
kdh->parity = kerneldump_parity(kdh);
- gzio_reset(di->kdgz->kdgz_stream);
+ compressor_reset(di->kdcomp->kdc_stream);
}
-#endif
/*
* Write kerneldump headers at the beginning and end of the dump extent.
@@ -1471,7 +1451,7 @@ dump_init_header(const struct dumperinfo *di, struct kerneldumpheader *kdh,
kdh->dumpextent = kdh->dumplength;
kdh->dumptime = htod64(time_second);
#ifdef EKCD
- kdh->dumpkeysize = htod32(kerneldumpcrypto_dumpkeysize(di->kdc));
+ kdh->dumpkeysize = htod32(kerneldumpcrypto_dumpkeysize(di->kdcrypto));
#else
kdh->dumpkeysize = 0;
#endif
@@ -1482,10 +1462,8 @@ dump_init_header(const struct dumperinfo *di, struct kerneldumpheader *kdh,
kdh->versionstring[dstsize - 2] = '\n';
if (panicstr != NULL)
strlcpy(kdh->panicstring, panicstr, sizeof(kdh->panicstring));
-#ifdef GZIO
- if (di->kdgz != NULL)
+ if (di->kdcomp != NULL)
kdh->compression = KERNELDUMP_COMP_GZIP;
-#endif
kdh->parity = kerneldump_parity(kdh);
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 1a93544bdb7d..24c1cbdf1618 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -40,7 +40,6 @@
__FBSDID("$FreeBSD$");
#include "opt_compat.h"
-#include "opt_gzio.h"
#include "opt_ktrace.h"
#include <sys/param.h>
@@ -51,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <sys/acct.h>
#include <sys/bus.h>
#include <sys/capsicum.h>
+#include <sys/compressor.h>
#include <sys/condvar.h>
#include <sys/event.h>
#include <sys/fcntl.h>
@@ -3255,17 +3255,30 @@ SYSCTL_PROC(_debug, OID_AUTO, ncores, CTLTYPE_INT|CTLFLAG_RW,
#define GZ_SUFFIX ".gz"
-#ifdef GZIO
-static int compress_user_cores = 1;
-SYSCTL_INT(_kern, OID_AUTO, compress_user_cores, CTLFLAG_RWTUN,
- &compress_user_cores, 0, "Compression of user corefiles");
+int compress_user_cores = 0;
-int compress_user_cores_gzlevel = 6;
-SYSCTL_INT(_kern, OID_AUTO, compress_user_cores_gzlevel, CTLFLAG_RWTUN,
- &compress_user_cores_gzlevel, 0, "Corefile gzip compression level");
-#else
-static int compress_user_cores = 0;
-#endif
+static int
+sysctl_compress_user_cores(SYSCTL_HANDLER_ARGS)
+{
+ int error, val;
+
+ val = compress_user_cores;
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+ if (val != 0 && !compressor_avail(val))
+ return (EINVAL);
+ compress_user_cores = val;
+ return (error);
+}
+SYSCTL_PROC(_kern, OID_AUTO, compress_user_cores, CTLTYPE_INT | CTLFLAG_RWTUN,
+ 0, sizeof(int), sysctl_compress_user_cores, "I",
+ "Enable compression of user corefiles (" __XSTRING(COMPRESS_GZIP) " = gzip)");
+
+int compress_user_cores_level = 6;
+SYSCTL_INT(_kern, OID_AUTO, compress_user_cores_level, CTLFLAG_RWTUN,
+ &compress_user_cores_level, 0,
+ "Corefile compression level");
/*
* Protect the access to corefilename[] by allproc_lock.
@@ -3363,7 +3376,7 @@ corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td,
}
sx_sunlock(&corefilename_lock);
free(hostname, M_TEMP);
- if (compress)
+ if (compress == COMPRESS_GZIP)
sbuf_printf(&sb, GZ_SUFFIX);
if (sbuf_error(&sb) != 0) {
log(LOG_ERR, "pid %ld (%s), uid (%lu): corename is too "
@@ -3529,8 +3542,7 @@ coredump(struct thread *td)
PROC_UNLOCK(p);
if (p->p_sysent->sv_coredump != NULL) {
- error = p->p_sysent->sv_coredump(td, vp, limit,
- compress_user_cores ? IMGACT_CORE_COMPRESS : 0);
+ error = p->p_sysent->sv_coredump(td, vp, limit, 0);
} else {
error = ENOSYS;
}
diff --git a/sys/kern/kern_gzio.c b/sys/kern/subr_compressor.c
index f659b9bb7d7a..0ddf27274511 100644
--- a/sys/kern/kern_gzio.c
+++ b/sys/kern/subr_compressor.c
@@ -1,5 +1,7 @@
/*-
- * Copyright (c) 2014 Mark Johnston <markj@FreeBSD.org>
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2014, 2017 Mark Johnston <markj@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -24,55 +26,87 @@
* SUCH DAMAGE.
*/
+/*
+ * Subroutines used for writing compressed user process and kernel core dumps.
+ */
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_gzio.h"
+
#include <sys/param.h>
-#include <sys/gzio.h>
+#include <sys/compressor.h>
#include <sys/kernel.h>
+#include <sys/linker_set.h>
#include <sys/malloc.h>
-#include <sys/zutil.h>
-#define KERN_GZ_HDRLEN 10 /* gzip header length */
-#define KERN_GZ_TRAILERLEN 8 /* gzip trailer length */
-#define KERN_GZ_MAGIC1 0x1f /* first magic byte */
-#define KERN_GZ_MAGIC2 0x8b /* second magic byte */
+MALLOC_DEFINE(M_COMPRESS, "compressor", "kernel compression subroutines");
+
+struct compressor_methods {
+ int format;
+ void *(* const init)(size_t, int);
+ void (* const reset)(void *);
+ int (* const write)(void *, void *, size_t, compressor_cb_t, void *);
+ void (* const fini)(void *);
+};
-MALLOC_DEFINE(M_GZIO, "gzio", "zlib state");
+struct compressor {
+ const struct compressor_methods *methods;
+ compressor_cb_t cb;
+ void *priv;
+ void *arg;
+};
-struct gzio_stream {
- uint8_t * gz_buffer; /* output buffer */
- size_t gz_bufsz; /* total buffer size */
+SET_DECLARE(compressors, struct compressor_methods);
+
+#ifdef GZIO
+
+#include <sys/zutil.h>
+
+struct gz_stream {
+ uint8_t *gz_buffer; /* output buffer */
+ size_t gz_bufsz; /* output buffer size */
off_t gz_off; /* offset into the output stream */
- enum gzio_mode gz_mode; /* stream mode */
uint32_t gz_crc; /* stream CRC32 */
- gzio_cb gz_cb; /* output callback */
- void * gz_arg; /* private callback arg */
z_stream gz_stream; /* zlib state */
};
-static void * gz_alloc(void *, u_int, u_int);
-static void gz_free(void *, void *);
-static int gz_write(struct gzio_stream *, void *, u_int, int);
+static void *gz_init(size_t maxiosize, int level);
+static void gz_reset(void *stream);
+static int gz_write(void *stream, void *data, size_t len, compressor_cb_t,
+ void *);
+static void gz_fini(void *stream);
-struct gzio_stream *
-gzio_init(gzio_cb cb, enum gzio_mode mode, size_t bufsz, int level, void *arg)
+static void *
+gz_alloc(void *arg __unused, u_int n, u_int sz)
{
- struct gzio_stream *s;
- int error;
- if (bufsz < KERN_GZ_HDRLEN)
- return (NULL);
- if (mode != GZIO_DEFLATE)
- return (NULL);
+ /*
+ * Memory for zlib state is allocated using M_NODUMP since it may be
+ * used to compress a kernel dump, and we don't want zlib to attempt to
+ * compress its own state.
+ */
+ return (malloc(n * sz, M_COMPRESS, M_WAITOK | M_ZERO | M_NODUMP));
+}
+
+static void
+gz_free(void *arg __unused, void *ptr)
+{
+
+ free(ptr, M_COMPRESS);
+}
+
+static void *
+gz_init(size_t maxiosize, int level)
+{
+ struct gz_stream *s;
+ int error;
- s = gz_alloc(NULL, 1, sizeof(*s));
- s->gz_bufsz = bufsz;
- s->gz_buffer = gz_alloc(NULL, 1, s->gz_bufsz);
- s->gz_mode = mode;
- s->gz_cb = cb;
- s->gz_arg = arg;
+ s = gz_alloc(NULL, 1, roundup2(sizeof(*s), PAGE_SIZE));
+ s->gz_buffer = gz_alloc(NULL, 1, maxiosize);
+ s->gz_bufsz = maxiosize;
s->gz_stream.zalloc = gz_alloc;
s->gz_stream.zfree = gz_free;
@@ -85,98 +119,57 @@ gzio_init(gzio_cb cb, enum gzio_mode mode, size_t bufsz, int level, void *arg)
if (error != 0)
goto fail;
- gzio_reset(s);
+ gz_reset(s);
return (s);
fail:
- gz_free(NULL, s->gz_buffer);
gz_free(NULL, s);
return (NULL);
}
-void
-gzio_reset(struct gzio_stream *s)
+static void
+gz_reset(void *stream)
{
+ struct gz_stream *s;
uint8_t *hdr;
+ const size_t hdrlen = 10;
- (void)deflateReset(&s->gz_stream);
-
+ s = stream;
s->gz_off = 0;
s->gz_crc = ~0U;
+ (void)deflateReset(&s->gz_stream);
s->gz_stream.avail_out = s->gz_bufsz;
s->gz_stream.next_out = s->gz_buffer;
/* Write the gzip header to the output buffer. */
hdr = s->gz_buffer;
- memset(hdr, 0, KERN_GZ_HDRLEN);
- hdr[0] = KERN_GZ_MAGIC1;
- hdr[1] = KERN_GZ_MAGIC2;
+ memset(hdr, 0, hdrlen);
+ hdr[0] = 0x1f;
+ hdr[1] = 0x8b;
hdr[2] = Z_DEFLATED;
hdr[9] = OS_CODE;
- s->gz_stream.next_out += KERN_GZ_HDRLEN;
- s->gz_stream.avail_out -= KERN_GZ_HDRLEN;
-}
-
-int
-gzio_write(struct gzio_stream *s, void *data, u_int len)
-{
-
- return (gz_write(s, data, len, Z_NO_FLUSH));
-}
-
-int
-gzio_flush(struct gzio_stream *s)
-{
-
- return (gz_write(s, NULL, 0, Z_FINISH));
-}
-
-void
-gzio_fini(struct gzio_stream *s)
-{
-
- (void)deflateEnd(&s->gz_stream);
- gz_free(NULL, s->gz_buffer);
- gz_free(NULL, s);
-}
-
-static void *
-gz_alloc(void *arg __unused, u_int n, u_int sz)
-{
-
- /*
- * Memory for zlib state is allocated using M_NODUMP since it may be
- * used to compress a kernel dump, and we don't want zlib to attempt to
- * compress its own state.
- */
- return (malloc(n * sz, M_GZIO, M_WAITOK | M_ZERO | M_NODUMP));
-}
-
-static void
-gz_free(void *arg __unused, void *ptr)
-{
-
- free(ptr, M_GZIO);
+ s->gz_stream.next_out += hdrlen;
+ s->gz_stream.avail_out -= hdrlen;
}
static int
-gz_write(struct gzio_stream *s, void *buf, u_int len, int zflag)
+gz_write(void *stream, void *data, size_t len, compressor_cb_t cb,
+ void *arg)
{
- uint8_t trailer[KERN_GZ_TRAILERLEN];
+ struct gz_stream *s;
+ uint8_t trailer[8];
size_t room;
- int error, zerror;
+ int error, zerror, zflag;
- KASSERT(zflag == Z_FINISH || zflag == Z_NO_FLUSH,
- ("unexpected flag %d", zflag));
- KASSERT(s->gz_mode == GZIO_DEFLATE,
- ("invalid stream mode %d", s->gz_mode));
+ s = stream;
+ zflag = data == NULL ? Z_FINISH : Z_NO_FLUSH;
if (len > 0) {
s->gz_stream.avail_in = len;
- s->gz_stream.next_in = buf;
- s->gz_crc = crc32_raw(buf, len, s->gz_crc);
+ s->gz_stream.next_in = data;
+ s->gz_crc = crc32_raw(data, len, s->gz_crc);
} else
s->gz_crc ^= ~0U;
@@ -202,14 +195,13 @@ gz_write(struct gzio_stream *s, void *buf, u_int len, int zflag)
((uint32_t *)trailer)[0] = s->gz_crc;
((uint32_t *)trailer)[1] =
s->gz_stream.total_in;
- room = MIN(KERN_GZ_TRAILERLEN,
+ room = MIN(sizeof(trailer),
s->gz_bufsz - len);
memcpy(s->gz_buffer + len, trailer, room);
len += room;
}
- error = s->gz_cb(s->gz_buffer, len, s->gz_off,
- s->gz_arg);
+ error = cb(s->gz_buffer, len, s->gz_off, arg);
if (error != 0)
break;
@@ -221,13 +213,103 @@ gz_write(struct gzio_stream *s, void *buf, u_int len, int zflag)
* If we couldn't pack the trailer into the output
* buffer, write it out now.
*/
- if (zerror == Z_STREAM_END && room < KERN_GZ_TRAILERLEN)
- error = s->gz_cb(trailer + room,
- KERN_GZ_TRAILERLEN - room, s->gz_off,
- s->gz_arg);
+ if (zerror == Z_STREAM_END && room < sizeof(trailer))
+ error = cb(trailer + room,
+ sizeof(trailer) - room, s->gz_off, arg);
}
} while (zerror != Z_STREAM_END &&
(zflag == Z_FINISH || s->gz_stream.avail_in > 0));
return (error);
}
+
+static void
+gz_fini(void *stream)
+{
+ struct gz_stream *s;
+
+ s = stream;
+ (void)deflateEnd(&s->gz_stream);
+ gz_free(NULL, s->gz_buffer);
+ gz_free(NULL, s);
+}
+
+struct compressor_methods gzip_methods = {
+ .format = COMPRESS_GZIP,
+ .init = gz_init,
+ .reset = gz_reset,
+ .write = gz_write,
+ .fini = gz_fini,
+};
+DATA_SET(compressors, gzip_methods);
+
+#endif /* GZIO */
+
+bool
+compressor_avail(int format)
+{
+ struct compressor_methods **iter;
+
+ SET_FOREACH(iter, compressors) {
+ if ((*iter)->format == format)
+ return (true);
+ }
+ return (false);
+}
+
+struct compressor *
+compressor_init(compressor_cb_t cb, int format, size_t maxiosize, int level,
+ void *arg)
+{
+ struct compressor_methods **iter;
+ struct compressor *s;
+ void *priv;
+
+ SET_FOREACH(iter, compressors) {
+ if ((*iter)->format == format)
+ break;
+ }
+ if (iter == NULL)
+ return (NULL);
+
+ priv = (*iter)->init(maxiosize, level);
+ if (priv == NULL)
+ return (NULL);
+
+ s = malloc(sizeof(*s), M_COMPRESS, M_WAITOK | M_ZERO);
+ s->methods = (*iter);
+ s->priv = priv;
+ s->cb = cb;
+ s->arg = arg;
+ return (s);
+}
+
+void
+compressor_reset(struct compressor *stream)
+{
+
+ stream->methods->reset(stream->priv);
+}
+
+int
+compressor_write(struct compressor *stream, void *data, size_t len)
+{
+
+ return (stream->methods->write(stream->priv, data, len, stream->cb,
+ stream->arg));
+}
+
+int
+compressor_flush(struct compressor *stream)
+{
+
+ return (stream->methods->write(stream->priv, NULL, 0, stream->cb,
+ stream->arg));
+}
+
+void
+compressor_fini(struct compressor *stream)
+{
+
+ stream->methods->fini(stream->priv);
+}
diff --git a/sys/sys/gzio.h b/sys/sys/compressor.h
index eb4aecf4b5a8..9407b950d5a8 100644
--- a/sys/sys/gzio.h
+++ b/sys/sys/compressor.h
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2014 Mark Johnston <markj@FreeBSD.org>
+ * Copyright (c) 2014, 2017 Mark Johnston <markj@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -28,25 +28,26 @@
* $FreeBSD$
*/
-#ifndef _SYS__GZIO_H_
-#define _SYS__GZIO_H_
+#ifndef _SYS__COMPRESSOR_H_
+#define _SYS__COMPRESSOR_H_
#ifdef _KERNEL
-enum gzio_mode {
- GZIO_DEFLATE,
-};
+/* Supported formats. */
+#define COMPRESS_GZIP 1
-typedef int (*gzio_cb)(void *, size_t, off_t, void *);
+typedef int (*compressor_cb_t)(void *, size_t, off_t, void *);
-struct gzio_stream;
+struct compressor;
-struct gzio_stream *gzio_init(gzio_cb cb, enum gzio_mode, size_t, int, void *);
-void gzio_reset(struct gzio_stream *);
-int gzio_write(struct gzio_stream *, void *, u_int);
-int gzio_flush(struct gzio_stream *);
-void gzio_fini(struct gzio_stream *);
+bool compressor_avail(int format);
+struct compressor *compressor_init(compressor_cb_t cb, int format,
+ size_t maxiosize, int level, void *arg);
+void compressor_reset(struct compressor *stream);
+int compressor_write(struct compressor *stream, void *data,
+ size_t len);
+int compressor_flush(struct compressor *stream);
+void compressor_fini(struct compressor *stream);
#endif /* _KERNEL */
-
-#endif /* _SYS__GZIO_H_ */
+#endif /* _SYS__COMPRESSOR_H_ */
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index d41d4707aac7..be3dee3d3de7 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -339,8 +339,8 @@ struct dumperinfo {
off_t mediasize; /* Space available in bytes. */
void *blockbuf; /* Buffer for padding shorter dump blocks */
off_t dumpoff; /* Offset of ongoing kernel dump. */
- struct kerneldumpcrypto *kdc; /* Kernel dump crypto. */
- struct kerneldumpgz *kdgz; /* Kernel dump compression. */
+ struct kerneldumpcrypto *kdcrypto; /* Kernel dump crypto. */
+ struct kerneldumpcomp *kdcomp; /* Kernel dump compression. */
};
extern int dumping; /* system is dumping */
diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h
index 60c9b60a05d2..54c4020f70a5 100644
--- a/sys/sys/imgact.h
+++ b/sys/sys/imgact.h
@@ -96,8 +96,6 @@ struct sysentvec;
struct thread;
struct vmspace;
-#define IMGACT_CORE_COMPRESS 0x01
-
int exec_alloc_args(struct image_args *);
int exec_check_permissions(struct image_params *);
register_t *exec_copyout_strings(struct image_params *);