Use the same approach as in iscsi iscsi_tcp_segment_map() which makes
the same operation
in the same context.

In vz7 we added iov_iter_get_pages() infrastructure ourselves and we
did it in safe way.
We checked page before doing any manipulations on it right in core of
iov_iter_get_pages()
and terminated iov_iter_get_pages() if the page looked dubious. We
cannot make this now because
this function is used in many places over kernel and not all the
places are sensitive
to origin of pages but all of them definitely will crash if
iov_iter_get_pages() returns error.

This patch will work for now. I still believe this place deserves
further investigation.
It smells like mainstream could be wrong. Look at my comment in code
for the reasons of doubts.

Affects: #PSBM-146821, #PSBM-146846
https://jira.vzint.dev/browse/PSBM-146821
https://jira.vzint.dev/browse/PSBM-146846

Signed-off-by: Alexey Kuznetsov <kuz...@acronis.com>
From 69bd3dc09f62ec0f023d2b0a6d521e3b32ac5bd2 Mon Sep 17 00:00:00 2001
From: Alexey Kuznetsov <kuz...@acronis.com>
Date: Mon, 17 Apr 2023 22:07:15 +0800
Subject: fuse: pcs: do not use sendpage on pages which cannot be sendpaged

Use the same approach as in iscsi iscsi_tcp_segment_map() which makes the same operation
in the same context.

In vz7 we added iov_iter_get_pages() infrastructure ourselves and we did it in safe way.
We checked page before doing any manipulations on it right in core of iov_iter_get_pages()
and terminated iov_iter_get_pages() if the page looked dubious. We cannot make this now because
this function is used in many places over kernel and not all the places are sensitive
to origin of pages but all of them definitely will crash if iov_iter_get_pages() returns error.

This patch will work for now. I still believe this place deserves further investigation.
It smells like mainstream could be wrong. Look at my comment in code for the reasons of doubts.

Affects: #PSBM-146821, #PSBM-146846
https://jira.vzint.dev/browse/PSBM-146821
https://jira.vzint.dev/browse/PSBM-146846

Signed-off-by: Alexey Kuznetsov <kuz...@acronis.com>
---
 fs/fuse/kio/pcs/pcs_sock_io.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/fs/fuse/kio/pcs/pcs_sock_io.c b/fs/fuse/kio/pcs/pcs_sock_io.c
index c43a0850dda4..c640c41f69db 100644
--- a/fs/fuse/kio/pcs/pcs_sock_io.c
+++ b/fs/fuse/kio/pcs/pcs_sock_io.c
@@ -151,7 +151,33 @@ static int do_send_one_seg(struct socket *sock, struct iov_iter *it, size_t left
 		len = iov_iter_get_pages(it, &page, size, 1, &offset);
 		BUG_ON(len <= 0);
 
-		ret = kernel_sendpage(sock, page, offset, len, flags);
+		/* XXX This is highly dubios place. The only thing which allows us to do
+		 * this is ref to iscsi_tcp_segment_map() which makes the same thing in  the same context.
+		 * Good thing is that it explains in comment why slab mem cannot
+		 * be sent to tcp: network send can coalesce neighbour slabs to single page fragment
+		 * and this wouldbe "triggers one of hardened usercopy checks" whatever it is.
+		 * The second condition page_count(page) >= 1 is still scary.
+		 * AFAIK such page cannot be even handled by get_page/put_page which
+		 * would mean that we come here with already corrupted page state.
+		 * In vz7 we dealt with this in maybe paranoid but obviously correct way:
+		 * iov_iter_get_pages checked sendpage_ok() _before_ making get_page and
+		 * failing iov_iter_get_pages otherwise. I would do the same thing now, but
+		 * I am afraid that current kernels are safe wrt get/put_page, but there is some
+		 * other reason to prohibit page_count(page) == 0 only for networking while
+		 * other components could be happy and would fail when we fail iov_iter_get_pages.
+		 * Well, everyone else does not worry, so that we cab go with this.
+		 * But still we need better justification, "everyone else" used to be stupid.
+		 */
+		if (sendpage_ok(page)) {
+			ret = kernel_sendpage(sock, page, offset, len, flags);
+		} else {
+			void * data = kmap(page);
+			struct msghdr msg = { .msg_flags = flags };
+			struct kvec iov = { .iov_base = data + offset, .iov_len = len };
+
+			ret = kernel_sendmsg(sock, &msg, &iov, 1, len);
+			kunmap(page);
+		}
 		put_page(page);
 	}
 
-- 
2.38.1

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to