Skip to content

Commit 10936eb

Browse files
committed
vsyscall_trace: Add a test mode using a faked vsyscall base address
1 parent dfd0ecc commit 10936eb

File tree

6 files changed

+55
-9
lines changed

6 files changed

+55
-9
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ matrix:
2525
script:
2626
- make -C docker/vsyscall_emu
2727
- docker build --rm -t quay.io/pypa/manylinux1_$PLATFORM:$TRAVIS_COMMIT -f docker/Dockerfile-$PLATFORM docker/
28+
- docker/vsyscall_emu/test.sh quay.io/pypa/manylinux1_$PLATFORM:$TRAVIS_COMMIT
2829

2930

3031
deploy:

docker/vsyscall_emu/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
vsyscall_trace
2+
vsyscall_trace_test

docker/vsyscall_emu/Makefile

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
1+
PLATFORM ?= $(shell uname -m)
2+
13
ifeq ($(PLATFORM),x86_64)
2-
all: vsyscall_trace
4+
TARGETS = vsyscall_trace vsyscall_trace_test
35
else
4-
all:
6+
TARGETS =
57
endif
68

9+
all: $(TARGETS)
10+
711
vsyscall_trace: vsyscall_trace.c
812
$(CC) -o $@ $< -ldl
913

14+
vsyscall_trace_test: vsyscall_trace.c
15+
$(CC) -o $@ $< -ldl -DVSYSCALL_BASE=0xfffffffffe600000 -DDEBUG
16+
1017
clean:
11-
$(RM) -f vsyscall_trace
18+
$(RM) $(TARGETS)
1219

1320
.PHONY: clean

docker/vsyscall_emu/maps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fffffffffe600000-fffffffffe601000 --xp 00000000 00:00 0 [vsyscall]

docker/vsyscall_emu/test.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/bash
2+
#
3+
# Test vsyscall_trace, either on a docker image if a name is provided or
4+
# directly on the host otherwise.
5+
6+
set -e
7+
8+
# Get build utilities
9+
cd "$(dirname "${BASH_SOURCE[0]}")"
10+
source ../build_scripts/build_utils.sh
11+
12+
set -x
13+
14+
# Run the kernel vsyscall test command with a fake vsyscall page
15+
# address, so that we're guaranteed that the host kernel will segfault
16+
# on the attempted vsyscalls.
17+
curl -sSLO https://github.com/torvalds/linux/raw/v4.15/tools/testing/selftests/x86/test_vsyscall.c
18+
check_sha256sum test_vsyscall.c ff55a0c8ae2fc03a248a7fa1c47ba00bfe73abcef09606b6708e01f246a4f2b5
19+
sed -i -e 's/0xffffffffff6/0xfffffffffe6/' -e 's|/proc/self/maps|/proc/self/cwd/maps|' test_vsyscall.c
20+
cc -ggdb3 -o test_vsyscall test_vsyscall.c -ldl
21+
22+
if [ -n "$1" ]; then
23+
docker run -v "$PWD":/vsyscall_emu --rm --entrypoint /vsyscall_emu/vsyscall_trace_test --security-opt=seccomp:unconfined --workdir /vsyscall_emu "$1" ./test_vsyscall
24+
else
25+
./vsyscall_trace_test ./test_vsyscall
26+
fi
27+
28+
rm -f test_vsyscall test_vsyscall.c

docker/vsyscall_emu/vsyscall_trace.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,16 @@
4141

4242
/* These are ABI constants: see arch/x86/include/uapi/asm/vsyscall.h
4343
* in the kernel source (probably installed on your system as
44-
* <asm/vsyscall.h>). They start at VSYSCALL_ADDR, and
45-
* increase by 1024 for each call. */
46-
const unsigned long VSYS_gettimeofday = 0xffffffffff600000,
47-
VSYS_time = 0xffffffffff600400,
48-
VSYS_getcpu = 0xffffffffff600800;
44+
* <asm/vsyscall.h> - we don't directly use this header so that this
45+
* program continues to compile when it is removed). They start at
46+
* VSYSCALL_ADDR, and increase by 1024 for each call. */
47+
48+
#ifndef VSYSCALL_BASE
49+
#define VSYSCALL_BASE 0xffffffffff600000
50+
#endif
51+
const unsigned long VSYS_gettimeofday = VSYSCALL_BASE + 0,
52+
VSYS_time = VSYSCALL_BASE + 0x400,
53+
VSYS_getcpu = VSYSCALL_BASE + 0x800;
4954

5055
/* The vDSO is an area of memory that looks like a normal relocatable
5156
* dynamic library, magically placed in your address space by the
@@ -91,13 +96,15 @@ unsigned long vdso_address(pid_t pid) {
9196
int handle_vsyscall(pid_t pid) {
9297
struct user_regs_struct regs;
9398
ptrace(PTRACE_GETREGS, pid, 0, &regs);
94-
if ((regs.rip & 0xfffffffffffff0ff) == 0xffffffffff600000) {
99+
debug_printf("got a segfault at %p\n", regs.rip);
100+
if ((regs.rip & 0xfffffffffffff0ff) == VSYSCALL_BASE) {
95101
debug_printf("handling vsyscall for %d\n", pid);
96102
unsigned long vdso = vdso_address(pid);
97103
if (vdso_address == 0) {
98104
debug_printf("couldn't find vdso\n");
99105
return 0;
100106
}
107+
debug_printf("vdso address is %p\n", vdso);
101108

102109
if (regs.rip == VSYS_gettimeofday) {
103110
regs.rip = vdso | VDSO_gettimeofday;
@@ -109,6 +116,7 @@ int handle_vsyscall(pid_t pid) {
109116
debug_printf("invalid vsyscall %x\n", regs.rip);
110117
return 0;
111118
}
119+
debug_printf("fixing up rip to %p\n", regs.rip);
112120
ptrace(PTRACE_SETREGS, pid, 0, &regs);
113121
return 1;
114122
}

0 commit comments

Comments
 (0)