public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: syzbot <syzbot+f9e28a23426ac3b24f20@syzkaller.appspotmail.com>
Cc: dhowells@redhat.com, brauner@kernel.org, kuba@kernel.org,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	netdev@vger.kernel.org, syzkaller-bugs@googlegroups.com,
	viro@zeniv.linux.org.uk
Subject: Re: [syzbot] [fs?] general protection fault in splice_to_socket
Date: Wed, 14 Jun 2023 10:00:30 +0100	[thread overview]
Message-ID: <1423848.1686733230@warthog.procyon.org.uk> (raw)
In-Reply-To: <0000000000000900e905fdeb8e39@google.com>

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git main

commit d302bc9baf84c549891bedee57ee917d9e0485d7
Author: David Howells <dhowells@redhat.com>
Date:   Wed Jun 14 09:14:50 2023 +0100

    splice: Fix splice_to_socket() to handle pipe bufs larger than a page
    
    splice_to_socket() assumes that a pipe_buffer won't hold more than a single
    page of data - but it seems that this assumption can be violated when
    splicing from a socket into a pipe.
    
    The problem is that splice_to_socket() doesn't advance the pipe_buffer
    length and offset when transcribing from the pipe buf into a bio_vec, so if
    the buf is >PAGE_SIZE, it keeps repeating the same initial chunk and
    doesn't advance the tail index.  It then subtracts this from "remain" and
    overcounts the amount of data to be sent.
    
    The cleanup phase then tries to overclean the pipe, hits an unused pipe buf
    and a NULL-pointer dereference occurs.
    
    Fix this by not restricting the bio_vec size to PAGE_SIZE and instead
    transcribing the entirety of each pipe_buffer into a single bio_vec and
    advancing the tail index if remain hasn't hit zero yet.
    
    Large bio_vecs will then be split up iterator functions such as
    iov_iter_extract_pages().
    
    This resulted in a KASAN report looking like:
    
    general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] PREEMPT SMP KASAN
    KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
    ...
    RIP: 0010:pipe_buf_release include/linux/pipe_fs_i.h:203 [inline]
    RIP: 0010:splice_to_socket+0xa91/0xe30 fs/splice.c:933
    
    Reported-by: syzbot+f9e28a23426ac3b24f20@syzkaller.appspotmail.com
    Fixes: 2dc334f1a63a ("splice, net: Use sendmsg(MSG_SPLICE_PAGES) rather than ->sendpage()")
    
    Signed-off-by: David Howells <dhowells@redhat.com>
    cc: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
    cc: David Ahern <dsahern@kernel.org>
    cc: "David S. Miller" <davem@davemloft.net>
    cc: Eric Dumazet <edumazet@google.com>
    cc: Jakub Kicinski <kuba@kernel.org>
    cc: Paolo Abeni <pabeni@redhat.com>
    cc: Jens Axboe <axboe@kernel.dk>
    cc: Matthew Wilcox <willy@infradead.org>
    cc: Christian Brauner <brauner@kernel.org>
    cc: Alexander Viro <viro@zeniv.linux.org.uk>
    cc: netdev@vger.kernel.org
    cc: linux-fsdevel@vger.kernel.org

diff --git a/fs/splice.c b/fs/splice.c
index e337630aed64..567a1f03ea1e 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -886,7 +886,6 @@ ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out,
 			}
 
 			seg = min_t(size_t, remain, buf->len);
-			seg = min_t(size_t, seg, PAGE_SIZE);
 
 			ret = pipe_buf_confirm(pipe, buf);
 			if (unlikely(ret)) {
@@ -897,10 +896,9 @@ ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out,
 
 			bvec_set_page(&bvec[bc++], buf->page, seg, buf->offset);
 			remain -= seg;
-			if (seg >= buf->len)
-				tail++;
-			if (bc >= ARRAY_SIZE(bvec))
+			if (remain == 0 || bc >= ARRAY_SIZE(bvec))
 				break;
+			tail++;
 		}
 
 		if (!bc)


  parent reply	other threads:[~2023-06-14  9:01 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-12  9:43 [syzbot] [fs?] general protection fault in splice_to_socket syzbot
2023-06-14  8:57 ` David Howells
2023-06-14  9:00 ` David Howells [this message]
2023-06-14 10:02   ` syzbot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1423848.1686733230@warthog.procyon.org.uk \
    --to=dhowells@redhat.com \
    --cc=brauner@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=syzbot+f9e28a23426ac3b24f20@syzkaller.appspotmail.com \
    --cc=syzkaller-bugs@googlegroups.com \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox