Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'usercopy-v4.8-rc6-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull more hardened usercopyfixes from Kees Cook:

- force check_object_size() to be inline too

- move page-spanning check behind a CONFIG since it's triggering false
positives

[ Changed the page-spanning config option to depend on EXPERT in the
merge. That way it still gets build testing, and you can enable it if
you want to, but is never enabled for "normal" configurations ]

* tag 'usercopy-v4.8-rc6-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
usercopy: remove page-spanning test for now
usercopy: force check_object_size() inline

+48 -28
+2 -2
include/linux/thread_info.h
··· 118 118 extern void __check_object_size(const void *ptr, unsigned long n, 119 119 bool to_user); 120 120 121 - static inline void check_object_size(const void *ptr, unsigned long n, 122 - bool to_user) 121 + static __always_inline void check_object_size(const void *ptr, unsigned long n, 122 + bool to_user) 123 123 { 124 124 if (!__builtin_constant_p(n)) 125 125 __check_object_size(ptr, n, to_user);
+35 -26
mm/usercopy.c
··· 134 134 return NULL; 135 135 } 136 136 137 - static inline const char *check_heap_object(const void *ptr, unsigned long n, 138 - bool to_user) 137 + /* Checks for allocs that are marked in some way as spanning multiple pages. */ 138 + static inline const char *check_page_span(const void *ptr, unsigned long n, 139 + struct page *page, bool to_user) 139 140 { 140 - struct page *page, *endpage; 141 + #ifdef CONFIG_HARDENED_USERCOPY_PAGESPAN 141 142 const void *end = ptr + n - 1; 143 + struct page *endpage; 142 144 bool is_reserved, is_cma; 143 - 144 - /* 145 - * Some architectures (arm64) return true for virt_addr_valid() on 146 - * vmalloced addresses. Work around this by checking for vmalloc 147 - * first. 148 - */ 149 - if (is_vmalloc_addr(ptr)) 150 - return NULL; 151 - 152 - if (!virt_addr_valid(ptr)) 153 - return NULL; 154 - 155 - page = virt_to_head_page(ptr); 156 - 157 - /* Check slab allocator for flags and size. */ 158 - if (PageSlab(page)) 159 - return __check_heap_object(ptr, n, page); 160 145 161 146 /* 162 147 * Sometimes the kernel data regions are not marked Reserved (see ··· 171 186 ((unsigned long)end & (unsigned long)PAGE_MASK))) 172 187 return NULL; 173 188 174 - /* Allow if start and end are inside the same compound page. */ 189 + /* Allow if fully inside the same compound (__GFP_COMP) page. */ 175 190 endpage = virt_to_head_page(end); 176 191 if (likely(endpage == page)) 177 192 return NULL; ··· 184 199 is_reserved = PageReserved(page); 185 200 is_cma = is_migrate_cma_page(page); 186 201 if (!is_reserved && !is_cma) 187 - goto reject; 202 + return "<spans multiple pages>"; 188 203 189 204 for (ptr += PAGE_SIZE; ptr <= end; ptr += PAGE_SIZE) { 190 205 page = virt_to_head_page(ptr); 191 206 if (is_reserved && !PageReserved(page)) 192 - goto reject; 207 + return "<spans Reserved and non-Reserved pages>"; 193 208 if (is_cma && !is_migrate_cma_page(page)) 194 - goto reject; 209 + return "<spans CMA and non-CMA pages>"; 195 210 } 211 + #endif 196 212 197 213 return NULL; 214 + } 198 215 199 - reject: 200 - return "<spans multiple pages>"; 216 + static inline const char *check_heap_object(const void *ptr, unsigned long n, 217 + bool to_user) 218 + { 219 + struct page *page; 220 + 221 + /* 222 + * Some architectures (arm64) return true for virt_addr_valid() on 223 + * vmalloced addresses. Work around this by checking for vmalloc 224 + * first. 225 + */ 226 + if (is_vmalloc_addr(ptr)) 227 + return NULL; 228 + 229 + if (!virt_addr_valid(ptr)) 230 + return NULL; 231 + 232 + page = virt_to_head_page(ptr); 233 + 234 + /* Check slab allocator for flags and size. */ 235 + if (PageSlab(page)) 236 + return __check_heap_object(ptr, n, page); 237 + 238 + /* Verify object does not incorrectly span multiple pages. */ 239 + return check_page_span(ptr, n, page, to_user); 201 240 } 202 241 203 242 /*
+11
security/Kconfig
··· 147 147 or are part of the kernel text. This kills entire classes 148 148 of heap overflow exploits and similar kernel memory exposures. 149 149 150 + config HARDENED_USERCOPY_PAGESPAN 151 + bool "Refuse to copy allocations that span multiple pages" 152 + depends on HARDENED_USERCOPY 153 + depends on EXPERT 154 + help 155 + When a multi-page allocation is done without __GFP_COMP, 156 + hardened usercopy will reject attempts to copy it. There are, 157 + however, several cases of this in the kernel that have not all 158 + been removed. This config is intended to be used only while 159 + trying to find such users. 160 + 150 161 source security/selinux/Kconfig 151 162 source security/smack/Kconfig 152 163 source security/tomoyo/Kconfig