If get_fs() == USER_DS we better test if current->mm is not zero before
walking page tables.
The page table walk code would try to lock mm->page_table_lock, however
if mm is zero this might crash.
Now it is arguably incorrect trying to access userspace if current->mm
is zero, however we have seen that and s390 would be the only architecture
which would crash in such a case.
So we better make the page table walk code a bit more robust and report
always a fault instead.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
unsigned long offset, done, size, kaddr;
void *from, *to;
unsigned long offset, done, size, kaddr;
void *from, *to;
done = 0;
retry:
spin_lock(&mm->page_table_lock);
done = 0;
retry:
spin_lock(&mm->page_table_lock);
return 0;
if (segment_eq(get_fs(), KERNEL_DS))
return strnlen_kernel(count, src);
return 0;
if (segment_eq(get_fs(), KERNEL_DS))
return strnlen_kernel(count, src);
done = 0;
retry:
spin_lock(&mm->page_table_lock);
done = 0;
retry:
spin_lock(&mm->page_table_lock);
if (segment_eq(get_fs(), KERNEL_DS))
return copy_in_kernel(n, to, from);
if (segment_eq(get_fs(), KERNEL_DS))
return copy_in_kernel(n, to, from);
done = 0;
retry:
spin_lock(&mm->page_table_lock);
done = 0;
retry:
spin_lock(&mm->page_table_lock);
if (segment_eq(get_fs(), KERNEL_DS))
return __futex_atomic_op_pt(op, uaddr, oparg, 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(¤t->mm->page_table_lock);
uaddr = (u32 __force __user *)
__dat_user_addr((__force unsigned long) uaddr, 1);
spin_lock(¤t->mm->page_table_lock);
uaddr = (u32 __force __user *)
__dat_user_addr((__force unsigned long) uaddr, 1);
if (segment_eq(get_fs(), KERNEL_DS))
return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
if (segment_eq(get_fs(), KERNEL_DS))
return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
+ if (unlikely(!current->mm))
+ return -EFAULT;
spin_lock(¤t->mm->page_table_lock);
uaddr = (u32 __force __user *)
__dat_user_addr((__force unsigned long) uaddr, 1);
spin_lock(¤t->mm->page_table_lock);
uaddr = (u32 __force __user *)
__dat_user_addr((__force unsigned long) uaddr, 1);