Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

post-process-pe: add tests to validate NX compliance #705

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/peimage.h
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,7 @@ typedef struct {
EFI_IMAGE_DATA_DIRECTORY *RelocDir;
EFI_IMAGE_DATA_DIRECTORY *SecDir;
UINT64 NumberOfRvaAndSizes;
UINT16 DllCharacteristics;
EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr;
} PE_COFF_LOADER_IMAGE_CONTEXT;

Expand Down
60 changes: 59 additions & 1 deletion post-process-pe.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ static int verbosity;
})

static bool set_nx_compat = false;
static bool require_nx_compat = false;

typedef uint8_t UINT8;
typedef uint16_t UINT16;
Expand Down Expand Up @@ -162,6 +163,7 @@ load_pe(const char *const file, void *const data, const size_t datasize,
ctx->ImageSize = PEHdr->Pe32Plus.OptionalHeader.SizeOfImage;
ctx->SectionAlignment =
PEHdr->Pe32Plus.OptionalHeader.SectionAlignment;
ctx->DllCharacteristics = PEHdr->Pe32Plus.OptionalHeader.DllCharacteristics;
FileAlignment = PEHdr->Pe32Plus.OptionalHeader.FileAlignment;
OptHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER64);
} else {
Expand All @@ -172,6 +174,7 @@ load_pe(const char *const file, void *const data, const size_t datasize,
ctx->ImageSize = (UINT64)PEHdr->Pe32.OptionalHeader.SizeOfImage;
ctx->SectionAlignment =
PEHdr->Pe32.OptionalHeader.SectionAlignment;
ctx->DllCharacteristics = PEHdr->Pe32.OptionalHeader.DllCharacteristics;
FileAlignment = PEHdr->Pe32.OptionalHeader.FileAlignment;
OptHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER32);
}
Expand Down Expand Up @@ -358,6 +361,50 @@ set_dll_characteristics(PE_COFF_LOADER_IMAGE_CONTEXT *ctx)
} else {
ctx->PEHdr->Pe32.OptionalHeader.DllCharacteristics = newflags;
}
ctx->DllCharacteristics = newflags;
}

static int
validate_nx_compat(PE_COFF_LOADER_IMAGE_CONTEXT *ctx)
{
EFI_IMAGE_SECTION_HEADER *Section;
int i;
bool nx_compat_flag;
const int level = require_nx_compat ? ERROR : WARNING;
int ret = 0;

nx_compat_flag = EFI_IMAGE_DLLCHARACTERISTICS_NX_COMPAT
& ctx->DllCharacteristics;
debug(NOISE, "NX-Compat-Flag: %s\n", nx_compat_flag ? "set" : "unset");
if (!nx_compat_flag) {
debug(level, "NX Compatibility flag is not set\n");
if (require_nx_compat)
ret = -1;
}

debug(NOISE, "Section alignment is 0x%x, page size is 0x%x\n",
ctx->SectionAlignment, PAGE_SIZE);
if (ctx->SectionAlignment != PAGE_SIZE) {
debug(level, "Section alignment is not page aligned\n");
if (require_nx_compat)
ret = -1;
}

Section = ctx->FirstSection;
for (i=0, Section = ctx->FirstSection; i < ctx->NumberOfSections; i++, Section++) {
debug(NOISE, "Section %d has WRITE=%d and EXECUTE=%d\n", i,
(Section->Characteristics & EFI_IMAGE_SCN_MEM_WRITE) ? 1 : 0,
(Section->Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) ? 1 : 0);

if ((Section->Characteristics & EFI_IMAGE_SCN_MEM_WRITE) &&
(Section->Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE)) {
debug(level, "Section %d is writable and executable\n", i);
if (require_nx_compat)
ret = -1;
}
}

return ret;
}

static void
Expand Down Expand Up @@ -449,6 +496,10 @@ handle_one(char *f)

set_dll_characteristics(&ctx);

rc = validate_nx_compat(&ctx);
if (rc < 0)
err(2, "NX compatibility check failed\n");

fix_timestamp(&ctx);

fix_checksum(&ctx, map, sz);
Expand Down Expand Up @@ -483,6 +534,7 @@ static void __attribute__((__noreturn__)) usage(int status)
fprintf(out, " -v Be more verbose\n");
fprintf(out, " -N Disable the NX compatibility flag\n");
fprintf(out, " -n Enable the NX compatibility flag\n");
fprintf(out, " -x Error on NX incompatibility\n");
fprintf(out, " -h Print this help text and exit\n");

exit(status);
Expand Down Expand Up @@ -510,11 +562,14 @@ int main(int argc, char **argv)
{.name = "verbose",
.val = 'v',
},
{.name = "error-nx-compat",
.val = 'x',
},
{.name = ""}
};
int longindex = -1;

while ((i = getopt_long(argc, argv, "hNnqv", options, &longindex)) != -1) {
while ((i = getopt_long(argc, argv, "hNnqvx", options, &longindex)) != -1) {
switch (i) {
case 'h':
case '?':
Expand All @@ -532,6 +587,9 @@ int main(int argc, char **argv)
case 'v':
verbosity = MIN(verbosity + 1, MAX_VERBOSITY);
break;
case 'x':
require_nx_compat = true;
break;
}
}

Expand Down