aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Tanguy <[email protected]>2017-01-17 21:05:14 +0100
committerBrian Behlendorf <[email protected]>2017-01-17 12:05:14 -0800
commit0194e4a03c394f0bb85cba78ac12f10c480c5670 (patch)
tree4b509fbbf9de775820f4b338ae4ebafbaed38888
parent120faefed90aa4c276a3db45525dc5c804cb1a00 (diff)
Add support for recent kmem_cache_create_usercopy
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 <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Kevin Tanguy <[email protected]> Closes #595
-rw-r--r--config/spl-build.m437
-rw-r--r--module/spl/spl-kmem-cache.c13
2 files changed, 48 insertions, 2 deletions
diff --git a/config/spl-build.m4 b/config/spl-build.m4
index 7e2e7a0a9..8d0e8aba3 100644
--- a/config/spl-build.m4
+++ b/config/spl-build.m4
@@ -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"
+])
diff --git a/module/spl/spl-kmem-cache.c b/module/spl/spl-kmem-cache.c
index 99967b14f..45576b976 100644
--- a/module/spl/spl-kmem-cache.c
+++ b/module/spl/spl-kmem-cache.c
@@ -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;