Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

proc: save LOC in vsyscall test

Do one fork in vsyscall detection code and let SIGSEGV handler exit and
carry information to the parent saving LOC.

[adobriyan@gmail.com: redo original patch, delete unnecessary variables, minimise code changes]
Link: https://lkml.kernel.org/r/YvoWzAn5dlhF75xa@localhost.localdomain
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Tested-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Brian Foster and committed by
Andrew Morton
f4068af3 4f1d2a03

+16 -40
+16 -40
tools/testing/selftests/proc/proc-pid-vm.c
··· 213 213 214 214 /* 215 215 * 0: vsyscall VMA doesn't exist vsyscall=none 216 - * 1: vsyscall VMA is r-xp vsyscall=emulate 217 - * 2: vsyscall VMA is --xp vsyscall=xonly 216 + * 1: vsyscall VMA is --xp vsyscall=xonly 217 + * 2: vsyscall VMA is r-xp vsyscall=emulate 218 218 */ 219 - static int g_vsyscall; 219 + static volatile int g_vsyscall; 220 220 static const char *str_vsyscall; 221 221 222 222 static const char str_vsyscall_0[] = ""; 223 223 static const char str_vsyscall_1[] = 224 - "ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n"; 225 - static const char str_vsyscall_2[] = 226 224 "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]\n"; 225 + static const char str_vsyscall_2[] = 226 + "ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n"; 227 227 228 228 #ifdef __x86_64__ 229 229 static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___) 230 230 { 231 - _exit(1); 231 + _exit(g_vsyscall); 232 232 } 233 233 234 234 /* ··· 255 255 act.sa_sigaction = sigaction_SIGSEGV; 256 256 (void)sigaction(SIGSEGV, &act, NULL); 257 257 258 + g_vsyscall = 0; 258 259 /* gettimeofday(NULL, NULL); */ 259 260 asm volatile ( 260 261 "call %P0" ··· 263 262 : "i" (0xffffffffff600000), "D" (NULL), "S" (NULL) 264 263 : "rax", "rcx", "r11" 265 264 ); 266 - exit(0); 265 + 266 + g_vsyscall = 1; 267 + *(volatile int *)0xffffffffff600000UL; 268 + 269 + g_vsyscall = 2; 270 + exit(g_vsyscall); 267 271 } 268 272 waitpid(pid, &wstatus, 0); 269 - if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) { 270 - /* vsyscall page exists and is executable. */ 273 + if (WIFEXITED(wstatus)) { 274 + g_vsyscall = WEXITSTATUS(wstatus); 271 275 } else { 272 - /* vsyscall page doesn't exist. */ 273 - g_vsyscall = 0; 274 - return; 275 - } 276 - 277 - pid = fork(); 278 - if (pid < 0) { 279 - fprintf(stderr, "fork, errno %d\n", errno); 276 + fprintf(stderr, "error: wstatus %08x\n", wstatus); 280 277 exit(1); 281 278 } 282 - if (pid == 0) { 283 - struct rlimit rlim = {0, 0}; 284 - (void)setrlimit(RLIMIT_CORE, &rlim); 285 - 286 - /* Hide "segfault at ffffffffff600000" messages. */ 287 - struct sigaction act; 288 - memset(&act, 0, sizeof(struct sigaction)); 289 - act.sa_flags = SA_SIGINFO; 290 - act.sa_sigaction = sigaction_SIGSEGV; 291 - (void)sigaction(SIGSEGV, &act, NULL); 292 - 293 - *(volatile int *)0xffffffffff600000UL; 294 - exit(0); 295 - } 296 - waitpid(pid, &wstatus, 0); 297 - if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) { 298 - /* vsyscall page is readable and executable. */ 299 - g_vsyscall = 1; 300 - return; 301 - } 302 - 303 - /* vsyscall page is executable but unreadable. */ 304 - g_vsyscall = 2; 305 279 } 306 280 307 281 int main(void)