]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - mm/slab.c
Merge tags 'cris-for-4.16' and 'cris-for-4.16-urgent' of git://git.kernel.org/pub...
[linux.git] / mm / slab.c
index 4e51ef954026bd15e5bef41167459970976faab0..324446621b3ee0d5179e23076699372781440555 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1281,7 +1281,7 @@ void __init kmem_cache_init(void)
        create_boot_cache(kmem_cache, "kmem_cache",
                offsetof(struct kmem_cache, node) +
                                  nr_node_ids * sizeof(struct kmem_cache_node *),
-                                 SLAB_HWCACHE_ALIGN);
+                                 SLAB_HWCACHE_ALIGN, 0, 0);
        list_add(&kmem_cache->list, &slab_caches);
        slab_state = PARTIAL;
 
@@ -1291,7 +1291,8 @@ void __init kmem_cache_init(void)
         */
        kmalloc_caches[INDEX_NODE] = create_kmalloc_cache(
                                kmalloc_info[INDEX_NODE].name,
-                               kmalloc_size(INDEX_NODE), ARCH_KMALLOC_FLAGS);
+                               kmalloc_size(INDEX_NODE), ARCH_KMALLOC_FLAGS,
+                               0, kmalloc_size(INDEX_NODE));
        slab_state = PARTIAL_NODE;
        setup_kmalloc_cache_index_table();
 
@@ -1316,8 +1317,6 @@ void __init kmem_cache_init_late(void)
 {
        struct kmem_cache *cachep;
 
-       slab_state = UP;
-
        /* 6) resize the head arrays to their final sizes */
        mutex_lock(&slab_mutex);
        list_for_each_entry(cachep, &slab_caches, list)
@@ -1353,8 +1352,6 @@ static int __init cpucache_init(void)
                                slab_online_cpu, slab_offline_cpu);
        WARN_ON(ret < 0);
 
-       /* Done! */
-       slab_state = FULL;
        return 0;
 }
 __initcall(cpucache_init);
@@ -3481,11 +3478,11 @@ static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac)
  * Release an obj back to its cache. If the obj has a constructed state, it must
  * be in this state _before_ it is released.  Called with disabled ints.
  */
-static inline void __cache_free(struct kmem_cache *cachep, void *objp,
-                               unsigned long caller)
+static __always_inline void __cache_free(struct kmem_cache *cachep, void *objp,
+                                        unsigned long caller)
 {
        /* Put the object into the quarantine, don't touch it for now. */
-       if (kasan_slab_free(cachep, objp))
+       if (kasan_slab_free(cachep, objp, _RET_IP_))
                return;
 
        ___cache_free(cachep, objp, caller);
@@ -4389,13 +4386,15 @@ module_init(slab_proc_init);
 
 #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.
  */
-const char *__check_heap_object(const void *ptr, unsigned long n,
-                               struct page *page)
+void __check_heap_object(const void *ptr, unsigned long n, struct page *page,
+                        bool to_user)
 {
        struct kmem_cache *cachep;
        unsigned int objnr;
@@ -4409,11 +4408,26 @@ const char *__check_heap_object(const void *ptr, unsigned long n,
        /* Find offset within object. */
        offset = ptr - index_to_obj(cachep, page, objnr) - obj_offset(cachep);
 
-       /* Allow address range falling entirely within object size. */
-       if (offset <= cachep->object_size && n <= cachep->object_size - offset)
-               return NULL;
+       /* Allow address range falling entirely within usercopy region. */
+       if (offset >= cachep->useroffset &&
+           offset - cachep->useroffset <= cachep->usersize &&
+           n <= cachep->useroffset - offset + cachep->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.
+        */
+       if (usercopy_fallback &&
+           offset <= cachep->object_size &&
+           n <= cachep->object_size - offset) {
+               usercopy_warn("SLAB object", cachep->name, to_user, offset, n);
+               return;
+       }
 
-       return cachep->name;
+       usercopy_abort("SLAB object", cachep->name, to_user, offset, n);
 }
 #endif /* CONFIG_HARDENED_USERCOPY */