lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 21 Jun 2021 22:57:30 +0100
From:   Dmitry Safonov <dima@...sta.com>
To:     Christophe Leroy <christophe.leroy@...roup.eu>,
        LKML <linux-kernel@...r.kernel.org>
Cc:     Dmitry Safonov <0x7f454c46@...il.com>,
        Alexander Viro <viro@...iv.linux.org.uk>,
        Andrew Morton <akpm@...ux-foundation.org>,
        Andy Lutomirski <luto@...nel.org>,
        Arnd Bergmann <arnd@...db.de>, Borislav Petkov <bp@...en8.de>,
        Catalin Marinas <catalin.marinas@....com>,
        Guo Ren <guoren@...nel.org>, "H. Peter Anvin" <hpa@...or.com>,
        Ingo Molnar <mingo@...hat.com>,
        Oleg Nesterov <oleg@...hat.com>,
        Russell King <linux@...linux.org.uk>,
        Thomas Bogendoerfer <tsbogend@...ha.franken.de>,
        Thomas Gleixner <tglx@...utronix.de>,
        Vincenzo Frascino <vincenzo.frascino@....com>,
        Will Deacon <will@...nel.org>, X86 ML <x86@...nel.org>
Subject: Re: [PATCH v3 00/23] Add generic vdso_base tracking

On 6/17/21 10:13 AM, Christophe Leroy wrote:
>
>
> Le 11/06/2021 à 20:02, Dmitry Safonov a écrit :
>> v3 Changes:
>> - Migrated arch/powerpc to vdso_base
>> - Added x86/selftest for unmapped vdso & no landing on fast syscall
>> - Review comments from Andy & Christophe (thanks!)
>> - Amended s/born process/execed process/ everywhere I noticed
>> - Build robot warning on cast from __user pointer
>>
>> I've tested it on x86, I would appreciate any help with
>> Tested-by on arm/arm64/mips/powerpc/s390/... platforms.
>
> I tried it on powerpc, normal use still works.

Thank you!

> What tests can be done exactly ?

Well, for x86 I've run all vdso tests from tools/testing/selftests/x86/
(with the new one from patch 23 here, which tests exactly forced
segfault on unmapped vdso).
I think normal use on other platforms sounds good to me.

>
> We have a selftest in powerpc
> (https://github.com/linuxppc/linux/blob/master/tools/testing/selftests/powerpc/signal/sigreturn_vdso.c)
> but it doesn't work anymore since the split of VDSO into VDSO+VVAR.

Well, it doesn't sound very hard to fix, see the sample diff inline.

Thank you,
Dmitry

--->8---
diff --git a/tools/testing/selftests/powerpc/signal/sigreturn_vdso.c
b/tools/testing/selftests/powerpc/signal/sigreturn_vdso.c
index e282fff0fe25..a4f85ee13c4a 100644
--- a/tools/testing/selftests/powerpc/signal/sigreturn_vdso.c
+++ b/tools/testing/selftests/powerpc/signal/sigreturn_vdso.c
@@ -13,6 +13,7 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdbool.h>
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -23,7 +24,7 @@

 #include "utils.h"

-static int search_proc_maps(char *needle, unsigned long *low,
unsigned long *high)
+static int search_proc_maps(char *needle, unsigned long *low,
unsigned long *high, unsigned long *size)
 {
     unsigned long start, end;
     static char buf[4096];
@@ -52,6 +53,7 @@ static int search_proc_maps(char *needle, unsigned
long *low, unsigned long *hig
         if (strstr(name, needle)) {
             *low = start;
             *high = end - 1;
+            *size = end - start;
             rc = 0;
             break;
         }
@@ -71,9 +73,12 @@ static void sigusr1_handler(int sig)

 int test_sigreturn_vdso(void)
 {
-    unsigned long low, high, size;
+    unsigned long stack_start, stack_end, stack_size;
+    unsigned long vdso_start, vdso_end, vdso_size;
+    unsigned long vvar_start, vvar_end, vvar_size;
+    char *vdso_parking, *vvar_parking;
     struct sigaction act;
-    char *p;
+    bool vvar_present;

     act.sa_handler = sigusr1_handler;
     act.sa_flags = 0;
@@ -82,36 +87,56 @@ int test_sigreturn_vdso(void)
     assert(sigaction(SIGUSR1, &act, NULL) == 0);

     // Confirm the VDSO is mapped, and work out where it is
-    assert(search_proc_maps("[vdso]", &low, &high) == 0);
-    size = high - low + 1;
-    printf("VDSO is at 0x%lx-0x%lx (%lu bytes)\n", low, high, size);
+    assert(search_proc_maps("[vdso]", &vdso_start, &vdso_end,
&vdso_size) == 0);
+    printf("VDSO is at 0x%lx-0x%lx (%lu bytes)\n", vdso_start,
vdso_end, vdso_size);
+    // On older kernels there's only vdso, on newer vdso/vvar pair
+    if (search_proc_maps("[vvar]", &vvar_start, &vvar_end, &vvar_size) == 0) {
+        vvar_present = true;
+        printf("VVAR is at 0x%lx-0x%lx (%lu bytes)\n",
+                vvar_start, vvar_end, vvar_size);
+    } else {
+        vvar_present = false;
+        vvar_size = 0;
+    }

     kill(getpid(), SIGUSR1);
     assert(took_signal == 1);
     printf("Signal delivered OK with VDSO mapped\n");

-    // Remap the VDSO somewhere else
-    p = mmap(NULL, size, PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
-    assert(p != MAP_FAILED);
-    assert(mremap((void *)low, size, size,
MREMAP_MAYMOVE|MREMAP_FIXED, p) != MAP_FAILED);
-    assert(search_proc_maps("[vdso]", &low, &high) == 0);
-    size = high - low + 1;
-    printf("VDSO moved to 0x%lx-0x%lx (%lu bytes)\n", low, high, size);
+    // Remap the VDSO and VVAR somewhere else
+    vdso_parking = mmap(NULL, vdso_size + vvar_size,
PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+    assert(vdso_parking != MAP_FAILED);
+
+    if (vvar_present) {
+        // The relative position of vdso/vvar must always stay the same
+        if (vvar_start > vdso_start) {
+            vvar_parking = vdso_parking + vdso_size;
+        } else {
+            vvar_parking = vdso_parking;
+            vdso_parking = vvar_parking + vvar_size;
+        }
+        assert(mremap((void *)vvar_start, vvar_size, vvar_size,
MREMAP_MAYMOVE|MREMAP_FIXED, vvar_parking) != MAP_FAILED);
+    }
+    assert(mremap((void *)vdso_start, vdso_size, vdso_size,
MREMAP_MAYMOVE|MREMAP_FIXED, vdso_parking) != MAP_FAILED);
+
+    assert(search_proc_maps("[vdso]", &vdso_start, &vdso_end,
&vdso_size) == 0);
+    printf("VDSO moved to 0x%lx-0x%lx (%lu bytes)\n", vdso_start,
vdso_end, vdso_size);
+    assert(search_proc_maps("[vvar]", &vvar_start, &vvar_end,
&vvar_size) == 0);
+    printf("VVAR moved to 0x%lx-0x%lx (%lu bytes)\n", vvar_start,
vvar_end, vvar_size);

     kill(getpid(), SIGUSR1);
     assert(took_signal == 2);
     printf("Signal delivered OK with VDSO moved\n");

-    assert(munmap((void *)low, size) == 0);
+    assert(munmap((void *)vdso_start, vdso_size) == 0);
     printf("Unmapped VDSO\n");

     // Confirm the VDSO is not mapped anymore
-    assert(search_proc_maps("[vdso]", &low, &high) != 0);
+    assert(search_proc_maps("[vdso]", &vdso_start, &vdso_end,
&vdso_size) != 0);

     // Make the stack executable
-    assert(search_proc_maps("[stack]", &low, &high) == 0);
-    size = high - low + 1;
-    mprotect((void *)low, size, PROT_READ|PROT_WRITE|PROT_EXEC);
+    assert(search_proc_maps("[stack]", &stack_start, &stack_end,
&stack_size) == 0);
+    mprotect((void *)stack_start, stack_size, PROT_READ|PROT_WRITE|PROT_EXEC);
     printf("Remapped the stack executable\n");

     kill(getpid(), SIGUSR1);

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ