ping? On Sat, 6 Aug 2022 22:57:49 +0900, Shigeru Yoshida wrote: > There are 3 vsyscall modes: emulate, xonly, and none. proc-pid-vm > detects the existence of the vsyscall with memory load on the vsyscall > page. > > This works for emulate and none vsyscall modes, but fails for xonly > because read permission is omitted with xonly vsyscall page, and it > results in the following error: > > # ./proc-pid-vm > proc-pid-vm: proc-pid-vm.c:328: main: Assertion `rv == len' failed. > Aborted (core dumped) > > This patch fixes this issue with introducing the following rule: > > 1. vsyscall mode is emulate if it can load memory > 2. vsyscall mode is xonly if it can call gettimeofday() on vsyscall > 3. vsyscall mode is node otherwise > > Signed-off-by: Shigeru Yoshida <syoshida@xxxxxxxxxx> > --- > tools/testing/selftests/proc/proc-pid-vm.c | 77 ++++++++++++++++++---- > 1 file changed, 65 insertions(+), 12 deletions(-) > > diff --git a/tools/testing/selftests/proc/proc-pid-vm.c b/tools/testing/selftests/proc/proc-pid-vm.c > index 28604c9f805c..dffd263beef3 100644 > --- a/tools/testing/selftests/proc/proc-pid-vm.c > +++ b/tools/testing/selftests/proc/proc-pid-vm.c > @@ -211,10 +211,16 @@ static int make_exe(const uint8_t *payload, size_t len) > } > #endif > > -static bool g_vsyscall = false; > - > -static const char str_vsyscall[] = > -"ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n"; > +static enum { EMULATE, XONLY, NONE } g_vsyscall_mode; > + > +static const char * const str_vsyscall[] = { > + /* emulate */ > + "ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n", > + /* xonly */ > + "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]\n", > + /* none */ > + "", > +}; > > #ifdef __x86_64__ > static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___) > @@ -225,7 +231,33 @@ static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___) > /* > * vsyscall page can't be unmapped, probe it with memory load. > */ > -static void vsyscall(void) > +static bool vsyscall_emulate(void) > +{ > + *(volatile int *)0xffffffffff600000UL; > + return true; > +} > + > +/* > + * vsyscall page can't be unmapped, probe it with calling gettimeofday(). > + */ > +static bool vsyscall_xonly(void) > +{ > + int ret; > + struct timeval tv; > + int (*f)(struct timeval *tv, struct timezone *tz); > + > + /* Try to call gettimeofday() on vsyscall*/ > + f = (void *)0xffffffffff600000UL; > + ret = f(&tv, NULL); > + if (ret < 0) { > + fprintf(stderr, "gettimeofday() on vsyscall, ret %d\n", ret); > + return false; > + } > + > + return true; > +} > + > +static bool vsyscall_test(bool (*test)(void)) > { > pid_t pid; > int wstatus; > @@ -246,13 +278,27 @@ static void vsyscall(void) > act.sa_sigaction = sigaction_SIGSEGV; > (void)sigaction(SIGSEGV, &act, NULL); > > - *(volatile int *)0xffffffffff600000UL; > + if (!test()) > + exit(1); > + > exit(0); > } > waitpid(pid, &wstatus, 0); > if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) { > - g_vsyscall = true; > + return true; > } > + > + return false; > +} > + > +static void vsyscall(void) > +{ > + if (vsyscall_test(vsyscall_emulate)) > + g_vsyscall_mode = EMULATE; > + else if (vsyscall_test(vsyscall_xonly)) > + g_vsyscall_mode = XONLY; > + else > + g_vsyscall_mode = NONE; > } > > int main(void) > @@ -314,11 +360,14 @@ int main(void) > > /* Test /proc/$PID/maps */ > { > - const size_t len = strlen(buf0) + (g_vsyscall ? strlen(str_vsyscall) : 0); > + size_t len = strlen(buf0); > char buf[256]; > ssize_t rv; > int fd; > > + if (g_vsyscall_mode != NONE) > + len += strlen(str_vsyscall[g_vsyscall_mode]); > + > snprintf(buf, sizeof(buf), "/proc/%u/maps", pid); > fd = open(buf, O_RDONLY); > if (fd == -1) { > @@ -327,8 +376,10 @@ int main(void) > rv = read(fd, buf, sizeof(buf)); > assert(rv == len); > assert(memcmp(buf, buf0, strlen(buf0)) == 0); > - if (g_vsyscall) { > - assert(memcmp(buf + strlen(buf0), str_vsyscall, strlen(str_vsyscall)) == 0); > + if (g_vsyscall_mode != NONE) { > + assert(memcmp(buf + strlen(buf0), > + str_vsyscall[g_vsyscall_mode], > + strlen(str_vsyscall[g_vsyscall_mode])) == 0); > } > } > > @@ -374,8 +425,10 @@ int main(void) > assert(memmem(buf, rv, S[i], strlen(S[i]))); > } > > - if (g_vsyscall) { > - assert(memmem(buf, rv, str_vsyscall, strlen(str_vsyscall))); > + if (g_vsyscall_mode != NONE) { > + assert(memmem(buf, rv, > + str_vsyscall[g_vsyscall_mode], > + strlen(str_vsyscall[g_vsyscall_mode]))); > } > } > > -- > 2.37.1 >