Skip to content

Commit aa28de2

Browse files
author
Al Viro
committed
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 <[email protected]>
1 parent b0377fe commit aa28de2

File tree

2 files changed

+64
-16
lines changed

2 files changed

+64
-16
lines changed

include/linux/uio.h

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define __LINUX_UIO_H
1111

1212
#include <linux/kernel.h>
13+
#include <linux/thread_info.h>
1314
#include <uapi/linux/uio.h>
1415

1516
struct page;
@@ -91,11 +92,58 @@ size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
9192
struct iov_iter *i);
9293
size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes,
9394
struct iov_iter *i);
94-
size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i);
95-
size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i);
96-
bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i);
97-
size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i);
98-
bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i);
95+
96+
size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i);
97+
size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i);
98+
bool _copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i);
99+
size_t _copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i);
100+
bool _copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i);
101+
102+
static __always_inline __must_check
103+
size_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+
111+
static __always_inline __must_check
112+
size_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+
120+
static __always_inline __must_check
121+
bool 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+
129+
static __always_inline __must_check
130+
size_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+
138+
static __always_inline __must_check
139+
bool 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+
99147
size_t iov_iter_zero(size_t bytes, struct iov_iter *);
100148
unsigned long iov_iter_alignment(const struct iov_iter *i);
101149
unsigned long iov_iter_gap_alignment(const struct iov_iter *i);

lib/iov_iter.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ static size_t copy_pipe_to_iter(const void *addr, size_t bytes,
535535
return bytes;
536536
}
537537

538-
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)
539539
{
540540
const char *from = addr;
541541
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)
550550

551551
return bytes;
552552
}
553-
EXPORT_SYMBOL(copy_to_iter);
553+
EXPORT_SYMBOL(_copy_to_iter);
554554

555-
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)
556556
{
557557
char *to = addr;
558558
if (unlikely(i->type & ITER_PIPE)) {
@@ -569,9 +569,9 @@ size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
569569

570570
return bytes;
571571
}
572-
EXPORT_SYMBOL(copy_from_iter);
572+
EXPORT_SYMBOL(_copy_from_iter);
573573

574-
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)
575575
{
576576
char *to = addr;
577577
if (unlikely(i->type & ITER_PIPE)) {
@@ -594,9 +594,9 @@ bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i)
594594
iov_iter_advance(i, bytes);
595595
return true;
596596
}
597-
EXPORT_SYMBOL(copy_from_iter_full);
597+
EXPORT_SYMBOL(_copy_from_iter_full);
598598

599-
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)
600600
{
601601
char *to = addr;
602602
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)
613613

614614
return bytes;
615615
}
616-
EXPORT_SYMBOL(copy_from_iter_nocache);
616+
EXPORT_SYMBOL(_copy_from_iter_nocache);
617617

618-
bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i)
618+
bool _copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i)
619619
{
620620
char *to = addr;
621621
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)
637637
iov_iter_advance(i, bytes);
638638
return true;
639639
}
640-
EXPORT_SYMBOL(copy_from_iter_full_nocache);
640+
EXPORT_SYMBOL(_copy_from_iter_full_nocache);
641641

642642
size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
643643
struct iov_iter *i)
@@ -663,7 +663,7 @@ size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes,
663663
}
664664
if (i->type & (ITER_BVEC|ITER_KVEC)) {
665665
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);
667667
kunmap_atomic(kaddr);
668668
return wanted;
669669
} else

0 commit comments

Comments
 (0)