From patchwork Wed Jun 14 10:09:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 107871 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp1139236vqr; Wed, 14 Jun 2023 03:32:18 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6585kdNi5JOlJwW8NyLSx2tuzZ1D8WW040rt3amZvKWFbnNo/ok3xwcnOKHOqG8+j/9feb X-Received: by 2002:a05:6a00:228e:b0:666:6b35:c909 with SMTP id f14-20020a056a00228e00b006666b35c909mr938866pfe.12.1686738738001; Wed, 14 Jun 2023 03:32:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1686738737; cv=none; d=google.com; s=arc-20160816; b=rIe3bTRSJbjD0rQ2dwGcNi/Ldm04dGan+VCZoURpSXZIL4ThKstKBTP/YXiBkClJHs D6/bhPBFScv+gEtba5Rnbg3UoiBdkmcZDx0H7I/Gep3LNRPVqGvDPBtvqSiiJy+jY7RP LdCBUOAS2ifxzUap1vQFUGp5eANunjiEnp2X9/+bdKfg2eCe2a2dMTsxL8r0ztqx2iBH +/iFhJwNqQ3f3/kwL2HfJj+XAq1VCU34Mb+Nnm1lmlgii6bw/7hAu1KqXW+RXvmIoN+k y5L8YRLCCtBcof3jQnUwAglGNOAqPjpW7QzPSf7ST3B9pLqJjScGGnbPWgsTYYL9fkPA ANTw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:date:content-transfer-encoding :content-id:mime-version:subject:cc:to:from:organization :dkim-signature; bh=MBrjoJbmEWc/Tn6Mkt7SpycUJkuHckypR5ks5lDPTJ8=; b=lwMdql4eDuFPYM630LhWQzOGMyEiYwElvxx1mkj/aPwm1EapReW2MFwMI7lRLZcqmf z+DAh7k8/xf+oUWLCTKMEw+F1RdxCw4qIyIGxGSQE1zAjN1zeMok1EgzoygxdczcgPLL sGT7JU6JymXY/p8Sg4awrl9Kk0I9oO5EYZWuY4UsbNJ3g6CiLMdKnB9vR56mPt9mRtp+ FO6xYmw80N2j6yYFJPAq5zkf2x1mcXPtk3d9rlZlVlz40ftssgOtft7rzoY1yh0CLX1V RC7OWgzDwQrSIJO8bOJYCq9ginp+3E9RUiF+/mzYGPk/pYQlhaCyDEnotOqprPHJ6emc Zw8w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=ETX4s1hu; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id b13-20020a63d80d000000b0053eefa04db9si10605508pgh.48.2023.06.14.03.32.05; Wed, 14 Jun 2023 03:32:17 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=ETX4s1hu; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234921AbjFNKKo (ORCPT + 99 others); Wed, 14 Jun 2023 06:10:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59938 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232060AbjFNKKm (ORCPT ); Wed, 14 Jun 2023 06:10:42 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4ED651B2 for ; Wed, 14 Jun 2023 03:09:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1686737394; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=MBrjoJbmEWc/Tn6Mkt7SpycUJkuHckypR5ks5lDPTJ8=; b=ETX4s1huZ3SOZStBIxcffweddGqeQ/kk6uTozwi4W1AOU4r/Fqg6ho+v7akOx46jUd/zPl +Tp8obL6ulxxSOD8QW+X5baSirU2DSij0K0y/vIwuKvFocLOkySLvZEz5CcdJRZn2iRi+d tknKD9Sa+FssEnZoZ29EQtVy+C/mKSA= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-567-DPX2FsP-PxqlW4E_Wy1R1w-1; Wed, 14 Jun 2023 06:09:53 -0400 X-MC-Unique: DPX2FsP-PxqlW4E_Wy1R1w-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 55518830EFD; Wed, 14 Jun 2023 10:09:52 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.42.28.67]) by smtp.corp.redhat.com (Postfix) with ESMTP id AEA7740C6F5D; Wed, 14 Jun 2023 10:09:49 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 From: David Howells To: netdev@vger.kernel.org cc: dhowells@redhat.com, syzbot+f9e28a23426ac3b24f20@syzkaller.appspotmail.com, Willem de Bruijn , David Ahern , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Jens Axboe , Matthew Wilcox , Christian Brauner , Alexander Viro , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next] splice, net: Fix splice_to_socket() to handle pipe bufs larger than a page MIME-Version: 1.0 Content-ID: <1428984.1686737388.1@warthog.procyon.org.uk> Date: Wed, 14 Jun 2023 11:09:48 +0100 Message-ID: <1428985.1686737388@warthog.procyon.org.uk> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_NONE,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1768673759046454131?= X-GMAIL-MSGID: =?utf-8?q?1768673759046454131?= splice_to_socket() assumes that a pipe_buffer won't hold more than a single page of data - but this assumption can be violated by skb_splice_bits() when it splices 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 by 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 Fixes: 2dc334f1a63a ("splice, net: Use sendmsg(MSG_SPLICE_PAGES) rather than ->sendpage()") Reported-by: syzbot+f9e28a23426ac3b24f20@syzkaller.appspotmail.com Link: https://lore.kernel.org/r/0000000000000900e905fdeb8e39@google.com/ Tested-by: syzbot+f9e28a23426ac3b24f20@syzkaller.appspotmail.com Signed-off-by: David Howells cc: Willem de Bruijn cc: David Ahern cc: "David S. Miller" cc: Eric Dumazet cc: Jakub Kicinski cc: Paolo Abeni cc: Jens Axboe cc: Matthew Wilcox cc: Christian Brauner cc: Alexander Viro cc: netdev@vger.kernel.org cc: linux-fsdevel@vger.kernel.org --- fs/splice.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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)