Skip to content

Commit 206e22f

Browse files
ckennellytorvalds
authored andcommitted
tools/testing/selftests: add self-test for verifying load alignment
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]>
1 parent ce81bb2 commit 206e22f

File tree

3 files changed

+76
-2
lines changed

3 files changed

+76
-2
lines changed

tools/testing/selftests/exec/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ execveat.moved
77
execveat.path.ephemeral
88
execveat.ephemeral
99
execveat.denatured
10+
/load_address_*
1011
/recursion-depth
1112
xxxxxxxx*
1213
pipe

tools/testing/selftests/exec/Makefile

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ CFLAGS += -Wno-nonnull
44
CFLAGS += -D_GNU_SOURCE
55

66
TEST_PROGS := binfmt_script non-regular
7-
TEST_GEN_PROGS := execveat
7+
TEST_GEN_PROGS := execveat load_address_4096 load_address_2097152 load_address_16777216
88
TEST_GEN_FILES := execveat.symlink execveat.denatured script subdir pipe
99
# Makefile is a run-time dependency, since it's accessed by the execveat test
1010
TEST_FILES := Makefile
@@ -27,4 +27,9 @@ $(OUTPUT)/execveat.symlink: $(OUTPUT)/execveat
2727
$(OUTPUT)/execveat.denatured: $(OUTPUT)/execveat
2828
cp $< $@
2929
chmod -x $@
30-
30+
$(OUTPUT)/load_address_4096: load_address.c
31+
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000 -pie $< -o $@
32+
$(OUTPUT)/load_address_2097152: load_address.c
33+
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x200000 -pie $< -o $@
34+
$(OUTPUT)/load_address_16777216: load_address.c
35+
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000000 -pie $< -o $@
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
#ifndef _GNU_SOURCE
3+
#define _GNU_SOURCE
4+
#endif
5+
#include <link.h>
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
9+
struct Statistics {
10+
unsigned long long load_address;
11+
unsigned long long alignment;
12+
};
13+
14+
int ExtractStatistics(struct dl_phdr_info *info, size_t size, void *data)
15+
{
16+
struct Statistics *stats = (struct Statistics *) data;
17+
int i;
18+
19+
if (info->dlpi_name != NULL && info->dlpi_name[0] != '\0') {
20+
// Ignore headers from other than the executable.
21+
return 2;
22+
}
23+
24+
stats->load_address = (unsigned long long) info->dlpi_addr;
25+
stats->alignment = 0;
26+
27+
for (i = 0; i < info->dlpi_phnum; i++) {
28+
if (info->dlpi_phdr[i].p_type != PT_LOAD)
29+
continue;
30+
31+
if (info->dlpi_phdr[i].p_align > stats->alignment)
32+
stats->alignment = info->dlpi_phdr[i].p_align;
33+
}
34+
35+
return 1; // Terminate dl_iterate_phdr.
36+
}
37+
38+
int main(int argc, char **argv)
39+
{
40+
struct Statistics extracted;
41+
unsigned long long misalign;
42+
int ret;
43+
44+
ret = dl_iterate_phdr(ExtractStatistics, &extracted);
45+
if (ret != 1) {
46+
fprintf(stderr, "FAILED\n");
47+
return 1;
48+
}
49+
50+
if (extracted.alignment == 0) {
51+
fprintf(stderr, "No alignment found\n");
52+
return 1;
53+
} else if (extracted.alignment & (extracted.alignment - 1)) {
54+
fprintf(stderr, "Alignment is not a power of 2\n");
55+
return 1;
56+
}
57+
58+
misalign = extracted.load_address & (extracted.alignment - 1);
59+
if (misalign) {
60+
printf("alignment = %llu, load_address = %llu\n",
61+
extracted.alignment, extracted.load_address);
62+
fprintf(stderr, "FAILED\n");
63+
return 1;
64+
}
65+
66+
fprintf(stderr, "PASS\n");
67+
return 0;
68+
}

0 commit comments

Comments
 (0)