Fix netdump buffering after r348473.

nd_buf is used to buffer headers (for both the kernel dump itself and
for EKCD) before the final call to netdump_dumper(), which flushes
residual data in nd_buf.  As a result, a small portion of the residual
data would be corrupted.  This manifests when kernel dump compression
is enabled since both zstd and zlib detect the corruption during
decompression.

Reviewed by:	cem
Differential Revision:	https://reviews.freebsd.org/D21294
This commit is contained in:
Mark Johnston 2019-08-19 16:29:51 +00:00
parent 165b9f965d
commit ccdc986607

View File

@ -922,6 +922,24 @@ netdump_network_poll(void)
* Dumping specific primitives.
*/
/*
* Flush any buffered vmcore data.
*/
static int
netdump_flush_buf(void)
{
int error;
error = 0;
if (nd_conf.nd_buf_len != 0) {
error = netdump_send(NETDUMP_VMCORE, nd_conf.nd_tx_off,
nd_buf, nd_conf.nd_buf_len);
if (error == 0)
nd_conf.nd_buf_len = 0;
}
return (error);
}
/*
* Callback from dumpsys() to dump a chunk of memory.
* Copies it out to our static buffer then sends it across the network.
@ -948,13 +966,9 @@ netdump_dumper(void *priv __unused, void *virtual,
virtual, (uintmax_t)offset, length);
if (virtual == NULL) {
if (nd_conf.nd_buf_len != 0) {
error = netdump_send(NETDUMP_VMCORE, nd_conf.nd_tx_off, nd_buf,
nd_conf.nd_buf_len);
if (error != 0) {
dump_failed = 1;
}
}
error = netdump_flush_buf();
if (error != 0)
dump_failed = 1;
if (dump_failed != 0)
printf("failed to dump the kernel core\n");
@ -971,13 +985,11 @@ netdump_dumper(void *priv __unused, void *virtual,
if (nd_conf.nd_buf_len + length > sizeof(nd_buf) ||
(nd_conf.nd_buf_len != 0 && nd_conf.nd_tx_off +
nd_conf.nd_buf_len != offset)) {
error = netdump_send(NETDUMP_VMCORE, nd_conf.nd_tx_off, nd_buf,
nd_conf.nd_buf_len);
error = netdump_flush_buf();
if (error != 0) {
dump_failed = 1;
return (error);
}
nd_conf.nd_buf_len = 0;
nd_conf.nd_tx_off = offset;
}
@ -1078,6 +1090,9 @@ netdump_write_headers(struct dumperinfo *di, struct kerneldumpheader *kdh,
{
int error;
error = netdump_flush_buf();
if (error != 0)
return (error);
memcpy(nd_buf, kdh, sizeof(*kdh));
error = netdump_send(NETDUMP_KDH, 0, nd_buf, sizeof(*kdh));
if (error == 0 && keysize > 0) {