Skip to content

Commit

Permalink
PPC get_user workaround
Browse files Browse the repository at this point in the history
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 openzfs#11958
Closes openzfs#12590
Closes openzfs#13367
  • Loading branch information
szubersk authored and beren12 committed Sep 19, 2022
1 parent 1f1b699 commit 810e1b1
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
26 changes: 26 additions & 0 deletions config/kernel-copy-from-user-inatomic.m4
Original file line number Diff line number Diff line change
@@ -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)
])
])
2 changes: 2 additions & 0 deletions config/kernel.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down Expand Up @@ -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 #
Expand Down
8 changes: 6 additions & 2 deletions module/os/linux/zfs/zfs_uio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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,
Expand Down Expand Up @@ -248,15 +252,15 @@ 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;
cnt -= incr;
}
/* 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);
}
}
Expand Down

0 comments on commit 810e1b1

Please sign in to comment.