Files
s390-tools/zdump/df_elf.h
Marc Hartmayer 8fa1b5a00b zdump: dfi: add support to read Protected Virtualization dumps
Sometimes dumping a virtual machine from the outside is the only way to
get the data that is needed. This can be the case if a dumping mechanism
like kdump hasn't been configured or data needs to be fetched at a
specific point. Dumping a protected guest from the outside without help
from FW/HW doesn't yield sufficient data to be useful. Hence we have
introduced Protected Virtualization (PV) dump support - also named
confidential dump support.

The confidential dump support works by integrating the firmware into the
dump process. New Ultravisor calls (UVC) are used to initiate the dump
process, dump CPU data, dump memory state and lastly complete the dump
process. The guest's data is fully encrypted and can only be decrypted
by the entity that owns the customer communication key (CCK) for the
dumped guest. The output format is very similar the normal s390 vmcore
ELF format, it's only enriched by new sections where the returned data
from the UVC "Complete Configuration Dump" and the UVC "Dump
Configuration Storage State" is stored. The encrypted CPU data is stored
in a new note type `NT_S390_PV_CPU_DATA`. The old note types do still
exists but without any confidential data stored. The memory data is
stored in the LOAD segment as usual but for PV dumps it's fully AES-XTS
encrypted.

This commit adds support for reading/decrypting PV guest dumps to
zgetdump by introducing a new DFI input module (`dfi_pv_elf.c`). For
specifying the customer communication key a new command line option
`--key` is added.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:45:38 +01:00

294 lines
5.7 KiB
C

/*
* zgetdump - Tool for copying and converting System z dumps
*
* ELF core dump format definitions
*
* Copyright IBM Corp. 2001, 2017
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef DF_ELF_H
#define DF_ELF_H
#include <elf.h>
#include <linux/types.h>
#include <stdbool.h>
#include "lib/zt_common.h"
#include "zg.h"
#include "dfi.h"
#ifndef ELF_VERSION_1
#define ELF_VERSION_1 0x1
#endif
/*
* S390 CPU timer note (u64)
*/
#ifndef NT_S390_TIMER
#define NT_S390_TIMER 0x301
#endif
/*
* S390 TOD clock comparator note (u64)
*/
#ifndef NT_S390_TODCMP
#define NT_S390_TODCMP 0x302
#endif
/*
* S390 TOD programmable register note (u32)
*/
#ifndef NT_S390_TODPREG
#define NT_S390_TODPREG 0x303
#endif
/*
* S390 control registers note (16 * u32)
*/
#ifndef NT_S390_CTRS
#define NT_S390_CTRS 0x304
#endif
/*
* S390 prefix note (u32)
*/
#ifndef NT_S390_PREFIX
#define NT_S390_PREFIX 0x305
#endif
/*
* S390 vector registers 0-15 upper half note (16 * u64)
*/
#ifndef NT_S390_VXRS_LOW
#define NT_S390_VXRS_LOW 0x309
#endif
/*
* S390 vector registers 16-31 note (16 * u128)
*/
#ifndef NT_S390_VXRS_HIGH
#define NT_S390_VXRS_HIGH 0x30a
#endif
/*
* S390 guarded-storage registers note (4 * u64)
*/
#ifndef NT_S390_GS_CB
#define NT_S390_GS_CB 0x30b
#endif
/*
* S390 confidential CPU data from secure guest.
*/
#ifndef NT_S390_PV_CPU_DATA
#define NT_S390_PV_CPU_DATA 0x30e
#endif
#define NOTE_NAME_CORE "CORE"
#define NOTE_NAME_LINUX "LINUX"
#define NOTE_NAME_VMCOREINFO "VMCOREINFO"
#define ELF_NOTE_ROUNDUP(size) ROUNDUP(size, 4)
#define ELF_NOTE_NAME_SIZE(name) ELF_NOTE_ROUNDUP(name ? strlen(name) + 1 : 0)
#define ELF64_NOTE_SIZE(name, desc_size) \
(sizeof(Elf64_Nhdr) + ELF_NOTE_NAME_SIZE(name) + ELF_NOTE_ROUNDUP(desc_size))
/*
* prstatus ELF Note
*/
struct nt_prstatus_64 {
u8 pad1[32];
u32 pr_pid;
u8 pad2[76];
u64 psw[2];
u64 gprs[16];
u32 acrs[16];
u64 orig_gpr2;
u32 pr_fpvalid;
u8 pad3[4];
} __packed;
/*
* fpregset ELF Note
*/
struct nt_fpregset_64 {
u32 fpc;
u32 pad;
u64 fprs[16];
} __packed;
/*
* prpsinfo ELF Note
*/
struct nt_prpsinfo_64 {
char pr_state;
char pr_sname;
char pr_zomb;
char pr_nice;
u64 pr_flag;
u32 pr_uid;
u32 pr_gid;
u32 pr_pid, pr_ppid, pr_pgrp, pr_sid;
char pr_fname[16];
char pr_psargs[80];
};
static inline void df_elf_ensure_s390x(void)
{
#ifndef __s390x__
ERR_EXIT("The ELF dump format is only supported on s390x (64 bit)");
#endif
}
/*
* Initialize ELF header
*/
void *ehdr_init(Elf64_Ehdr *ehdr, Elf64_Half phnum);
/*
* Checks whether @ehdr is a ELF object
*/
bool ehdr_is_elf_object(const Elf64_Ehdr *ehdr);
/*
* Checks whether @ehdr is a vmcore
*/
bool ehdr_is_vmcore(const Elf64_Ehdr *ehdr);
/*
* Checks whether @ehdr is a s390x header
*/
bool ehdr_is_s390x(const Elf64_Ehdr *ehdr);
/*
* Verify that given header is a s390x ELF header
*/
int ehdr_check_s390x(const Elf64_Ehdr *ehdr);
/*
* Read ELF header at current offset
*/
Elf64_Ehdr *read_elf_hdr(const struct zg_fh *fh);
/*
* Read ELF program headers
*
* To read the program headers the offset of @fh is changed.
*/
Elf64_Phdr *read_elf_phdrs(const struct zg_fh *fh, const Elf64_Ehdr *ehdr,
unsigned int *phdr_count);
/*
* Read ELF section headers
*
* To read the section headers the offset of @fh is changed.
*/
Elf64_Shdr *read_elf_shdrs(const struct zg_fh *fh, const Elf64_Ehdr *ehdr,
unsigned int *shdr_count);
/*
* Read ELF section content
*
* To read the section content the offset of @fh is changed.
*/
unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *shdr, size_t *size);
/*
* Read ELF section header string table
*
* To read the section header string table the offset of @fh is changed.
*/
char *read_elf_shstrtab(const struct zg_fh *fh, const Elf64_Ehdr *ehdr, const Elf64_Shdr *shdrs,
const unsigned int shnum, size_t *shstrtab_size);
/*
* Find ELF section header by section name
*/
const Elf64_Shdr *find_elf_shdr_by_name(const Elf64_Shdr *shdrs, const unsigned int shnum,
const char *shstrtab, const size_t shstrtab_size,
const char *name);
/*
* Read note and store the note description in @buf
*/
int nt_read(const struct zg_fh *fh, const Elf64_Nhdr *note, void *buf, size_t buf_len);
/*
* Skip note
*/
void nt_skip(const struct zg_fh *fh, const Elf64_Nhdr *note);
/*
* Initialize ELF note
*/
void *nt_init(void *buf, Elf64_Word type, const void *desc, int d_len,
const char *name);
/*
* Initialize prstatus note
*/
void *nt_prstatus(void *ptr, const struct dfi_cpu *cpu);
/*
* Initialize fpregset (floating point) note
*/
void *nt_fpregset(void *ptr, const struct dfi_cpu *cpu);
/*
* Initialize timer note
*/
void *nt_s390_timer(void *ptr, const struct dfi_cpu *cpu);
/*
* Initialize TOD clock comparator note
*/
void *nt_s390_tod_cmp(void *ptr, const struct dfi_cpu *cpu);
/*
* Initialize TOD programmable register note
*/
void *nt_s390_tod_preg(void *ptr, const struct dfi_cpu *cpu);
/*
* Initialize control register note
*/
void *nt_s390_ctrs(void *ptr, const struct dfi_cpu *cpu);
/*
* Initialize prefix register note
*/
void *nt_s390_prefix(void *ptr, const struct dfi_cpu *cpu);
/*
* Initialize vxrs_low register note
*/
void *nt_s390_vxrs_low(void *ptr, const struct dfi_cpu *cpu);
/*
* Initialize vxrs_high register note
*/
void *nt_s390_vxrs_high(void *ptr, const struct dfi_cpu *cpu);
/*
* Initialize guarded-storage registers note
*/
void *nt_s390_gs_cb(void *ptr, const struct dfi_cpu *cpu);
/*
* Initialize prpsinfo note
*/
void *nt_prpsinfo(void *ptr);
/*
* Initialize vmcoreinfo note
*/
void *nt_vmcoreinfo(void *ptr, const char *vmcoreinfo);
size_t get_max_note_size_per_cpu(void);
#endif /* DF_ELF_H */