diff options
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/sched/task.h | 14 | ||||
| -rw-r--r-- | include/linux/slab.h | 41 | ||||
| -rw-r--r-- | include/linux/slab_def.h | 3 | ||||
| -rw-r--r-- | include/linux/slub_def.h | 3 | ||||
| -rw-r--r-- | include/linux/stddef.h | 10 | ||||
| -rw-r--r-- | include/linux/uaccess.h | 8 |
6 files changed, 64 insertions, 15 deletions
diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h index 05b8650f06f5..5be31eb7b266 100644 --- a/include/linux/sched/task.h +++ b/include/linux/sched/task.h | |||
| @@ -104,6 +104,20 @@ extern int arch_task_struct_size __read_mostly; | |||
| 104 | # define arch_task_struct_size (sizeof(struct task_struct)) | 104 | # define arch_task_struct_size (sizeof(struct task_struct)) |
| 105 | #endif | 105 | #endif |
| 106 | 106 | ||
| 107 | #ifndef CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST | ||
| 108 | /* | ||
| 109 | * If an architecture has not declared a thread_struct whitelist we | ||
| 110 | * must assume something there may need to be copied to userspace. | ||
| 111 | */ | ||
| 112 | static inline void arch_thread_struct_whitelist(unsigned long *offset, | ||
| 113 | unsigned long *size) | ||
| 114 | { | ||
| 115 | *offset = 0; | ||
| 116 | /* Handle dynamically sized thread_struct. */ | ||
| 117 | *size = arch_task_struct_size - offsetof(struct task_struct, thread); | ||
| 118 | } | ||
| 119 | #endif | ||
| 120 | |||
| 107 | #ifdef CONFIG_VMAP_STACK | 121 | #ifdef CONFIG_VMAP_STACK |
| 108 | static inline struct vm_struct *task_stack_vm_area(const struct task_struct *t) | 122 | static inline struct vm_struct *task_stack_vm_area(const struct task_struct *t) |
| 109 | { | 123 | { |
diff --git a/include/linux/slab.h b/include/linux/slab.h index 50697a1d6621..231abc8976c5 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h | |||
| @@ -135,9 +135,15 @@ struct mem_cgroup; | |||
| 135 | void __init kmem_cache_init(void); | 135 | void __init kmem_cache_init(void); |
| 136 | bool slab_is_available(void); | 136 | bool slab_is_available(void); |
| 137 | 137 | ||
| 138 | struct kmem_cache *kmem_cache_create(const char *, size_t, size_t, | 138 | extern bool usercopy_fallback; |
| 139 | slab_flags_t, | 139 | |
| 140 | void (*)(void *)); | 140 | struct kmem_cache *kmem_cache_create(const char *name, size_t size, |
| 141 | size_t align, slab_flags_t flags, | ||
| 142 | void (*ctor)(void *)); | ||
| 143 | struct kmem_cache *kmem_cache_create_usercopy(const char *name, | ||
| 144 | size_t size, size_t align, slab_flags_t flags, | ||
| 145 | size_t useroffset, size_t usersize, | ||
| 146 | void (*ctor)(void *)); | ||
| 141 | void kmem_cache_destroy(struct kmem_cache *); | 147 | void kmem_cache_destroy(struct kmem_cache *); |
| 142 | int kmem_cache_shrink(struct kmem_cache *); | 148 | int kmem_cache_shrink(struct kmem_cache *); |
| 143 | 149 | ||
| @@ -153,9 +159,20 @@ void memcg_destroy_kmem_caches(struct mem_cgroup *); | |||
| 153 | * f.e. add ____cacheline_aligned_in_smp to the struct declaration | 159 | * f.e. add ____cacheline_aligned_in_smp to the struct declaration |
| 154 | * then the objects will be properly aligned in SMP configurations. | 160 | * then the objects will be properly aligned in SMP configurations. |
| 155 | */ | 161 | */ |
| 156 | #define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\ | 162 | #define KMEM_CACHE(__struct, __flags) \ |
| 157 | sizeof(struct __struct), __alignof__(struct __struct),\ | 163 | kmem_cache_create(#__struct, sizeof(struct __struct), \ |
| 158 | (__flags), NULL) | 164 | __alignof__(struct __struct), (__flags), NULL) |
| 165 | |||
| 166 | /* | ||
| 167 | * To whitelist a single field for copying to/from usercopy, use this | ||
| 168 | * macro instead for KMEM_CACHE() above. | ||
| 169 | */ | ||
| 170 | #define KMEM_CACHE_USERCOPY(__struct, __flags, __field) \ | ||
| 171 | kmem_cache_create_usercopy(#__struct, \ | ||
| 172 | sizeof(struct __struct), \ | ||
| 173 | __alignof__(struct __struct), (__flags), \ | ||
| 174 | offsetof(struct __struct, __field), \ | ||
| 175 | sizeof_field(struct __struct, __field), NULL) | ||
| 159 | 176 | ||
| 160 | /* | 177 | /* |
| 161 | * Common kmalloc functions provided by all allocators | 178 | * Common kmalloc functions provided by all allocators |
| @@ -167,15 +184,11 @@ void kzfree(const void *); | |||
| 167 | size_t ksize(const void *); | 184 | size_t ksize(const void *); |
| 168 | 185 | ||
| 169 | #ifdef CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR | 186 | #ifdef CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR |
| 170 | const char *__check_heap_object(const void *ptr, unsigned long n, | 187 | void __check_heap_object(const void *ptr, unsigned long n, struct page *page, |
| 171 | struct page *page); | 188 | bool to_user); |
| 172 | #else | 189 | #else |
| 173 | static inline const char *__check_heap_object(const void *ptr, | 190 | static inline void __check_heap_object(const void *ptr, unsigned long n, |
| 174 | unsigned long n, | 191 | struct page *page, bool to_user) { } |
| 175 | struct page *page) | ||
| 176 | { | ||
| 177 | return NULL; | ||
| 178 | } | ||
| 179 | #endif | 192 | #endif |
| 180 | 193 | ||
| 181 | /* | 194 | /* |
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index 072e46e9e1d5..7385547c04b1 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h | |||
| @@ -85,6 +85,9 @@ struct kmem_cache { | |||
| 85 | unsigned int *random_seq; | 85 | unsigned int *random_seq; |
| 86 | #endif | 86 | #endif |
| 87 | 87 | ||
| 88 | size_t useroffset; /* Usercopy region offset */ | ||
| 89 | size_t usersize; /* Usercopy region size */ | ||
| 90 | |||
| 88 | struct kmem_cache_node *node[MAX_NUMNODES]; | 91 | struct kmem_cache_node *node[MAX_NUMNODES]; |
| 89 | }; | 92 | }; |
| 90 | 93 | ||
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index 0adae162dc8f..8ad99c47b19c 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h | |||
| @@ -135,6 +135,9 @@ struct kmem_cache { | |||
| 135 | struct kasan_cache kasan_info; | 135 | struct kasan_cache kasan_info; |
| 136 | #endif | 136 | #endif |
| 137 | 137 | ||
| 138 | size_t useroffset; /* Usercopy region offset */ | ||
| 139 | size_t usersize; /* Usercopy region size */ | ||
| 140 | |||
| 138 | struct kmem_cache_node *node[MAX_NUMNODES]; | 141 | struct kmem_cache_node *node[MAX_NUMNODES]; |
| 139 | }; | 142 | }; |
| 140 | 143 | ||
diff --git a/include/linux/stddef.h b/include/linux/stddef.h index 2181719fd907..998a4ba28eba 100644 --- a/include/linux/stddef.h +++ b/include/linux/stddef.h | |||
| @@ -20,12 +20,20 @@ enum { | |||
| 20 | #endif | 20 | #endif |
| 21 | 21 | ||
| 22 | /** | 22 | /** |
| 23 | * sizeof_field(TYPE, MEMBER) | ||
| 24 | * | ||
| 25 | * @TYPE: The structure containing the field of interest | ||
| 26 | * @MEMBER: The field to return the size of | ||
| 27 | */ | ||
| 28 | #define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) | ||
| 29 | |||
| 30 | /** | ||
| 23 | * offsetofend(TYPE, MEMBER) | 31 | * offsetofend(TYPE, MEMBER) |
| 24 | * | 32 | * |
| 25 | * @TYPE: The type of the structure | 33 | * @TYPE: The type of the structure |
| 26 | * @MEMBER: The member within the structure to get the end offset of | 34 | * @MEMBER: The member within the structure to get the end offset of |
| 27 | */ | 35 | */ |
| 28 | #define offsetofend(TYPE, MEMBER) \ | 36 | #define offsetofend(TYPE, MEMBER) \ |
| 29 | (offsetof(TYPE, MEMBER) + sizeof(((TYPE *)0)->MEMBER)) | 37 | (offsetof(TYPE, MEMBER) + sizeof_field(TYPE, MEMBER)) |
| 30 | 38 | ||
| 31 | #endif | 39 | #endif |
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index 251e655d407f..efe79c1cdd47 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h | |||
| @@ -273,4 +273,12 @@ extern long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count); | |||
| 273 | #define unsafe_put_user(x, ptr, err) do { if (unlikely(__put_user(x, ptr))) goto err; } while (0) | 273 | #define unsafe_put_user(x, ptr, err) do { if (unlikely(__put_user(x, ptr))) goto err; } while (0) |
| 274 | #endif | 274 | #endif |
| 275 | 275 | ||
| 276 | #ifdef CONFIG_HARDENED_USERCOPY | ||
| 277 | void usercopy_warn(const char *name, const char *detail, bool to_user, | ||
| 278 | unsigned long offset, unsigned long len); | ||
| 279 | void __noreturn usercopy_abort(const char *name, const char *detail, | ||
| 280 | bool to_user, unsigned long offset, | ||
| 281 | unsigned long len); | ||
| 282 | #endif | ||
| 283 | |||
| 276 | #endif /* __LINUX_UACCESS_H__ */ | 284 | #endif /* __LINUX_UACCESS_H__ */ |
