Skip to content

Commit b57a290

Browse files
committed
selftests/exec: Build both static and non-static load_address tests
After commit 4d1cd3b ("tools/testing/selftests/exec: fix link error"), the load address alignment tests tried to build statically. This was silently ignored in some cases. However, after attempting to further fix the build by switching to "-static-pie", the test started failing. This appears to be due to non-PT_INTERP ET_DYN execs ("static PIE") not doing alignment correctly, which remains unfixed[1]. See commit aeb7923 ("revert "fs/binfmt_elf: use PT_LOAD p_align values for static PIE"") for more details. Provide rules to build both static and non-static PIE binaries, improve debug reporting, and perform several test steps instead of a single all-or-nothing test. However, do not actually enable static-pie tests; alignment specification is only supported for ET_DYN with PT_INTERP ("regular PIE"). Link: https://bugzilla.kernel.org/show_bug.cgi?id=215275 [1] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Kees Cook <[email protected]>
1 parent c3f38fa commit b57a290

File tree

2 files changed

+66
-20
lines changed

2 files changed

+66
-20
lines changed

tools/testing/selftests/exec/Makefile

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@ CFLAGS = -Wall
33
CFLAGS += -Wno-nonnull
44
CFLAGS += -D_GNU_SOURCE
55

6+
ALIGNS := 0x1000 0x200000 0x1000000
7+
ALIGN_PIES := $(patsubst %,load_address.%,$(ALIGNS))
8+
ALIGN_STATIC_PIES := $(patsubst %,load_address.static.%,$(ALIGNS))
9+
ALIGNMENT_TESTS := $(ALIGN_PIES)
10+
611
TEST_PROGS := binfmt_script.py
7-
TEST_GEN_PROGS := execveat load_address_4096 load_address_2097152 load_address_16777216 non-regular
12+
TEST_GEN_PROGS := execveat non-regular $(ALIGNMENT_TESTS)
813
TEST_GEN_FILES := execveat.symlink execveat.denatured script subdir
914
# Makefile is a run-time dependency, since it's accessed by the execveat test
1015
TEST_FILES := Makefile
@@ -28,9 +33,9 @@ $(OUTPUT)/execveat.symlink: $(OUTPUT)/execveat
2833
$(OUTPUT)/execveat.denatured: $(OUTPUT)/execveat
2934
cp $< $@
3035
chmod -x $@
31-
$(OUTPUT)/load_address_4096: load_address.c
32-
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000 -pie -static $< -o $@
33-
$(OUTPUT)/load_address_2097152: load_address.c
34-
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x200000 -pie -static $< -o $@
35-
$(OUTPUT)/load_address_16777216: load_address.c
36-
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000000 -pie -static $< -o $@
36+
$(OUTPUT)/load_address.0x%: load_address.c
37+
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=$(lastword $(subst ., ,$@)) \
38+
-fPIE -pie $< -o $@
39+
$(OUTPUT)/load_address.static.0x%: load_address.c
40+
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=$(lastword $(subst ., ,$@)) \
41+
-fPIE -static-pie $< -o $@

tools/testing/selftests/exec/load_address.c

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
#include <link.h>
66
#include <stdio.h>
77
#include <stdlib.h>
8+
#include <stdbool.h>
89
#include "../kselftest.h"
910

1011
struct Statistics {
1112
unsigned long long load_address;
1213
unsigned long long alignment;
14+
bool interp;
1315
};
1416

1517
int ExtractStatistics(struct dl_phdr_info *info, size_t size, void *data)
@@ -26,39 +28,78 @@ int ExtractStatistics(struct dl_phdr_info *info, size_t size, void *data)
2628
stats->alignment = 0;
2729

2830
for (i = 0; i < info->dlpi_phnum; i++) {
31+
unsigned long long align;
32+
33+
if (info->dlpi_phdr[i].p_type == PT_INTERP) {
34+
stats->interp = true;
35+
continue;
36+
}
37+
2938
if (info->dlpi_phdr[i].p_type != PT_LOAD)
3039
continue;
3140

32-
if (info->dlpi_phdr[i].p_align > stats->alignment)
33-
stats->alignment = info->dlpi_phdr[i].p_align;
41+
align = info->dlpi_phdr[i].p_align;
42+
43+
if (align > stats->alignment)
44+
stats->alignment = align;
3445
}
3546

3647
return 1; // Terminate dl_iterate_phdr.
3748
}
3849

3950
int main(int argc, char **argv)
4051
{
41-
struct Statistics extracted;
42-
unsigned long long misalign;
52+
struct Statistics extracted = { };
53+
unsigned long long misalign, pow2;
54+
bool interp_needed;
55+
char buf[1024];
56+
FILE *maps;
4357
int ret;
4458

4559
ksft_print_header();
46-
ksft_set_plan(1);
60+
ksft_set_plan(4);
61+
62+
/* Dump maps file for debugging reference. */
63+
maps = fopen("/proc/self/maps", "r");
64+
if (!maps)
65+
ksft_exit_fail_msg("FAILED: /proc/self/maps: %s\n", strerror(errno));
66+
while (fgets(buf, sizeof(buf), maps)) {
67+
ksft_print_msg("%s", buf);
68+
}
69+
fclose(maps);
4770

71+
/* Walk the program headers. */
4872
ret = dl_iterate_phdr(ExtractStatistics, &extracted);
4973
if (ret != 1)
5074
ksft_exit_fail_msg("FAILED: dl_iterate_phdr\n");
5175

52-
if (extracted.alignment == 0)
53-
ksft_exit_fail_msg("FAILED: No alignment found\n");
54-
else if (extracted.alignment & (extracted.alignment - 1))
55-
ksft_exit_fail_msg("FAILED: Alignment is not a power of 2\n");
76+
/* Report our findings. */
77+
ksft_print_msg("load_address=%#llx alignment=%#llx\n",
78+
extracted.load_address, extracted.alignment);
79+
80+
/* If we're named with ".static." we expect no INTERP. */
81+
interp_needed = strstr(argv[0], ".static.") == NULL;
82+
83+
/* Were we built as expected? */
84+
ksft_test_result(interp_needed == extracted.interp,
85+
"%s INTERP program header %s\n",
86+
interp_needed ? "Wanted" : "Unwanted",
87+
extracted.interp ? "seen" : "missing");
88+
89+
/* Did we find an alignment? */
90+
ksft_test_result(extracted.alignment != 0,
91+
"Alignment%s found\n", extracted.alignment ? "" : " NOT");
92+
93+
/* Is the alignment sane? */
94+
pow2 = extracted.alignment & (extracted.alignment - 1);
95+
ksft_test_result(pow2 == 0,
96+
"Alignment is%s a power of 2: %#llx\n",
97+
pow2 == 0 ? "" : " NOT", extracted.alignment);
5698

99+
/* Is the load address aligned? */
57100
misalign = extracted.load_address & (extracted.alignment - 1);
58-
if (misalign)
59-
ksft_exit_fail_msg("FAILED: alignment = %llu, load_address = %llu\n",
60-
extracted.alignment, extracted.load_address);
101+
ksft_test_result(misalign == 0, "Load Address is %saligned (%#llx)\n",
102+
misalign ? "MIS" : "", misalign);
61103

62-
ksft_test_result_pass("Completed\n");
63104
ksft_finished();
64105
}

0 commit comments

Comments
 (0)