Received: by 2002:a6b:fb09:0:0:0:0:0 with SMTP id h9csp6053460iog; Thu, 23 Jun 2022 10:20:14 -0700 (PDT) X-Google-Smtp-Source: AGRyM1szUZMTtuvl5AnQpxnV5O9GaAjXJBqaTOxLxiNih4W1HHYskIZJA6sRg2Vw9n/qAuNilog/ X-Received: by 2002:a05:6402:3491:b0:435:8939:1989 with SMTP id v17-20020a056402349100b0043589391989mr12376945edc.23.1656004814072; Thu, 23 Jun 2022 10:20:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1656004814; cv=none; d=google.com; s=arc-20160816; b=bw59hiy6j+4E2Sc55POXB47TWbZOq0mX+Kip/HH3AQidBIETf8qIH61lpbjKiJNqh3 dL9Z9e78ugpY+k/9rnPF8HT4fcnawT23sU4yRt8hRkfIc/z36Ps6yeM8T2b0Ad30ZYDl 3xRlWc8KUVXL6fWQjcwl73IDvYkJpCURwkwW/l3WsXxMUj32MetdWGSU0ZY58boRHnUG uOQeZrN0J6Ja9ve0r5ZLN/6b5ZZNP0ZUr7jcaOj23+Xki1nhjAYej58Vl14UDszWrg69 2kbrXcGWonuFHiAMYaPbz3kD0N0ms4L8ytBLUHcrXN2TzAoHhVXH9BMRo0m2cIG1HvnJ QqAA== 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=O0mrcauqGk9Eb2Ohvy0+IYD/O3y0hyhwZqtN95ixK4s=; b=HfISwtR7KbpPo3k34VpJ8GrzyYM55ZnsF2XBqEFwuZLu7HAeOZ97ilWUTOKxsiGKcA 2sDClaNAqkgAYj8Hh0/+Vgiyqn2AMrMIkIGnvQMRj2RIU6GpyTJVSpG+0t1mP1n9sPvR e5eIfYQrkbd/mYi7NbBfYrbtHJpTGhEY6nUbRQs5vsRLI+HNkpuZjS13Ie8cYb6or3sV /uGsVwKX2IMRixboCFvhgLw5JCqVc5Gd8+MCEyGVlMC52pC4pbrAXsGkrEycZbkj1T7l 4rbLo6swG/Xb/Z14FDK25een1lVHKjkertDynn1uY0feiqJpYyWpjEgbQ+UAngiUrS1S MIbw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Q9ZKw9hV; 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 i15-20020a1709067a4f00b0070cb60f5168si1060436ejo.843.2022.06.23.10.19.47; Thu, 23 Jun 2022 10:20:14 -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=Q9ZKw9hV; 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 S232218AbiFWRP5 (ORCPT + 99 others); Thu, 23 Jun 2022 13:15:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39074 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233264AbiFWRMn (ORCPT ); Thu, 23 Jun 2022 13:12:43 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4ECEB4EA11; Thu, 23 Jun 2022 09:58:18 -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 dfw.source.kernel.org (Postfix) with ESMTPS id DA0AE60AD7; Thu, 23 Jun 2022 16:58:17 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B2AE0C341C6; Thu, 23 Jun 2022 16:58:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1656003497; bh=qOxbimxBQ+BB2CE/6f3pBmDmBtSD3l6gkMENxniCBQE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Q9ZKw9hVjkwi4cU40zEZRE2bYkTgc6fldWY05QSRWUBeL/i0hgJZ0+CHr33NHt3K6 ur9ae/QlFItQIY/iY5a9CcvgGQx76LUiWLeZlBBrPGmp6Xx4Uy4npTQw24Xx8GEIjk sva4aj6v0QzocJqcpeXOAsMzd3GnVSKkrCL6gjQ4= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jann Horn , Miklos Szeredi , Zach OKeefe , Ben Hutchings Subject: [PATCH 4.9 256/264] fuse: fix pipe buffer lifetime for direct_io Date: Thu, 23 Jun 2022 18:44:09 +0200 Message-Id: <20220623164351.308519608@linuxfoundation.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220623164344.053938039@linuxfoundation.org> References: <20220623164344.053938039@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 Signed-off-by: Ben Hutchings 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 @@ -992,7 +992,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 @@ -1319,6 +1319,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 @@ -310,6 +310,8 @@ struct fuse_req { /** refcount */ atomic_t count; + bool user_pages; + /** Unique ID for the interrupt request */ u64 intr_unique;