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

Merge branch 'uaccess-work.iov_iter' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull iov_iter hardening from Al Viro:
"This is the iov_iter/uaccess/hardening pile.

For one thing, it trims the inline part of copy_to_user/copy_from_user
to the minimum that *does* need to be inlined - object size checks,
basically. For another, it sanitizes the checks for iov_iter
primitives. There are 4 groups of checks: access_ok(), might_fault(),
object size and KASAN.

- access_ok() had been verified by whoever had set the iov_iter up.
However, that has happened in a function far away, so proving that
there's no path to actual copying bypassing those checks is hard
and proving that iov_iter has not been buggered in the meanwhile is
also not pleasant. So we want those redone in actual
copyin/copyout.

- might_fault() is better off consolidated - we know whether it needs
to be checked as soon as we enter iov_iter primitive and observe
the iov_iter flavour. No need to wait until the copyin/copyout. The
call chains are short enough to make sure we won't miss anything -
in fact, it's more robust that way, since there are cases where we
do e.g. forced fault-in before getting to copyin/copyout. It's not
quite what we need to check (in particular, combination of
iovec-backed and set_fs(KERNEL_DS) is almost certainly a bug, not a
cause to skip checks), but that's for later series. For now let's
keep might_fault().

- KASAN checks belong in copyin/copyout - at the same level where
other iov_iter flavours would've hit them in memcpy().

- object size checks should apply to *all* iov_iter flavours, not
just iovec-backed ones.

There are two groups of primitives - one gets the kernel object
described as pointer + size (copy_to_iter(), etc.) while another gets
it as page + offset + size (copy_page_to_iter(), etc.)

For the first group the checks are best done where we actually have a
chance to find the object size. In other words, those belong in inline
wrappers in uio.h, before calling into iov_iter.c. Same kind as we
have for inlined part of copy_to_user().

For the second group there is no object to look at - offset in page is
just a number, it bears no type information. So we do them in the
common helper called by iov_iter.c primitives of that kind. All it
currently does is checking that we are not trying to access outside of
the compound page; eventually we might want to add some sanity checks
on the page involved.

So the things we need in copyin/copyout part of iov_iter.c do not
quite match anything in uaccess.h (we want no zeroing, we *do* want
access_ok() and KASAN and we want no might_fault() or object size
checks done on that level). OTOH, these needs are simple enough to
provide a couple of helpers (static in iov_iter.c) doing just what we
need..."

* 'uaccess-work.iov_iter' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
iov_iter: saner checks on copyin/copyout
iov_iter: sanity checks for copy to/from page primitives
iov_iter/hardening: move object size checks to inlined part
copy_{to,from}_user(): consolidate object size checks
copy_{from,to}_user(): move kasan checks and might_fault() out-of-line

+179 -76
+27
include/linux/thread_info.h
··· 113 113 { } 114 114 #endif /* CONFIG_HARDENED_USERCOPY */ 115 115 116 + extern void __compiletime_error("copy source size is too small") 117 + __bad_copy_from(void); 118 + extern void __compiletime_error("copy destination size is too small") 119 + __bad_copy_to(void); 120 + 121 + static inline void copy_overflow(int size, unsigned long count) 122 + { 123 + WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count); 124 + } 125 + 126 + static __always_inline bool 127 + check_copy_size(const void *addr, size_t bytes, bool is_source) 128 + { 129 + int sz = __compiletime_object_size(addr); 130 + if (unlikely(sz >= 0 && sz < bytes)) { 131 + if (!__builtin_constant_p(bytes)) 132 + copy_overflow(sz, bytes); 133 + else if (is_source) 134 + __bad_copy_from(); 135 + else 136 + __bad_copy_to(); 137 + return false; 138 + } 139 + check_object_size(addr, bytes, is_source); 140 + return true; 141 + } 142 + 116 143 #ifndef arch_setup_new_exec 117 144 static inline void arch_setup_new_exec(void) { } 118 145 #endif
+10 -34
include/linux/uaccess.h
··· 109 109 _copy_from_user(void *to, const void __user *from, unsigned long n) 110 110 { 111 111 unsigned long res = n; 112 - if (likely(access_ok(VERIFY_READ, from, n))) 112 + might_fault(); 113 + if (likely(access_ok(VERIFY_READ, from, n))) { 114 + kasan_check_write(to, n); 113 115 res = raw_copy_from_user(to, from, n); 116 + } 114 117 if (unlikely(res)) 115 118 memset(to + (n - res), 0, res); 116 119 return res; ··· 127 124 static inline unsigned long 128 125 _copy_to_user(void __user *to, const void *from, unsigned long n) 129 126 { 130 - if (access_ok(VERIFY_WRITE, to, n)) 127 + might_fault(); 128 + if (access_ok(VERIFY_WRITE, to, n)) { 129 + kasan_check_read(from, n); 131 130 n = raw_copy_to_user(to, from, n); 131 + } 132 132 return n; 133 133 } 134 134 #else ··· 139 133 _copy_to_user(void __user *, const void *, unsigned long); 140 134 #endif 141 135 142 - extern void __compiletime_error("usercopy buffer size is too small") 143 - __bad_copy_user(void); 144 - 145 - static inline void copy_user_overflow(int size, unsigned long count) 146 - { 147 - WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count); 148 - } 149 - 150 136 static __always_inline unsigned long __must_check 151 137 copy_from_user(void *to, const void __user *from, unsigned long n) 152 138 { 153 - int sz = __compiletime_object_size(to); 154 - 155 - might_fault(); 156 - kasan_check_write(to, n); 157 - 158 - if (likely(sz < 0 || sz >= n)) { 159 - check_object_size(to, n, false); 139 + if (likely(check_copy_size(to, n, false))) 160 140 n = _copy_from_user(to, from, n); 161 - } else if (!__builtin_constant_p(n)) 162 - copy_user_overflow(sz, n); 163 - else 164 - __bad_copy_user(); 165 - 166 141 return n; 167 142 } 168 143 169 144 static __always_inline unsigned long __must_check 170 145 copy_to_user(void __user *to, const void *from, unsigned long n) 171 146 { 172 - int sz = __compiletime_object_size(from); 173 - 174 - kasan_check_read(from, n); 175 - might_fault(); 176 - 177 - if (likely(sz < 0 || sz >= n)) { 178 - check_object_size(from, n, true); 147 + if (likely(check_copy_size(from, n, true))) 179 148 n = _copy_to_user(to, from, n); 180 - } else if (!__builtin_constant_p(n)) 181 - copy_user_overflow(sz, n); 182 - else 183 - __bad_copy_user(); 184 - 185 149 return n; 186 150 } 187 151 #ifdef CONFIG_COMPAT
+65 -11
include/linux/uio.h
··· 10 10 #define __LINUX_UIO_H 11 11 12 12 #include <linux/kernel.h> 13 + #include <linux/thread_info.h> 13 14 #include <uapi/linux/uio.h> 14 15 15 16 struct page; ··· 92 91 struct iov_iter *i); 93 92 size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, 94 93 struct iov_iter *i); 95 - size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i); 96 - size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i); 97 - bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i); 98 - size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i); 94 + 95 + size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i); 96 + size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i); 97 + bool _copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i); 98 + size_t _copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i); 99 + bool _copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i); 100 + 101 + static __always_inline __must_check 102 + size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) 103 + { 104 + if (unlikely(!check_copy_size(addr, bytes, true))) 105 + return bytes; 106 + else 107 + return _copy_to_iter(addr, bytes, i); 108 + } 109 + 110 + static __always_inline __must_check 111 + size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) 112 + { 113 + if (unlikely(!check_copy_size(addr, bytes, false))) 114 + return bytes; 115 + else 116 + return _copy_from_iter(addr, bytes, i); 117 + } 118 + 119 + static __always_inline __must_check 120 + bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i) 121 + { 122 + if (unlikely(!check_copy_size(addr, bytes, false))) 123 + return false; 124 + else 125 + return _copy_from_iter_full(addr, bytes, i); 126 + } 127 + 128 + static __always_inline __must_check 129 + size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) 130 + { 131 + if (unlikely(!check_copy_size(addr, bytes, false))) 132 + return bytes; 133 + else 134 + return _copy_from_iter_nocache(addr, bytes, i); 135 + } 136 + 137 + static __always_inline __must_check 138 + bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i) 139 + { 140 + if (unlikely(!check_copy_size(addr, bytes, false))) 141 + return false; 142 + else 143 + return _copy_from_iter_full_nocache(addr, bytes, i); 144 + } 145 + 99 146 #ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE 100 147 /* 101 148 * Note, users like pmem that depend on the stricter semantics of ··· 151 102 * IS_ENABLED(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) before assuming that the 152 103 * destination is flushed from the cache on return. 153 104 */ 154 - size_t copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i); 105 + size_t _copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i); 155 106 #else 156 - static inline size_t copy_from_iter_flushcache(void *addr, size_t bytes, 157 - struct iov_iter *i) 158 - { 159 - return copy_from_iter_nocache(addr, bytes, i); 160 - } 107 + #define _copy_from_iter_flushcache _copy_from_iter_nocache 161 108 #endif 162 - bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i); 109 + 110 + static __always_inline __must_check 111 + size_t copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i) 112 + { 113 + if (unlikely(!check_copy_size(addr, bytes, false))) 114 + return bytes; 115 + else 116 + return _copy_from_iter_flushcache(addr, bytes, i); 117 + } 118 + 163 119 size_t iov_iter_zero(size_t bytes, struct iov_iter *); 164 120 unsigned long iov_iter_alignment(const struct iov_iter *i); 165 121 unsigned long iov_iter_gap_alignment(const struct iov_iter *i);
+69 -29
lib/iov_iter.c
··· 130 130 } \ 131 131 } 132 132 133 + static int copyout(void __user *to, const void *from, size_t n) 134 + { 135 + if (access_ok(VERIFY_WRITE, to, n)) { 136 + kasan_check_read(from, n); 137 + n = raw_copy_to_user(to, from, n); 138 + } 139 + return n; 140 + } 141 + 142 + static int copyin(void *to, const void __user *from, size_t n) 143 + { 144 + if (access_ok(VERIFY_READ, from, n)) { 145 + kasan_check_write(to, n); 146 + n = raw_copy_from_user(to, from, n); 147 + } 148 + return n; 149 + } 150 + 133 151 static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes, 134 152 struct iov_iter *i) 135 153 { ··· 162 144 if (unlikely(!bytes)) 163 145 return 0; 164 146 147 + might_fault(); 165 148 wanted = bytes; 166 149 iov = i->iov; 167 150 skip = i->iov_offset; ··· 174 155 from = kaddr + offset; 175 156 176 157 /* first chunk, usually the only one */ 177 - left = __copy_to_user_inatomic(buf, from, copy); 158 + left = copyout(buf, from, copy); 178 159 copy -= left; 179 160 skip += copy; 180 161 from += copy; ··· 184 165 iov++; 185 166 buf = iov->iov_base; 186 167 copy = min(bytes, iov->iov_len); 187 - left = __copy_to_user_inatomic(buf, from, copy); 168 + left = copyout(buf, from, copy); 188 169 copy -= left; 189 170 skip = copy; 190 171 from += copy; ··· 203 184 204 185 kaddr = kmap(page); 205 186 from = kaddr + offset; 206 - left = __copy_to_user(buf, from, copy); 187 + left = copyout(buf, from, copy); 207 188 copy -= left; 208 189 skip += copy; 209 190 from += copy; ··· 212 193 iov++; 213 194 buf = iov->iov_base; 214 195 copy = min(bytes, iov->iov_len); 215 - left = __copy_to_user(buf, from, copy); 196 + left = copyout(buf, from, copy); 216 197 copy -= left; 217 198 skip = copy; 218 199 from += copy; ··· 246 227 if (unlikely(!bytes)) 247 228 return 0; 248 229 230 + might_fault(); 249 231 wanted = bytes; 250 232 iov = i->iov; 251 233 skip = i->iov_offset; ··· 258 238 to = kaddr + offset; 259 239 260 240 /* first chunk, usually the only one */ 261 - left = __copy_from_user_inatomic(to, buf, copy); 241 + left = copyin(to, buf, copy); 262 242 copy -= left; 263 243 skip += copy; 264 244 to += copy; ··· 268 248 iov++; 269 249 buf = iov->iov_base; 270 250 copy = min(bytes, iov->iov_len); 271 - left = __copy_from_user_inatomic(to, buf, copy); 251 + left = copyin(to, buf, copy); 272 252 copy -= left; 273 253 skip = copy; 274 254 to += copy; ··· 287 267 288 268 kaddr = kmap(page); 289 269 to = kaddr + offset; 290 - left = __copy_from_user(to, buf, copy); 270 + left = copyin(to, buf, copy); 291 271 copy -= left; 292 272 skip += copy; 293 273 to += copy; ··· 296 276 iov++; 297 277 buf = iov->iov_base; 298 278 copy = min(bytes, iov->iov_len); 299 - left = __copy_from_user(to, buf, copy); 279 + left = copyin(to, buf, copy); 300 280 copy -= left; 301 281 skip = copy; 302 282 to += copy; ··· 555 535 return bytes; 556 536 } 557 537 558 - size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) 538 + size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) 559 539 { 560 540 const char *from = addr; 561 541 if (unlikely(i->type & ITER_PIPE)) 562 542 return copy_pipe_to_iter(addr, bytes, i); 543 + if (iter_is_iovec(i)) 544 + might_fault(); 563 545 iterate_and_advance(i, bytes, v, 564 - __copy_to_user(v.iov_base, (from += v.iov_len) - v.iov_len, 565 - v.iov_len), 546 + copyout(v.iov_base, (from += v.iov_len) - v.iov_len, v.iov_len), 566 547 memcpy_to_page(v.bv_page, v.bv_offset, 567 548 (from += v.bv_len) - v.bv_len, v.bv_len), 568 549 memcpy(v.iov_base, (from += v.iov_len) - v.iov_len, v.iov_len) ··· 571 550 572 551 return bytes; 573 552 } 574 - EXPORT_SYMBOL(copy_to_iter); 553 + EXPORT_SYMBOL(_copy_to_iter); 575 554 576 - size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) 555 + size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) 577 556 { 578 557 char *to = addr; 579 558 if (unlikely(i->type & ITER_PIPE)) { 580 559 WARN_ON(1); 581 560 return 0; 582 561 } 562 + if (iter_is_iovec(i)) 563 + might_fault(); 583 564 iterate_and_advance(i, bytes, v, 584 - __copy_from_user((to += v.iov_len) - v.iov_len, v.iov_base, 585 - v.iov_len), 565 + copyin((to += v.iov_len) - v.iov_len, v.iov_base, v.iov_len), 586 566 memcpy_from_page((to += v.bv_len) - v.bv_len, v.bv_page, 587 567 v.bv_offset, v.bv_len), 588 568 memcpy((to += v.iov_len) - v.iov_len, v.iov_base, v.iov_len) ··· 591 569 592 570 return bytes; 593 571 } 594 - EXPORT_SYMBOL(copy_from_iter); 572 + EXPORT_SYMBOL(_copy_from_iter); 595 573 596 - bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i) 574 + bool _copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i) 597 575 { 598 576 char *to = addr; 599 577 if (unlikely(i->type & ITER_PIPE)) { ··· 603 581 if (unlikely(i->count < bytes)) 604 582 return false; 605 583 584 + if (iter_is_iovec(i)) 585 + might_fault(); 606 586 iterate_all_kinds(i, bytes, v, ({ 607 - if (__copy_from_user((to += v.iov_len) - v.iov_len, 587 + if (copyin((to += v.iov_len) - v.iov_len, 608 588 v.iov_base, v.iov_len)) 609 589 return false; 610 590 0;}), ··· 618 594 iov_iter_advance(i, bytes); 619 595 return true; 620 596 } 621 - EXPORT_SYMBOL(copy_from_iter_full); 597 + EXPORT_SYMBOL(_copy_from_iter_full); 622 598 623 - size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) 599 + size_t _copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) 624 600 { 625 601 char *to = addr; 626 602 if (unlikely(i->type & ITER_PIPE)) { ··· 637 613 638 614 return bytes; 639 615 } 640 - EXPORT_SYMBOL(copy_from_iter_nocache); 616 + EXPORT_SYMBOL(_copy_from_iter_nocache); 641 617 642 618 #ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE 643 - size_t copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i) 619 + size_t _copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i) 644 620 { 645 621 char *to = addr; 646 622 if (unlikely(i->type & ITER_PIPE)) { ··· 658 634 659 635 return bytes; 660 636 } 661 - EXPORT_SYMBOL_GPL(copy_from_iter_flushcache); 637 + EXPORT_SYMBOL_GPL(_copy_from_iter_flushcache); 662 638 #endif 663 639 664 - bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i) 640 + bool _copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i) 665 641 { 666 642 char *to = addr; 667 643 if (unlikely(i->type & ITER_PIPE)) { ··· 683 659 iov_iter_advance(i, bytes); 684 660 return true; 685 661 } 686 - EXPORT_SYMBOL(copy_from_iter_full_nocache); 662 + EXPORT_SYMBOL(_copy_from_iter_full_nocache); 663 + 664 + static inline bool page_copy_sane(struct page *page, size_t offset, size_t n) 665 + { 666 + size_t v = n + offset; 667 + if (likely(n <= v && v <= (PAGE_SIZE << compound_order(page)))) 668 + return true; 669 + WARN_ON(1); 670 + return false; 671 + } 687 672 688 673 size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, 689 674 struct iov_iter *i) 690 675 { 676 + if (unlikely(!page_copy_sane(page, offset, bytes))) 677 + return 0; 691 678 if (i->type & (ITER_BVEC|ITER_KVEC)) { 692 679 void *kaddr = kmap_atomic(page); 693 680 size_t wanted = copy_to_iter(kaddr + offset, bytes, i); ··· 714 679 size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, 715 680 struct iov_iter *i) 716 681 { 682 + if (unlikely(!page_copy_sane(page, offset, bytes))) 683 + return 0; 717 684 if (unlikely(i->type & ITER_PIPE)) { 718 685 WARN_ON(1); 719 686 return 0; 720 687 } 721 688 if (i->type & (ITER_BVEC|ITER_KVEC)) { 722 689 void *kaddr = kmap_atomic(page); 723 - size_t wanted = copy_from_iter(kaddr + offset, bytes, i); 690 + size_t wanted = _copy_from_iter(kaddr + offset, bytes, i); 724 691 kunmap_atomic(kaddr); 725 692 return wanted; 726 693 } else ··· 759 722 if (unlikely(i->type & ITER_PIPE)) 760 723 return pipe_zero(bytes, i); 761 724 iterate_and_advance(i, bytes, v, 762 - __clear_user(v.iov_base, v.iov_len), 725 + clear_user(v.iov_base, v.iov_len), 763 726 memzero_page(v.bv_page, v.bv_offset, v.bv_len), 764 727 memset(v.iov_base, 0, v.iov_len) 765 728 ) ··· 772 735 struct iov_iter *i, unsigned long offset, size_t bytes) 773 736 { 774 737 char *kaddr = kmap_atomic(page), *p = kaddr + offset; 738 + if (unlikely(!page_copy_sane(page, offset, bytes))) { 739 + kunmap_atomic(kaddr); 740 + return 0; 741 + } 775 742 if (unlikely(i->type & ITER_PIPE)) { 776 743 kunmap_atomic(kaddr); 777 744 WARN_ON(1); 778 745 return 0; 779 746 } 780 747 iterate_all_kinds(i, bytes, v, 781 - __copy_from_user_inatomic((p += v.iov_len) - v.iov_len, 782 - v.iov_base, v.iov_len), 748 + copyin((p += v.iov_len) - v.iov_len, v.iov_base, v.iov_len), 783 749 memcpy_from_page((p += v.bv_len) - v.bv_len, v.bv_page, 784 750 v.bv_offset, v.bv_len), 785 751 memcpy((p += v.iov_len) - v.iov_len, v.iov_base, v.iov_len)
+8 -2
lib/usercopy.c
··· 6 6 unsigned long _copy_from_user(void *to, const void __user *from, unsigned long n) 7 7 { 8 8 unsigned long res = n; 9 - if (likely(access_ok(VERIFY_READ, from, n))) 9 + might_fault(); 10 + if (likely(access_ok(VERIFY_READ, from, n))) { 11 + kasan_check_write(to, n); 10 12 res = raw_copy_from_user(to, from, n); 13 + } 11 14 if (unlikely(res)) 12 15 memset(to + (n - res), 0, res); 13 16 return res; ··· 21 18 #ifndef INLINE_COPY_TO_USER 22 19 unsigned long _copy_to_user(void *to, const void __user *from, unsigned long n) 23 20 { 24 - if (likely(access_ok(VERIFY_WRITE, to, n))) 21 + might_fault(); 22 + if (likely(access_ok(VERIFY_WRITE, to, n))) { 23 + kasan_check_read(from, n); 25 24 n = raw_copy_to_user(to, from, n); 25 + } 26 26 return n; 27 27 } 28 28 EXPORT_SYMBOL(_copy_to_user);