diff --git a/mm/maccess.c b/mm/maccess.c index ded4bfaba7f3..f7bca30ac8fa 100644 --- a/mm/maccess.c +++ b/mm/maccess.c @@ -5,6 +5,7 @@ #include #include #include +#include bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size) @@ -221,14 +222,18 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count) long copy_from_user_nofault(void *dst, const void __user *src, size_t size) { long ret = -EFAULT; - mm_segment_t old_fs = force_uaccess_begin(); - if (access_ok(src, size)) { - pagefault_disable(); - ret = __copy_from_user_inatomic(dst, src, size); - pagefault_enable(); - } - force_uaccess_end(old_fs); + if (!__access_ok(src, size)) + return ret; + + if (!nmi_uaccess_okay()) + return ret; + + mm_segment_t old_fs = force_uaccess_begin(); + pagefault_disable(); + ret = __copy_from_user_inatomic(dst, src, size); + pagefault_enable(); + force_uaccess_end(old_fs); if (ret) return -EFAULT; diff --git a/mm/usercopy.c b/mm/usercopy.c index 540968b481e7..181e4e0ebc1e 100644 --- a/mm/usercopy.c +++ b/mm/usercopy.c @@ -224,6 +224,31 @@ static inline void check_heap_object(const void *ptr, unsigned long n, bool to_user) { struct page *page; +/* + unsigned long addr = (unsigned long)ptr; + unsigned long offset; + struct folio *folio; + + if (is_kmap_addr(ptr)) { + offset = offset_in_page(ptr); + if (n > PAGE_SIZE - offset) + usercopy_abort("kmap", NULL, to_user, offset, n); + return; + } + + if (is_vmalloc_addr(ptr) && !pagefault_disabled()) { + struct vmap_area *area = find_vmap_area(addr); + + if (!area) + usercopy_abort("vmalloc", "no area", to_user, 0, n); + + if (n > area->va_end - addr) { + offset = addr - area->va_start; + usercopy_abort("vmalloc", NULL, to_user, offset, n); + } + return; + } + */ if (!virt_addr_valid(ptr)) return;