summaryrefslogtreecommitdiff
path: root/include/linux/uio.h
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2022-02-02 14:20:31 -0800
committerDavid S. Miller <davem@davemloft.net>2022-02-04 10:14:07 +0000
commitb93235e68921b9acd38ee309953a3a9808105289 (patch)
tree48d9273feaf831aaa0b4f3393c199a049505b1f6 /include/linux/uio.h
parent6ff6064605e96db40c7e95c4924518028cd827bf (diff)
downloadlwn-b93235e68921b9acd38ee309953a3a9808105289.tar.gz
lwn-b93235e68921b9acd38ee309953a3a9808105289.zip
tls: cap the output scatter list to something reasonable
TLS recvmsg() passes user pages as destination for decrypt. The decrypt operation is repeated record by record, each record being 16kB, max. TLS allocates an sg_table and uses iov_iter_get_pages() to populate it with enough pages to fit the decrypted record. Even though we decrypt a single message at a time we size the sg_table based on the entire length of the iovec. This leads to unnecessarily large allocations, risking triggering OOM conditions. Use iov_iter_truncate() / iov_iter_reexpand() to construct a "capped" version of iov_iter_npages(). Alternatively we could parametrize iov_iter_npages() to take the size as arg instead of using i->count, or do something else.. Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/uio.h')
-rw-r--r--include/linux/uio.h17
1 files changed, 17 insertions, 0 deletions
diff --git a/include/linux/uio.h b/include/linux/uio.h
index 1198a2bfc9bf..739285fe5a2f 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -273,6 +273,23 @@ static inline void iov_iter_reexpand(struct iov_iter *i, size_t count)
i->count = count;
}
+static inline int
+iov_iter_npages_cap(struct iov_iter *i, int maxpages, size_t max_bytes)
+{
+ size_t shorted = 0;
+ int npages;
+
+ if (iov_iter_count(i) > max_bytes) {
+ shorted = iov_iter_count(i) - max_bytes;
+ iov_iter_truncate(i, max_bytes);
+ }
+ npages = iov_iter_npages(i, INT_MAX);
+ if (shorted)
+ iov_iter_reexpand(i, iov_iter_count(i) + shorted);
+
+ return npages;
+}
+
struct csum_state {
__wsum csum;
size_t off;