netdump: send key before dump, in case dump fails
Previously, if an encrypted netdump failed, such as due to a timeout or network failure, the key was not saved, so a partial dump was completely useless. Send the key first, so the partial dump can be decrypted, because even a partial dump can be useful. Reviewed by: bdrewery, markj MFC after: 1 week Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D31453
This commit is contained in:
parent
96f9bd4654
commit
13a58148de
@ -1488,7 +1488,7 @@ dump_write_headers(struct dumperinfo *di, struct kerneldumpheader *kdh)
|
||||
#ifdef EKCD
|
||||
struct kerneldumpcrypto *kdc;
|
||||
#endif
|
||||
void *buf, *key;
|
||||
void *buf;
|
||||
size_t hdrsz;
|
||||
uint64_t extent;
|
||||
uint32_t keysize;
|
||||
@ -1500,10 +1500,8 @@ dump_write_headers(struct dumperinfo *di, struct kerneldumpheader *kdh)
|
||||
|
||||
#ifdef EKCD
|
||||
kdc = di->kdcrypto;
|
||||
key = kdc->kdc_dumpkey;
|
||||
keysize = kerneldumpcrypto_dumpkeysize(kdc);
|
||||
#else
|
||||
key = NULL;
|
||||
keysize = 0;
|
||||
#endif
|
||||
|
||||
@ -1512,7 +1510,7 @@ dump_write_headers(struct dumperinfo *di, struct kerneldumpheader *kdh)
|
||||
* of writing them out.
|
||||
*/
|
||||
if (di->dumper_hdr != NULL)
|
||||
return (di->dumper_hdr(di, kdh, key, keysize));
|
||||
return (di->dumper_hdr(di, kdh));
|
||||
|
||||
if (hdrsz == di->blocksize)
|
||||
buf = kdh;
|
||||
@ -1571,22 +1569,30 @@ dump_write_headers(struct dumperinfo *di, struct kerneldumpheader *kdh)
|
||||
int
|
||||
dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh)
|
||||
{
|
||||
#ifdef EKCD
|
||||
struct kerneldumpcrypto *kdc;
|
||||
#endif
|
||||
void *key;
|
||||
uint64_t dumpextent, span;
|
||||
uint32_t keysize;
|
||||
int error;
|
||||
|
||||
#ifdef EKCD
|
||||
error = kerneldumpcrypto_init(di->kdcrypto);
|
||||
/* Send the key before the dump so a partial dump is still usable. */
|
||||
kdc = di->kdcrypto;
|
||||
error = kerneldumpcrypto_init(kdc);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
keysize = kerneldumpcrypto_dumpkeysize(di->kdcrypto);
|
||||
keysize = kerneldumpcrypto_dumpkeysize(kdc);
|
||||
key = keysize > 0 ? kdc->kdc_dumpkey : NULL;
|
||||
#else
|
||||
error = 0;
|
||||
keysize = 0;
|
||||
key = NULL;
|
||||
#endif
|
||||
|
||||
if (di->dumper_start != NULL) {
|
||||
error = di->dumper_start(di);
|
||||
error = di->dumper_start(di, key, keysize);
|
||||
} else {
|
||||
dumpextent = dtoh64(kdh->dumpextent);
|
||||
span = SIZEOF_METADATA + dumpextent + 2 * di->blocksize +
|
||||
|
@ -95,7 +95,8 @@ static int netdump_enabled_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int netdump_ioctl(struct cdev *dev __unused, u_long cmd,
|
||||
caddr_t addr, int flags __unused, struct thread *td);
|
||||
static int netdump_modevent(module_t mod, int type, void *priv);
|
||||
static int netdump_start(struct dumperinfo *di);
|
||||
static int netdump_start(struct dumperinfo *di, void *key,
|
||||
uint32_t keysize);
|
||||
static void netdump_unconfigure(void);
|
||||
|
||||
/* Must be at least as big as the chunks dumpsys() gives us. */
|
||||
@ -285,7 +286,7 @@ netdump_dumper(void *priv __unused, void *virtual,
|
||||
* Perform any initialization needed prior to transmitting the kernel core.
|
||||
*/
|
||||
static int
|
||||
netdump_start(struct dumperinfo *di)
|
||||
netdump_start(struct dumperinfo *di, void *key, uint32_t keysize)
|
||||
{
|
||||
struct debugnet_conn_params dcp;
|
||||
struct debugnet_pcb *pcb;
|
||||
@ -336,12 +337,34 @@ netdump_start(struct dumperinfo *di)
|
||||
printf("netdumping to %s (%6D)\n", inet_ntoa_r(nd_server, buf),
|
||||
debugnet_get_gw_mac(pcb), ":");
|
||||
nd_conf.nd_pcb = pcb;
|
||||
return (0);
|
||||
|
||||
/* Send the key before the dump so a partial dump is still usable. */
|
||||
if (keysize > 0) {
|
||||
if (keysize > sizeof(nd_buf)) {
|
||||
printf("crypto key is too large (%u)\n", keysize);
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(nd_buf, key, keysize);
|
||||
error = debugnet_send(pcb, NETDUMP_EKCD_KEY, nd_buf, keysize,
|
||||
NULL);
|
||||
if (error != 0) {
|
||||
printf("error %d sending crypto key\n", error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (error != 0) {
|
||||
/* As above, squash errors. */
|
||||
error = EINVAL;
|
||||
netdump_cleanup();
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
netdump_write_headers(struct dumperinfo *di, struct kerneldumpheader *kdh,
|
||||
void *key, uint32_t keysize)
|
||||
netdump_write_headers(struct dumperinfo *di, struct kerneldumpheader *kdh)
|
||||
{
|
||||
int error;
|
||||
|
||||
@ -351,15 +374,6 @@ netdump_write_headers(struct dumperinfo *di, struct kerneldumpheader *kdh,
|
||||
memcpy(nd_buf, kdh, sizeof(*kdh));
|
||||
error = debugnet_send(nd_conf.nd_pcb, NETDUMP_KDH, nd_buf,
|
||||
sizeof(*kdh), NULL);
|
||||
if (error == 0 && keysize > 0) {
|
||||
if (keysize > sizeof(nd_buf)) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(nd_buf, key, keysize);
|
||||
error = debugnet_send(nd_conf.nd_pcb, NETDUMP_EKCD_KEY, nd_buf,
|
||||
keysize, NULL);
|
||||
}
|
||||
out:
|
||||
if (error != 0)
|
||||
netdump_cleanup();
|
||||
|
@ -133,9 +133,8 @@ typedef int dumper_t(
|
||||
vm_offset_t _physical, /* Physical address of virtual. */
|
||||
off_t _offset, /* Byte-offset to write at. */
|
||||
size_t _length); /* Number of bytes to dump. */
|
||||
typedef int dumper_start_t(struct dumperinfo *di);
|
||||
typedef int dumper_hdr_t(struct dumperinfo *di, struct kerneldumpheader *kdh,
|
||||
void *key, uint32_t keylen);
|
||||
typedef int dumper_start_t(struct dumperinfo *di, void *key, uint32_t keysize);
|
||||
typedef int dumper_hdr_t(struct dumperinfo *di, struct kerneldumpheader *kdh);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user