Skip to content

Commit

Permalink
tools/testing/selftests: add self-test for verifying load alignment
Browse files Browse the repository at this point in the history
This produces a PIE binary with a variety of p_align requirements,
suitable for verifying that the load address meets that alignment
requirement.

Signed-off-by: Chris Kennelly <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Cc: Shuah Khan <[email protected]>
Cc: Alexander Viro <[email protected]>
Cc: Alexey Dobriyan <[email protected]>
Cc: David Rientjes <[email protected]>
Cc: Fangrui Song <[email protected]>
Cc: Hugh Dickens <[email protected]>
Cc: Ian Rogers <[email protected]>
Cc: "Kirill A. Shutemov" <[email protected]>
Cc: Mike Kravetz <[email protected]>
Cc: Nick Desaulniers <[email protected]>
Cc: Sandeep Patil <[email protected]>
Cc: Song Liu <[email protected]>
Cc: Suren Baghdasaryan <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
ckennelly authored and torvalds committed Oct 16, 2020
1 parent ce81bb2 commit 206e22f
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 2 deletions.
1 change: 1 addition & 0 deletions tools/testing/selftests/exec/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ execveat.moved
execveat.path.ephemeral
execveat.ephemeral
execveat.denatured
/load_address_*
/recursion-depth
xxxxxxxx*
pipe
Expand Down
9 changes: 7 additions & 2 deletions tools/testing/selftests/exec/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ CFLAGS += -Wno-nonnull
CFLAGS += -D_GNU_SOURCE

TEST_PROGS := binfmt_script non-regular
TEST_GEN_PROGS := execveat
TEST_GEN_PROGS := execveat load_address_4096 load_address_2097152 load_address_16777216
TEST_GEN_FILES := execveat.symlink execveat.denatured script subdir pipe
# Makefile is a run-time dependency, since it's accessed by the execveat test
TEST_FILES := Makefile
Expand All @@ -27,4 +27,9 @@ $(OUTPUT)/execveat.symlink: $(OUTPUT)/execveat
$(OUTPUT)/execveat.denatured: $(OUTPUT)/execveat
cp $< $@
chmod -x $@

$(OUTPUT)/load_address_4096: load_address.c
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000 -pie $< -o $@
$(OUTPUT)/load_address_2097152: load_address.c
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x200000 -pie $< -o $@
$(OUTPUT)/load_address_16777216: load_address.c
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000000 -pie $< -o $@
68 changes: 68 additions & 0 deletions tools/testing/selftests/exec/load_address.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: GPL-2.0-only
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <link.h>
#include <stdio.h>
#include <stdlib.h>

struct Statistics {
unsigned long long load_address;
unsigned long long alignment;
};

int ExtractStatistics(struct dl_phdr_info *info, size_t size, void *data)
{
struct Statistics *stats = (struct Statistics *) data;
int i;

if (info->dlpi_name != NULL && info->dlpi_name[0] != '\0') {
// Ignore headers from other than the executable.
return 2;
}

stats->load_address = (unsigned long long) info->dlpi_addr;
stats->alignment = 0;

for (i = 0; i < info->dlpi_phnum; i++) {
if (info->dlpi_phdr[i].p_type != PT_LOAD)
continue;

if (info->dlpi_phdr[i].p_align > stats->alignment)
stats->alignment = info->dlpi_phdr[i].p_align;
}

return 1; // Terminate dl_iterate_phdr.
}

int main(int argc, char **argv)
{
struct Statistics extracted;
unsigned long long misalign;
int ret;

ret = dl_iterate_phdr(ExtractStatistics, &extracted);
if (ret != 1) {
fprintf(stderr, "FAILED\n");
return 1;
}

if (extracted.alignment == 0) {
fprintf(stderr, "No alignment found\n");
return 1;
} else if (extracted.alignment & (extracted.alignment - 1)) {
fprintf(stderr, "Alignment is not a power of 2\n");
return 1;
}

misalign = extracted.load_address & (extracted.alignment - 1);
if (misalign) {
printf("alignment = %llu, load_address = %llu\n",
extracted.alignment, extracted.load_address);
fprintf(stderr, "FAILED\n");
return 1;
}

fprintf(stderr, "PASS\n");
return 0;
}

0 comments on commit 206e22f

Please sign in to comment.