Received: by 2002:a05:6358:3188:b0:123:57c1:9b43 with SMTP id q8csp2470618rwd; Wed, 14 Jun 2023 03:22:55 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ7yZWS7J+8Hs5Rhj5300y9giUMiNWa9GdvPeKfgKHL/okxJZ2X4nF+FbLZlgYH+sLC+QGjX X-Received: by 2002:a05:6808:e87:b0:39a:522c:55c1 with SMTP id k7-20020a0568080e8700b0039a522c55c1mr9679148oil.8.1686738175614; Wed, 14 Jun 2023 03:22:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1686738175; cv=none; d=google.com; s=arc-20160816; b=dX9aYzj3FcvHgrqm5YqMbBl+1dnL2eqTRPo8QLJypG+spY66zkSb6P4FualViGBIdo /73fFoBal2nUx+MDnl8UrJ5dfPn0jgdXY7e5hQ9jS8fPANcM7UeLvs3oQGB8GGklTH9C M1CHnmFoam2p+Mw7F9L0ptn9ki3F7y4FqD+35LQf3zBRm/erIBLDUi2fVJqqdxJp5em4 jmOudz5oT/nAia0NTkJUSz9Ggc9vWHJSY/MHr0TIDQcz1B3aP5PfETJiQiOAWp8tKs5v hrHOYLwEZUsPmlY8y+geaBmFnfUCwy+B0ctWugE3uMxQ/sysY0lROk3fRkw6C/7A6MLU pqmQ== 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 Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id 16-20020a17090a1a1000b002565045f145si12247543pjk.122.2023.06.14.03.22.42; Wed, 14 Jun 2023 03:22:55 -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 S234587AbjFNKKo (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-Type: text/plain; charset="us-ascii" Content-ID: <1428984.1686737388.1@warthog.procyon.org.uk> Content-Transfer-Encoding: quoted-printable 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 = splice_to_socket() assumes that a pipe_buffer won't hold more than a singl= e 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 i= f 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 bu= f 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 0xdffffc00000= 00001: 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 th= an ->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 =3D min_t(size_t, remain, buf->len); - seg =3D min_t(size_t, seg, PAGE_SIZE); = ret =3D 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 -=3D seg; - if (seg >=3D buf->len) - tail++; - if (bc >=3D ARRAY_SIZE(bvec)) + if (remain =3D=3D 0 || bc >=3D ARRAY_SIZE(bvec)) break; + tail++; } = if (!bc)