|
@@ -3813,7 +3813,9 @@ EXPORT_SYMBOL(__kmalloc_node);
|
|
|
|
|
|
#ifdef CONFIG_HARDENED_USERCOPY
|
|
|
/*
|
|
|
- * Rejects objects that are incorrectly sized.
|
|
|
+ * Rejects incorrectly sized objects and objects that are to be copied
|
|
|
+ * to/from userspace but do not fall entirely within the containing slab
|
|
|
+ * cache's usercopy region.
|
|
|
*
|
|
|
* Returns NULL if check passes, otherwise const char * to name of cache
|
|
|
* to indicate an error.
|
|
@@ -3827,7 +3829,6 @@ void __check_heap_object(const void *ptr, unsigned long n, struct page *page,
|
|
|
|
|
|
/* Find object and usable object size. */
|
|
|
s = page->slab_cache;
|
|
|
- object_size = slab_ksize(s);
|
|
|
|
|
|
/* Reject impossible pointers. */
|
|
|
if (ptr < page_address(page))
|
|
@@ -3845,10 +3846,24 @@ void __check_heap_object(const void *ptr, unsigned long n, struct page *page,
|
|
|
offset -= s->red_left_pad;
|
|
|
}
|
|
|
|
|
|
- /* Allow address range falling entirely within object size. */
|
|
|
- if (offset <= object_size && n <= object_size - offset)
|
|
|
+ /* Allow address range falling entirely within usercopy region. */
|
|
|
+ if (offset >= s->useroffset &&
|
|
|
+ offset - s->useroffset <= s->usersize &&
|
|
|
+ n <= s->useroffset - offset + s->usersize)
|
|
|
return;
|
|
|
|
|
|
+ /*
|
|
|
+ * If the copy is still within the allocated object, produce
|
|
|
+ * a warning instead of rejecting the copy. This is intended
|
|
|
+ * to be a temporary method to find any missing usercopy
|
|
|
+ * whitelists.
|
|
|
+ */
|
|
|
+ object_size = slab_ksize(s);
|
|
|
+ if (offset <= object_size && n <= object_size - offset) {
|
|
|
+ usercopy_warn("SLUB object", s->name, to_user, offset, n);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
usercopy_abort("SLUB object", s->name, to_user, offset, n);
|
|
|
}
|
|
|
#endif /* CONFIG_HARDENED_USERCOPY */
|