aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2017-06-29 21:45:10 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2017-06-29 22:21:22 -0400
commitaa28de275a248879f9828cb9f7ee7e119c72ff96 (patch)
treeea50dff24c17d06ed9a799b38e8089996c3ccff2
parentb0377fedb6528087ed319b0d054d6ed82240372c (diff)
iov_iter/hardening: move object size checks to inlined part
There we actually have useful information about object sizes. Note: this patch has them done for all iov_iter flavours. Right now we do them twice in iovec case, but that'll change very shortly. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--include/linux/uio.h58
-rw-r--r--lib/iov_iter.c22
2 files changed, 64 insertions, 16 deletions
diff --git a/include/linux/uio.h b/include/linux/uio.h
index f2d36a3d3005..243e2362fe1a 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -10,6 +10,7 @@
10#define __LINUX_UIO_H 10#define __LINUX_UIO_H
11 11
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/thread_info.h>
13#include <uapi/linux/uio.h> 14#include <uapi/linux/uio.h>
14 15
15struct page; 16struct page;
@@ -91,11 +92,58 @@ size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
91 struct iov_iter *i); 92 struct iov_iter *i);
92size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, 93size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes,
93 struct iov_iter *i); 94 struct iov_iter *i);
94size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i); 95
95size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i); 96size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i);
96bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i); 97size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i);
97size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i); 98bool _copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i);
98bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i); 99size_t _copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i);
100bool _copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i);
101
102static __always_inline __must_check
103size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
104{
105 if (unlikely(!check_copy_size(addr, bytes, true)))
106 return bytes;
107 else
108 return _copy_to_iter(addr, bytes, i);
109}
110
111static __always_inline __must_check
112size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
113{
114 if (unlikely(!check_copy_size(addr, bytes, false)))
115 return bytes;
116 else
117 return _copy_from_iter(addr, bytes, i);
118}
119
120static __always_inline __must_check
121bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i)
122{
123 if (unlikely(!check_copy_size(addr, bytes, false)))
124 return false;
125 else
126 return _copy_from_iter_full(addr, bytes, i);
127}
128
129static __always_inline __must_check
130size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i)
131{
132 if (unlikely(!check_copy_size(addr, bytes, false)))
133 return bytes;
134 else
135 return _copy_from_iter_nocache(addr, bytes, i);
136}
137
138static __always_inline __must_check
139bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i)
140{
141 if (unlikely(!check_copy_size(addr, bytes, false)))
142 return false;
143 else
144 return _copy_from_iter_full_nocache(addr, bytes, i);
145}
146
99size_t iov_iter_zero(size_t bytes, struct iov_iter *); 147size_t iov_iter_zero(size_t bytes, struct iov_iter *);
100unsigned long iov_iter_alignment(const struct iov_iter *i); 148unsigned long iov_iter_alignment(const struct iov_iter *i);
101unsigned long iov_iter_gap_alignment(const struct iov_iter *i); 149unsigned long iov_iter_gap_alignment(const struct iov_iter *i);
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index f835964c9485..bc4a63ebe91a 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -535,7 +535,7 @@ static size_t copy_pipe_to_iter(const void *addr, size_t bytes,
535 return bytes; 535 return bytes;
536} 536}
537 537
538size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) 538size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
539{ 539{
540 const char *from = addr; 540 const char *from = addr;
541 if (unlikely(i->type & ITER_PIPE)) 541 if (unlikely(i->type & ITER_PIPE))
@@ -550,9 +550,9 @@ size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
550 550
551 return bytes; 551 return bytes;
552} 552}
553EXPORT_SYMBOL(copy_to_iter); 553EXPORT_SYMBOL(_copy_to_iter);
554 554
555size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) 555size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
556{ 556{
557 char *to = addr; 557 char *to = addr;
558 if (unlikely(i->type & ITER_PIPE)) { 558 if (unlikely(i->type & ITER_PIPE)) {
@@ -569,9 +569,9 @@ size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
569 569
570 return bytes; 570 return bytes;
571} 571}
572EXPORT_SYMBOL(copy_from_iter); 572EXPORT_SYMBOL(_copy_from_iter);
573 573
574bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i) 574bool _copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i)
575{ 575{
576 char *to = addr; 576 char *to = addr;
577 if (unlikely(i->type & ITER_PIPE)) { 577 if (unlikely(i->type & ITER_PIPE)) {
@@ -594,9 +594,9 @@ bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i)
594 iov_iter_advance(i, bytes); 594 iov_iter_advance(i, bytes);
595 return true; 595 return true;
596} 596}
597EXPORT_SYMBOL(copy_from_iter_full); 597EXPORT_SYMBOL(_copy_from_iter_full);
598 598
599size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) 599size_t _copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i)
600{ 600{
601 char *to = addr; 601 char *to = addr;
602 if (unlikely(i->type & ITER_PIPE)) { 602 if (unlikely(i->type & ITER_PIPE)) {
@@ -613,9 +613,9 @@ size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i)
613 613
614 return bytes; 614 return bytes;
615} 615}
616EXPORT_SYMBOL(copy_from_iter_nocache); 616EXPORT_SYMBOL(_copy_from_iter_nocache);
617 617
618bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i) 618bool _copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i)
619{ 619{
620 char *to = addr; 620 char *to = addr;
621 if (unlikely(i->type & ITER_PIPE)) { 621 if (unlikely(i->type & ITER_PIPE)) {
@@ -637,7 +637,7 @@ bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i)
637 iov_iter_advance(i, bytes); 637 iov_iter_advance(i, bytes);
638 return true; 638 return true;
639} 639}
640EXPORT_SYMBOL(copy_from_iter_full_nocache); 640EXPORT_SYMBOL(_copy_from_iter_full_nocache);
641 641
642size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, 642size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
643 struct iov_iter *i) 643 struct iov_iter *i)
@@ -663,7 +663,7 @@ size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes,
663 } 663 }
664 if (i->type & (ITER_BVEC|ITER_KVEC)) { 664 if (i->type & (ITER_BVEC|ITER_KVEC)) {
665 void *kaddr = kmap_atomic(page); 665 void *kaddr = kmap_atomic(page);
666 size_t wanted = copy_from_iter(kaddr + offset, bytes, i); 666 size_t wanted = _copy_from_iter(kaddr + offset, bytes, i);
667 kunmap_atomic(kaddr); 667 kunmap_atomic(kaddr);
668 return wanted; 668 return wanted;
669 } else 669 } else