diff options
author | Mark Johnston <markj@FreeBSD.org> | 2019-08-19 16:29:51 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2019-08-19 16:29:51 +0000 |
commit | ccdc986607d3a12def360e6c6d01b44f64cb0868 (patch) | |
tree | 7614631f2768dad338dc92e2a1d401347b3f7d5a | |
parent | 165b9f965d190e81a85f23dff9bd1f3977e73c01 (diff) | |
download | src-ccdc986607d3a12def360e6c6d01b44f64cb0868.tar.gz src-ccdc986607d3a12def360e6c6d01b44f64cb0868.zip |
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
Notes
Notes:
svn path=/head/; revision=351219
-rw-r--r-- | sys/netinet/netdump/netdump_client.c | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/sys/netinet/netdump/netdump_client.c b/sys/netinet/netdump/netdump_client.c index 262a9d9e9de1..5887a3796212 100644 --- a/sys/netinet/netdump/netdump_client.c +++ b/sys/netinet/netdump/netdump_client.c @@ -923,6 +923,24 @@ netdump_network_poll(void) */ /* + * 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. * Detects the initial KDH and makes sure it is given a special packet type. @@ -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"); @@ -968,16 +982,14 @@ netdump_dumper(void *priv __unused, void *virtual, if (length > sizeof(nd_buf)) return (ENOSPC); - if (nd_conf.nd_buf_len + length > sizeof(nd_buf) || - (nd_conf.nd_buf_len != 0 && nd_conf.nd_tx_off + + 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) { |