summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamian Szuberski <[email protected]>2022-04-27 03:52:40 +1000
committerGitHub <[email protected]>2022-04-26 10:52:40 -0700
commit849c14e04844a2f0e1f7e42886c2cef083563f35 (patch)
tree344e5abdab3b23a3f8589e868db9c93e19532405
parenta0dfd98a25b57411b5b31e69356a92b194b690a9 (diff)
PPC get_user workaround
Linux 5.12 PPC 5.12 get_user() and __copy_from_user_inatomic() inline helpers very indirectly include a reference to the GPL'd array mmu_feature_keys[] and fails to build. Workaround this by using copy_from_user() and throwing EFAULT for any calls to __copy_from_user_inatomic(). This is a workaround until a fix for Linux commit 7613f5a66becfd0e43a0f34de8518695888f5458 "powerpc/64s/kuap: Use mmu_has_feature()" is fully addressed. Reviewed-by: Brian Behlendorf <[email protected]> Authored-by: Colin Ian King <[email protected]> Signed-off-by: szubersk <[email protected]> Closes #11958 Closes #12590 Closes #13367
-rw-r--r--config/kernel-copy-from-user-inatomic.m426
-rw-r--r--config/kernel.m42
-rw-r--r--module/os/linux/zfs/zfs_uio.c8
3 files changed, 34 insertions, 2 deletions
diff --git a/config/kernel-copy-from-user-inatomic.m4 b/config/kernel-copy-from-user-inatomic.m4
new file mode 100644
index 000000000..5fddaca59
--- /dev/null
+++ b/config/kernel-copy-from-user-inatomic.m4
@@ -0,0 +1,26 @@
+dnl #
+dnl # On certain architectures `__copy_from_user_inatomic`
+dnl # is a GPL exported variable and cannot be used by OpenZFS.
+dnl #
+
+dnl #
+dnl # Checking if `__copy_from_user_inatomic` is available.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC], [
+ ZFS_LINUX_TEST_SRC([__copy_from_user_inatomic], [
+ #include <linux/uaccess.h>
+ ], [
+ int result __attribute__ ((unused)) = __copy_from_user_inatomic(NULL, NULL, 0);
+ ], [], [ZFS_META_LICENSE])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC], [
+ AC_MSG_CHECKING([whether __copy_from_user_inatomic is available])
+ ZFS_LINUX_TEST_RESULT([__copy_from_user_inatomic_license], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE___COPY_FROM_USER_INATOMIC, 1,
+ [__copy_from_user_inatomic is available])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+])
diff --git a/config/kernel.m4 b/config/kernel.m4
index 2a552431a..432089407 100644
--- a/config/kernel.m4
+++ b/config/kernel.m4
@@ -142,6 +142,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_ADD_DISK
ZFS_AC_KERNEL_SRC_KTHREAD
ZFS_AC_KERNEL_SRC_ZERO_PAGE
+ ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC
AC_MSG_CHECKING([for available kernel interfaces])
ZFS_LINUX_TEST_COMPILE_ALL([kabi])
@@ -257,6 +258,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_ADD_DISK
ZFS_AC_KERNEL_KTHREAD
ZFS_AC_KERNEL_ZERO_PAGE
+ ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC
])
dnl #
diff --git a/module/os/linux/zfs/zfs_uio.c b/module/os/linux/zfs/zfs_uio.c
index ce47b3e60..0d4b4c583 100644
--- a/module/os/linux/zfs/zfs_uio.c
+++ b/module/os/linux/zfs/zfs_uio.c
@@ -75,6 +75,7 @@ zfs_uiomove_iov(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio)
} else {
unsigned long b_left = 0;
if (uio->uio_fault_disable) {
+#if defined(HAVE___COPY_FROM_USER_INATOMIC)
if (!zfs_access_ok(VERIFY_READ,
(iov->iov_base + skip), cnt)) {
return (EFAULT);
@@ -84,6 +85,9 @@ zfs_uiomove_iov(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio)
__copy_from_user_inatomic(p,
(iov->iov_base + skip), cnt);
pagefault_enable();
+#else
+ return (EFAULT);
+#endif
} else {
b_left =
copy_from_user(p,
@@ -248,7 +252,7 @@ zfs_uio_prefaultpages(ssize_t n, zfs_uio_t *uio)
/* touch each page in this segment. */
p = iov->iov_base + skip;
while (cnt) {
- if (get_user(tmp, (uint8_t *)p))
+ if (copy_from_user(&tmp, p, 1))
return (EFAULT);
ulong_t incr = MIN(cnt, PAGESIZE);
p += incr;
@@ -256,7 +260,7 @@ zfs_uio_prefaultpages(ssize_t n, zfs_uio_t *uio)
}
/* touch the last byte in case it straddles a page. */
p--;
- if (get_user(tmp, (uint8_t *)p))
+ if (copy_from_user(&tmp, p, 1))
return (EFAULT);
}
}