summaryrefslogtreecommitdiff
path: root/arch/s390/lib/uaccess_pt.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/lib/uaccess_pt.c')
-rw-r--r--arch/s390/lib/uaccess_pt.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 97e03caf7825..61ebcc9ccb34 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -74,15 +74,18 @@ static size_t copy_in_kernel(size_t count, void __user *to,
/*
* Returns kernel address for user virtual address. If the returned address is
- * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occured and the address
- * contains the (negative) exception code.
+ * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occurred and the
+ * address contains the (negative) exception code.
*/
#ifdef CONFIG_64BIT
+
static unsigned long follow_table(struct mm_struct *mm,
unsigned long address, int write)
{
unsigned long *table = (unsigned long *)__pa(mm->pgd);
+ if (unlikely(address > mm->context.asce_limit - 1))
+ return -0x38UL;
switch (mm->context.asce_bits & _ASCE_TYPE_MASK) {
case _ASCE_TYPE_REGION1:
table = table + ((address >> 53) & 0x7ff);
@@ -150,6 +153,8 @@ static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
unsigned long offset, done, size, kaddr;
void *from, *to;
+ if (!mm)
+ return n;
done = 0;
retry:
spin_lock(&mm->page_table_lock);
@@ -206,7 +211,7 @@ fault:
return 0;
}
-size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
+static size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
{
size_t rc;
@@ -218,7 +223,7 @@ size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
return rc;
}
-size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
+static size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
{
if (segment_eq(get_fs(), KERNEL_DS))
return copy_in_kernel(n, to, (void __user *) from);
@@ -259,6 +264,8 @@ static size_t strnlen_user_pt(size_t count, const char __user *src)
return 0;
if (segment_eq(get_fs(), KERNEL_DS))
return strnlen_kernel(count, src);
+ if (!mm)
+ return 0;
done = 0;
retry:
spin_lock(&mm->page_table_lock);
@@ -320,6 +327,8 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
if (segment_eq(get_fs(), KERNEL_DS))
return copy_in_kernel(n, to, from);
+ if (!mm)
+ return n;
done = 0;
retry:
spin_lock(&mm->page_table_lock);
@@ -408,6 +417,8 @@ int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
if (segment_eq(get_fs(), KERNEL_DS))
return __futex_atomic_op_pt(op, uaddr, oparg, old);
+ if (unlikely(!current->mm))
+ return -EFAULT;
spin_lock(&current->mm->page_table_lock);
uaddr = (u32 __force __user *)
__dat_user_addr((__force unsigned long) uaddr, 1);
@@ -445,6 +456,8 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
if (segment_eq(get_fs(), KERNEL_DS))
return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
+ if (unlikely(!current->mm))
+ return -EFAULT;
spin_lock(&current->mm->page_table_lock);
uaddr = (u32 __force __user *)
__dat_user_addr((__force unsigned long) uaddr, 1);