diff options
author | Damian Szuberski <[email protected]> | 2022-04-27 03:52:40 +1000 |
---|---|---|
committer | GitHub <[email protected]> | 2022-04-26 10:52:40 -0700 |
commit | 849c14e04844a2f0e1f7e42886c2cef083563f35 (patch) | |
tree | 344e5abdab3b23a3f8589e868db9c93e19532405 | |
parent | a0dfd98a25b57411b5b31e69356a92b194b690a9 (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.m4 | 26 | ||||
-rw-r--r-- | config/kernel.m4 | 2 | ||||
-rw-r--r-- | module/os/linux/zfs/zfs_uio.c | 8 |
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); } } |