]> granicus.if.org Git - zfs/commitdiff
Add support for recent kmem_cache_create_usercopy
authorKevin Tanguy <kevin.tanguy@ovh.net>
Tue, 17 Jan 2017 20:05:14 +0000 (21:05 +0100)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 17 Jan 2017 20:05:14 +0000 (12:05 -0800)
SLAB_USERCOPY flag was used to indicate PAX
not to kill copies from kernel to userland.

With recent grsecurity patchset and
CONFIG_GRKERNSEC_HIDESYM that enables
CONFIG_PAX_USERCOPY zfs would panic.

Handle newer API while keeping old one functional.

Tested-by: RageLtMan <rageltman@sempervictus>
Reviewed-by: spendergrsec <spender@grsecurity.net>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Kevin Tanguy <kevin.tanguy@ovh.net>
Closes #595

config/spl-build.m4
module/spl/spl-kmem-cache.c

index 7e2e7a0a92d9421356b972b6b19577ce240abee0..8d0e8aba3ccd2b85c726a61da9f985081068d5cf 100644 (file)
@@ -50,6 +50,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
        SPL_AC_MUTEX_OWNER
        SPL_AC_INODE_LOCK
        SPL_AC_GROUP_INFO_GID
+       SPL_AC_KMEM_CACHE_CREATE_USERCOPY
 ])
 
 AC_DEFUN([SPL_AC_MODULE_SYMVERS], [
@@ -1597,3 +1598,39 @@ AC_DEFUN([SPL_AC_GROUP_INFO_GID], [
        ])
        EXTRA_KCFLAGS="$tmp_flags"
 ])
+
+dnl #
+dnl # grsecurity API change,
+dnl # kmem_cache_create() with SLAB_USERCOPY flag replaced by
+dnl # kmem_cache_create_usercopy().
+dnl #
+AC_DEFUN([SPL_AC_KMEM_CACHE_CREATE_USERCOPY], [
+       AC_MSG_CHECKING([whether kmem_cache_create_usercopy() exists])
+       tmp_flags="$EXTRA_KCFLAGS"
+       EXTRA_KCFLAGS="-Werror"
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/slab.h>
+               static void ctor(void *foo)
+               {
+                       // fake ctor
+               }
+       ],[
+               struct kmem_cache *skc_linux_cache;
+               const char *name = "test";
+               size_t size = 4096;
+               size_t align = 8;
+               unsigned long flags = 0;
+               size_t useroffset = 0;
+               size_t usersize = size - useroffset;
+
+               skc_linux_cache = kmem_cache_create_usercopy(
+                       name, size, align, flags, useroffset, usersize, ctor);
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_KMEM_CACHE_CREATE_USERCOPY, 1,
+                               [kmem_cache_create_usercopy() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+       EXTRA_KCFLAGS="$tmp_flags"
+])
index 99967b14fdb20ad3926e9c7c7a1fd0a4181b35df..45576b9761e72863495bd6c5e8259b5d85bcec36 100644 (file)
@@ -1001,8 +1001,17 @@ spl_kmem_cache_create(char *name, size_t size, size_t align,
                slabflags |= SLAB_USERCOPY;
 #endif
 
-               skc->skc_linux_cache = kmem_cache_create(
-                   skc->skc_name, size, align, slabflags, NULL);
+#if defined(HAVE_KMEM_CACHE_CREATE_USERCOPY)
+        /*
+         * Newer grsec patchset uses kmem_cache_create_usercopy()
+         * instead of SLAB_USERCOPY flag
+         */
+        skc->skc_linux_cache = kmem_cache_create_usercopy(
+            skc->skc_name, size, align, slabflags, 0, size, NULL);
+#else
+        skc->skc_linux_cache = kmem_cache_create(
+            skc->skc_name, size, align, slabflags, NULL);
+#endif
                if (skc->skc_linux_cache == NULL) {
                        rc = ENOMEM;
                        goto out;