Files
systemd/src/shared/pe-binary.h
Lennart Poettering ef2dbc9c40 pe-binary: actually check if PE binary is UEFI binary when determining if UKI
If it's not a UEFI binary, then it's not a UKI.
2023-09-29 21:54:16 +02:00

145 lines
5.0 KiB
C

/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <sys/types.h>
#include "sparse-endian.h"
/* When naming things we try to stay close to the official Windows APIs as per:
* → https://learn.microsoft.com/en-us/windows/win32/debug/pe-format */
typedef struct _packed_ _IMAGE_DOS_HEADER {
le16_t e_magic;
le16_t e_cblp;
le16_t e_cp;
le16_t e_crlc;
le16_t e_cparhdr;
le16_t e_minalloc;
le16_t e_maxalloc;
le16_t e_ss;
le16_t e_sp;
le16_t e_csum;
le16_t e_ip;
le16_t e_cs;
le16_t e_lfarlc;
le16_t e_ovno;
le16_t e_res[4];
le16_t e_oemid;
le16_t e_oeminfo;
le16_t e_res2[10];
le32_t e_lfanew;
} IMAGE_DOS_HEADER;
typedef struct _packed_ _IMAGE_FILE_HEADER {
le16_t Machine;
le16_t NumberOfSections;
le32_t TimeDateStamp;
le32_t PointerToSymbolTable;
le32_t NumberOfSymbols;
le16_t SizeOfOptionalHeader;
le16_t Characteristics;
} IMAGE_FILE_HEADER;
typedef struct _packed_ _IMAGE_DATA_DIRECTORY {
le32_t VirtualAddress;
le32_t Size;
} IMAGE_DATA_DIRECTORY;
typedef struct _packed_ _IMAGE_OPTIONAL_HEADER {
/* Standard fields */
le16_t Magic;
uint8_t MajorLinkerVersion;
uint8_t MinorLinkerVersion;
le32_t SizeOfCode;
le32_t SizeOfInitializedData;
le32_t SizeOfUninitializedData;
le32_t AddressOfEntryPoint;
le32_t BaseOfCode;
/* Here the PE32 and PE32+ headers differ: PE32+ has one 64bit field, PE32+ has two 32bit fields */
union {
struct {
le32_t BaseOfData;
le32_t pe32_ImageBase;
};
le64_t pe32plus_ImageBase;
};
/* Additional fields */
le32_t SectionAlignment;
le32_t FileAlignment;
le16_t MajorOperatingSystemVersion;
le16_t MinorOperatingSystemVersion;
le16_t MajorImageVersion;
le16_t MinorImageVersion;
le16_t MajorSubsystemVersion;
le16_t MinorSubsystemVersion;
le32_t Win32VersionValue;
le32_t SizeOfImage;
le32_t SizeOfHeaders;
le32_t CheckSum;
le16_t Subsystem;
le16_t DllCharacteristics;
/* Here similar: on PE32+ some fields are 64bit that are 32bit on PE32. */
union {
struct {
le32_t pe32_SizeOfStackReserve;
le32_t pe32_SizeOfStackCommit;
le32_t pe32_SizeOfHeapReserve;
le32_t pe32_SizeOfHeapCommit;
le32_t pe32_LoaderFlags;
le32_t pe32_NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY pe32_DataDirectory[];
};
struct {
le64_t pe32plus_SizeOfStackReserve;
le64_t pe32plus_SizeOfStackCommit;
le64_t pe32plus_SizeOfHeapReserve;
le64_t pe32plus_SizeOfHeapCommit;
le32_t pe32plus_LoaderFlags;
le32_t pe32plus_NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY pe32plus_DataDirectory[];
};
};
} IMAGE_OPTIONAL_HEADER;
typedef struct _packed_ PeHeader {
le32_t signature;
IMAGE_FILE_HEADER pe;
IMAGE_OPTIONAL_HEADER optional;
} PeHeader;
typedef struct _packed_ _IMAGE_SECTION_HEADER {
uint8_t Name[8];
le32_t VirtualSize;
le32_t VirtualAddress;
le32_t SizeOfRawData;
le32_t PointerToRawData;
le32_t PointerToRelocations;
le32_t PointerToLinenumbers;
le16_t NumberOfRelocations;
le16_t NumberOfLinenumbers;
le32_t Characteristics;
} IMAGE_SECTION_HEADER;
#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10
bool pe_header_is_64bit(const PeHeader *h);
#define PE_HEADER_OPTIONAL_FIELD(h, field) \
(pe_header_is_64bit(h) ? (h)->optional.pe32plus_##field : (h)->optional.pe32_##field)
#define PE_HEADER_OPTIONAL_FIELD_OFFSET(h, field) \
(pe_header_is_64bit(h) ? offsetof(PeHeader, optional.pe32plus_##field) : offsetof(PeHeader, optional.pe32_##field))
const IMAGE_DATA_DIRECTORY *pe_header_get_data_directory(const PeHeader *h, size_t i);
const IMAGE_SECTION_HEADER *pe_header_find_section(const PeHeader *pe_header, const IMAGE_SECTION_HEADER *sections, const char *name);
int pe_load_headers(int fd, IMAGE_DOS_HEADER **ret_dos_header, PeHeader **ret_pe_header);
int pe_load_sections(int fd, const IMAGE_DOS_HEADER *dos_header, const PeHeader *pe_header, IMAGE_SECTION_HEADER **ret_sections);
int pe_read_section_data(int fd, const PeHeader *pe_header, const IMAGE_SECTION_HEADER *sections, const char *name, size_t max_size, void **ret, size_t *ret_size);
bool pe_is_uki(const PeHeader *pe_header, const IMAGE_SECTION_HEADER *sections);