Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/kern_shutdown.c
Show First 20 Lines • Show All 891 Lines • ▼ Show 20 Lines | kerneldumpcrypto_create(size_t blocksize, uint8_t encryption, | ||||
return (kdc); | return (kdc); | ||||
failed: | failed: | ||||
explicit_bzero(kdc, sizeof(*kdc) + dumpkeysize); | explicit_bzero(kdc, sizeof(*kdc) + dumpkeysize); | ||||
free(kdc, M_EKCD); | free(kdc, M_EKCD); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
#endif /* EKCD */ | #endif /* EKCD */ | ||||
int | static int | ||||
kerneldumpcrypto_init(struct kerneldumpcrypto *kdc) | kerneldumpcrypto_init(struct kerneldumpcrypto *kdc) | ||||
{ | { | ||||
#ifndef EKCD | #ifndef EKCD | ||||
return (0); | return (0); | ||||
#else | #else | ||||
uint8_t hash[SHA256_DIGEST_LENGTH]; | uint8_t hash[SHA256_DIGEST_LENGTH]; | ||||
SHA256_CTX ctx; | SHA256_CTX ctx; | ||||
struct kerneldumpkey *kdk; | struct kerneldumpkey *kdk; | ||||
▲ Show 20 Lines • Show All 266 Lines • ▼ Show 20 Lines | dump_raw_write_pad(struct dumperinfo *di, void *virtual, vm_offset_t physical, | ||||
error = dump_pad(di, virtual, length, &buf, size); | error = dump_pad(di, virtual, length, &buf, size); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
return (dump_raw_write(di, buf, physical, offset, *size)); | return (dump_raw_write(di, buf, physical, offset, *size)); | ||||
} | } | ||||
int | static int | ||||
dump_write_pad(struct dumperinfo *di, void *virtual, vm_offset_t physical, | |||||
off_t offset, size_t length, size_t *size) | |||||
{ | |||||
void *buf; | |||||
int error; | |||||
error = dump_pad(di, virtual, length, &buf, size); | |||||
if (error != 0) | |||||
return (error); | |||||
return (dump_write(di, buf, physical, offset, *size)); | |||||
} | |||||
int | |||||
dump_write_header(struct dumperinfo *di, struct kerneldumpheader *kdh, | dump_write_header(struct dumperinfo *di, struct kerneldumpheader *kdh, | ||||
vm_offset_t physical, off_t offset) | vm_offset_t physical, off_t offset) | ||||
{ | { | ||||
size_t size; | size_t size; | ||||
int ret; | int ret; | ||||
ret = dump_raw_write_pad(di, kdh, physical, offset, sizeof(*kdh), | ret = dump_raw_write_pad(di, kdh, physical, offset, sizeof(*kdh), | ||||
&size); | &size); | ||||
if (ret == 0 && size != di->blocksize) | if (ret == 0 && size != di->blocksize) | ||||
ret = EINVAL; | ret = EINVAL; | ||||
return (ret); | return (ret); | ||||
} | } | ||||
int | static int | ||||
dump_write_key(struct dumperinfo *di, vm_offset_t physical, off_t offset) | dump_write_key(struct dumperinfo *di, vm_offset_t physical, off_t offset) | ||||
{ | { | ||||
#ifndef EKCD | #ifndef EKCD | ||||
return (0); | return (0); | ||||
#else /* EKCD */ | #else /* EKCD */ | ||||
struct kerneldumpcrypto *kdc; | struct kerneldumpcrypto *kdc; | ||||
kdc = di->kdc; | kdc = di->kdc; | ||||
if (kdc == NULL) | if (kdc == NULL) | ||||
return (0); | return (0); | ||||
return (dump_raw_write(di, kdc->kdc_dumpkey, physical, offset, | return (dump_raw_write(di, kdc->kdc_dumpkey, physical, offset, | ||||
kdc->kdc_dumpkeysize)); | kdc->kdc_dumpkeysize)); | ||||
#endif /* !EKCD */ | #endif /* !EKCD */ | ||||
} | |||||
/* | |||||
* Don't touch the first SIZEOF_METADATA bytes on the dump device. This is to | |||||
* protect us from metadata and metadata from us. | |||||
*/ | |||||
#define SIZEOF_METADATA (64 * 1024) | |||||
/* | |||||
* Do some preliminary setup for a kernel dump: verify that we have enough space | |||||
* on the dump device, write the leading header, and optionally write the crypto | |||||
* key. | |||||
*/ | |||||
int | |||||
dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh, off_t *dumplop) | |||||
{ | |||||
uint64_t dumpsize; | |||||
int error; | |||||
error = kerneldumpcrypto_init(di->kdc); | |||||
if (error != 0) | |||||
return (error); | |||||
dumpsize = dtoh64(kdh->dumplength) + 2 * di->blocksize + | |||||
kerneldumpcrypto_dumpkeysize(di->kdc); | |||||
if (di->mediasize < SIZEOF_METADATA + dumpsize) | |||||
return (E2BIG); | |||||
*dumplop = di->mediaoffset + di->mediasize - dumpsize; | |||||
error = dump_write_header(di, kdh, 0, *dumplop); | |||||
if (error != 0) | |||||
return (error); | |||||
*dumplop += di->blocksize; | |||||
error = dump_write_key(di, 0, *dumplop); | |||||
if (error != 0) | |||||
return (error); | |||||
*dumplop += kerneldumpcrypto_dumpkeysize(di->kdc); | |||||
return (0); | |||||
} | |||||
/* | |||||
* Write the trailing kernel dump header and signal to the lower layers that the | |||||
* dump has completed. | |||||
*/ | |||||
int | |||||
dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh, off_t dumplo) | |||||
{ | |||||
int error; | |||||
error = dump_write_header(di, kdh, 0, dumplo); | |||||
if (error != 0) | |||||
return (error); | |||||
(void)dump_write(di, NULL, 0, 0, 0); | |||||
return (0); | |||||
} | } | ||||
void | void | ||||
mkdumpheader(struct kerneldumpheader *kdh, char *magic, uint32_t archver, | mkdumpheader(struct kerneldumpheader *kdh, char *magic, uint32_t archver, | ||||
uint64_t dumplen, uint32_t dumpkeysize, uint32_t blksz) | uint64_t dumplen, uint32_t dumpkeysize, uint32_t blksz) | ||||
{ | { | ||||
size_t dstsize; | size_t dstsize; | ||||
Show All 28 Lines |