aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-02-03 19:25:42 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-03 19:25:42 -0500
commit617aebe6a97efa539cc4b8a52adccd89596e6be0 (patch)
tree51c7753c940fd3727b8cc3e93553c57f89d1d9d2 /include
parent0771ad44a20bc512d1123bac728d3a89ea6febe6 (diff)
parente47e311843dece8073146f3606871280ee9beb87 (diff)
Merge tag 'usercopy-v4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull hardened usercopy whitelisting from Kees Cook: "Currently, hardened usercopy performs dynamic bounds checking on slab cache objects. This is good, but still leaves a lot of kernel memory available to be copied to/from userspace in the face of bugs. To further restrict what memory is available for copying, this creates a way to whitelist specific areas of a given slab cache object for copying to/from userspace, allowing much finer granularity of access control. Slab caches that are never exposed to userspace can declare no whitelist for their objects, thereby keeping them unavailable to userspace via dynamic copy operations. (Note, an implicit form of whitelisting is the use of constant sizes in usercopy operations and get_user()/put_user(); these bypass all hardened usercopy checks since these sizes cannot change at runtime.) This new check is WARN-by-default, so any mistakes can be found over the next several releases without breaking anyone's system. The series has roughly the following sections: - remove %p and improve reporting with offset - prepare infrastructure and whitelist kmalloc - update VFS subsystem with whitelists - update SCSI subsystem with whitelists - update network subsystem with whitelists - update process memory with whitelists - update per-architecture thread_struct with whitelists - update KVM with whitelists and fix ioctl bug - mark all other allocations as not whitelisted - update lkdtm for more sensible test overage" * tag 'usercopy-v4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: (38 commits) lkdtm: Update usercopy tests for whitelisting usercopy: Restrict non-usercopy caches to size 0 kvm: x86: fix KVM_XEN_HVM_CONFIG ioctl kvm: whitelist struct kvm_vcpu_arch arm: Implement thread_struct whitelist for hardened usercopy arm64: Implement thread_struct whitelist for hardened usercopy x86: Implement thread_struct whitelist for hardened usercopy fork: Provide usercopy whitelisting for task_struct fork: Define usercopy region in thread_stack slab caches fork: Define usercopy region in mm_struct slab caches net: Restrict unwhitelisted proto caches to size 0 sctp: Copy struct sctp_sock.autoclose to userspace using put_user() sctp: Define usercopy region in SCTP proto slab cache caif: Define usercopy region in caif proto slab cache ip: Define usercopy region in IP proto slab cache net: Define usercopy region in struct proto slab cache scsi: Define usercopy region in scsi_sense_cache slab cache cifs: Define usercopy region in cifs_request slab cache vxfs: Define usercopy region in vxfs_inode slab cache ufs: Define usercopy region in ufs_inode_cache slab cache ...
Diffstat (limited to 'include')
-rw-r--r--include/linux/sched/task.h14
-rw-r--r--include/linux/slab.h41
-rw-r--r--include/linux/slab_def.h3
-rw-r--r--include/linux/slub_def.h3
-rw-r--r--include/linux/stddef.h10
-rw-r--r--include/linux/uaccess.h8
-rw-r--r--include/net/sctp/structs.h9
-rw-r--r--include/net/sock.h2
8 files changed, 73 insertions, 17 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 */
112static 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
108static inline struct vm_struct *task_stack_vm_area(const struct task_struct *t) 122static 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;
135void __init kmem_cache_init(void); 135void __init kmem_cache_init(void);
136bool slab_is_available(void); 136bool slab_is_available(void);
137 137
138struct kmem_cache *kmem_cache_create(const char *, size_t, size_t, 138extern bool usercopy_fallback;
139 slab_flags_t, 139
140 void (*)(void *)); 140struct kmem_cache *kmem_cache_create(const char *name, size_t size,
141 size_t align, slab_flags_t flags,
142 void (*ctor)(void *));
143struct 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 *));
141void kmem_cache_destroy(struct kmem_cache *); 147void kmem_cache_destroy(struct kmem_cache *);
142int kmem_cache_shrink(struct kmem_cache *); 148int 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 *);
167size_t ksize(const void *); 184size_t ksize(const void *);
168 185
169#ifdef CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR 186#ifdef CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR
170const char *__check_heap_object(const void *ptr, unsigned long n, 187void __check_heap_object(const void *ptr, unsigned long n, struct page *page,
171 struct page *page); 188 bool to_user);
172#else 189#else
173static inline const char *__check_heap_object(const void *ptr, 190static 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
277void usercopy_warn(const char *name, const char *detail, bool to_user,
278 unsigned long offset, unsigned long len);
279void __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__ */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 02369e379d35..03e92dda1813 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -203,12 +203,17 @@ struct sctp_sock {
203 /* Flags controlling Heartbeat, SACK delay, and Path MTU Discovery. */ 203 /* Flags controlling Heartbeat, SACK delay, and Path MTU Discovery. */
204 __u32 param_flags; 204 __u32 param_flags;
205 205
206 struct sctp_initmsg initmsg;
207 struct sctp_rtoinfo rtoinfo; 206 struct sctp_rtoinfo rtoinfo;
208 struct sctp_paddrparams paddrparam; 207 struct sctp_paddrparams paddrparam;
209 struct sctp_event_subscribe subscribe;
210 struct sctp_assocparams assocparams; 208 struct sctp_assocparams assocparams;
211 209
210 /*
211 * These two structures must be grouped together for the usercopy
212 * whitelist region.
213 */
214 struct sctp_event_subscribe subscribe;
215 struct sctp_initmsg initmsg;
216
212 int user_frag; 217 int user_frag;
213 218
214 __u32 autoclose; 219 __u32 autoclose;
diff --git a/include/net/sock.h b/include/net/sock.h
index 63731289186a..169c92afcafa 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1109,6 +1109,8 @@ struct proto {
1109 struct kmem_cache *slab; 1109 struct kmem_cache *slab;
1110 unsigned int obj_size; 1110 unsigned int obj_size;
1111 slab_flags_t slab_flags; 1111 slab_flags_t slab_flags;
1112 size_t useroffset; /* Usercopy region offset */
1113 size_t usersize; /* Usercopy region size */
1112 1114
1113 struct percpu_counter *orphan_count; 1115 struct percpu_counter *orphan_count;
1114 1116