selftests/vm/pkeys: test correct behaviour of pkey-0
authorRam Pai <linuxram@us.ibm.com>
Thu, 4 Jun 2020 23:52:43 +0000 (16:52 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 5 Jun 2020 02:06:27 +0000 (19:06 -0700)
Ensure that pkey-0 is allocated on start and that it can be attached
dynamically in various modes, without failures.

Signed-off-by: Ram Pai <linuxram@us.ibm.com>
Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Dave Hansen <dave.hansen@intel.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Florian Weimer <fweimer@redhat.com>
Cc: "Desnes A. Nunes do Rosario" <desnesn@linux.vnet.ibm.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Thiago Jung Bauermann <bauerman@linux.ibm.com>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Michal Suchanek <msuchanek@suse.de>
Cc: Shuah Khan <shuah@kernel.org>
Link: http://lkml.kernel.org/r/9b7c54a9b4261894fe0c7e884c70b87214ff8fbb.1585646528.git.sandipan@linux.ibm.com
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
tools/testing/selftests/vm/protection_keys.c

index d4952b57cc9099faaaaa85d6a15006588cab9693..a1cb9a71e77ce57352b26d8985823cff273a0612 100644 (file)
@@ -964,6 +964,58 @@ __attribute__((noinline)) int read_ptr(int *ptr)
        return *ptr;
 }
 
+void test_pkey_alloc_free_attach_pkey0(int *ptr, u16 pkey)
+{
+       int i, err;
+       int max_nr_pkey_allocs;
+       int alloced_pkeys[NR_PKEYS];
+       int nr_alloced = 0;
+       long size;
+
+       pkey_assert(pkey_last_malloc_record);
+       size = pkey_last_malloc_record->size;
+       /*
+        * This is a bit of a hack.  But mprotect() requires
+        * huge-page-aligned sizes when operating on hugetlbfs.
+        * So, make sure that we use something that's a multiple
+        * of a huge page when we can.
+        */
+       if (size >= HPAGE_SIZE)
+               size = HPAGE_SIZE;
+
+       /* allocate every possible key and make sure key-0 never got allocated */
+       max_nr_pkey_allocs = NR_PKEYS;
+       for (i = 0; i < max_nr_pkey_allocs; i++) {
+               int new_pkey = alloc_pkey();
+               pkey_assert(new_pkey != 0);
+
+               if (new_pkey < 0)
+                       break;
+               alloced_pkeys[nr_alloced++] = new_pkey;
+       }
+       /* free all the allocated keys */
+       for (i = 0; i < nr_alloced; i++) {
+               int free_ret;
+
+               if (!alloced_pkeys[i])
+                       continue;
+               free_ret = sys_pkey_free(alloced_pkeys[i]);
+               pkey_assert(!free_ret);
+       }
+
+       /* attach key-0 in various modes */
+       err = sys_mprotect_pkey(ptr, size, PROT_READ, 0);
+       pkey_assert(!err);
+       err = sys_mprotect_pkey(ptr, size, PROT_WRITE, 0);
+       pkey_assert(!err);
+       err = sys_mprotect_pkey(ptr, size, PROT_EXEC, 0);
+       pkey_assert(!err);
+       err = sys_mprotect_pkey(ptr, size, PROT_READ|PROT_WRITE, 0);
+       pkey_assert(!err);
+       err = sys_mprotect_pkey(ptr, size, PROT_READ|PROT_WRITE|PROT_EXEC, 0);
+       pkey_assert(!err);
+}
+
 void test_read_of_write_disabled_region(int *ptr, u16 pkey)
 {
        int ptr_contents;
@@ -1448,6 +1500,7 @@ void (*pkey_tests[])(int *ptr, u16 pkey) = {
        test_pkey_syscalls_on_non_allocated_pkey,
        test_pkey_syscalls_bad_args,
        test_pkey_alloc_exhaust,
+       test_pkey_alloc_free_attach_pkey0,
 };
 
 void run_tests_once(void)