Received: by 2002:a05:6a10:6d10:0:0:0:0 with SMTP id gq16csp4295395pxb; Tue, 19 Apr 2022 23:16:51 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwX8zKSVtXNVeEfVpJs8HQRhpOMkMlIX1mQlJ4jxKCijPNoZxGywaS3b9ghQ7iTDAbE0RhV X-Received: by 2002:a05:6402:418:b0:423:d3e8:b77 with SMTP id q24-20020a056402041800b00423d3e80b77mr19573642edv.267.1650435411565; Tue, 19 Apr 2022 23:16:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1650435411; cv=none; d=google.com; s=arc-20160816; b=I1loJMHrQRjG5vsMScx/0Z5v1sMSm/yu1DXVByrTnhjGEdrvHuuyJjhtfT8t+Xhdk2 q1roDb8kjVvbxCMX5KvKCsh+O7pXlpRjoZovFHCT73gagIAElBDVeLFsNYKL+2X/oaO0 4l8StXqcMlxnxhfBo2c29UQtU+TzVs+xnJ+aX3WgAr35Jo5p6BaVnRJP77YoIdmrKt2B mXUoNALtc2iA9K8UasQWxjfoqn4wVK56Qdg02o3kRSE0w/DlAJOYsC3d5T+NBrd9I+sk HTIeoonuhDgtKY5wU6V/4AMGBeZH4J9wz6dqFrvg1TkyXtGS+R4yzEzoXkcY/+dYMLQP ayAw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=GLOya39ukogRdLj5Cp3gJSatewLKjG/h8vTinFirWT0=; b=dOKPNGo+WIQhV4VslivSkyGkpZ/BkGhxardNoLlCN0XzG8tKz9wTW9fQuKHfiVx2jm mLWGOAxD5ASQtsaGfWnrdYKCgz7gbJOGxoczus8QS4o21VmNHRVuQRH+Fb26E21A45z/ 9Ob9/eUYEnjTD4WcxD0wx7rk3zPQqSG3x06LHMfbBACnT+2vg7huaaMaMu2/NX3XtlQj kP+SJcnvWti124b7xlxtQIRJoNmdef7GkSeDNPcR+HFKPX4c7ypWTHtTB+WZAqK7+JGg riuwR5DuSax6gcSSpnNTNGGzoAir3HVtXRbwWTcJac0MzHPxUl+VytV9/SiThMn6BvtV F2uA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=TQb8FyAG; 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=linuxfoundation.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id s7-20020a056402520700b00418c2b5befdsi824154edd.479.2022.04.19.23.16.28; Tue, 19 Apr 2022 23:16:51 -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=@linuxfoundation.org header.s=korg header.b=TQb8FyAG; 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=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243070AbiDRNkj (ORCPT + 99 others); Mon, 18 Apr 2022 09:40:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53684 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243010AbiDRNJq (ORCPT ); Mon, 18 Apr 2022 09:09:46 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5E3B0369E7; Mon, 18 Apr 2022 05:49:13 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 8B3B1B80EC3; Mon, 18 Apr 2022 12:49:08 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D9F5FC385A8; Mon, 18 Apr 2022 12:49:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1650286147; bh=z+MJ5BwcFYCOls5GqHWIzpBRgYQfepqqFTN/5M0j8+Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TQb8FyAGGxhP57sRA4LtmvnxKVfR10mKocN0+fr+dXDypo6iASRN6RfKeHXI1jIWu mmnQjYunUkaVDW8xHo0eMNE3Px0aG1XWR306cH07PTTl+qjJOTkv/jlLwA2pMSRqMH SRGKfnHyRHa9NBV8BHvU1nTFnFs11/DbJpTollXY= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jann Horn , Miklos Szeredi , Zach OKeefe Subject: [PATCH 4.14 009/284] fuse: fix pipe buffer lifetime for direct_io Date: Mon, 18 Apr 2022 14:09:50 +0200 Message-Id: <20220418121210.961307913@linuxfoundation.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418121210.689577360@linuxfoundation.org> References: <20220418121210.689577360@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS,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 From: Miklos Szeredi commit 0c4bcfdecb1ac0967619ee7ff44871d93c08c909 upstream. In FOPEN_DIRECT_IO mode, fuse_file_write_iter() calls fuse_direct_write_iter(), which normally calls fuse_direct_io(), which then imports the write buffer with fuse_get_user_pages(), which uses iov_iter_get_pages() to grab references to userspace pages instead of actually copying memory. On the filesystem device side, these pages can then either be read to userspace (via fuse_dev_read()), or splice()d over into a pipe using fuse_dev_splice_read() as pipe buffers with &nosteal_pipe_buf_ops. This is wrong because after fuse_dev_do_read() unlocks the FUSE request, the userspace filesystem can mark the request as completed, causing write() to return. At that point, the userspace filesystem should no longer have access to the pipe buffer. Fix by copying pages coming from the user address space to new pipe buffers. Reported-by: Jann Horn Fixes: c3021629a0d8 ("fuse: support splice() reading from fuse device") Cc: Signed-off-by: Miklos Szeredi Signed-off-by: Zach O'Keefe Signed-off-by: Greg Kroah-Hartman --- fs/fuse/dev.c | 12 +++++++++++- fs/fuse/file.c | 1 + fs/fuse/fuse_i.h | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -991,7 +991,17 @@ static int fuse_copy_page(struct fuse_co while (count) { if (cs->write && cs->pipebufs && page) { - return fuse_ref_page(cs, page, offset, count); + /* + * Can't control lifetime of pipe buffers, so always + * copy user pages. + */ + if (cs->req->user_pages) { + err = fuse_copy_fill(cs); + if (err) + return err; + } else { + return fuse_ref_page(cs, page, offset, count); + } } else if (!cs->len) { if (cs->move_pages && page && offset == 0 && count == PAGE_SIZE) { --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1325,6 +1325,7 @@ static int fuse_get_user_pages(struct fu (PAGE_SIZE - ret) & (PAGE_SIZE - 1); } + req->user_pages = true; if (write) req->in.argpages = 1; else --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -312,6 +312,8 @@ struct fuse_req { /** refcount */ refcount_t count; + bool user_pages; + /** Unique ID for the interrupt request */ u64 intr_unique;