All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg KH <greg@kroah.com>
To: Sasha Levin <sashal@kernel.org>
Cc: stable@vger.kernel.org, Miklos Szeredi <mszeredi@redhat.com>
Subject: Re: [PATCH 6.18.y 1/4] fuse: abort related layering cleanup
Date: Wed, 9 Sep 2026 14:33:20 +0200	[thread overview]
Message-ID: <2026090913-courier-static-e571@gregkh> (raw)
In-Reply-To: <20260831164256.270090-1-sashal@kernel.org>

On Mon, Aug 31, 2026 at 12:42:53PM -0400, Sasha Levin wrote:
> From: Miklos Szeredi <mszeredi@redhat.com>
> 
> [ Upstream commit 4eeb5e6cb0fd89b343fcf755ae3aad76fdb5b2c2 ]
> 
>  - rename fuse_abort_conn() to fuse_chan_abort(), pass fuse_chan pointer
>    instead of fuse_conn
> 
>  - pass an abort_with_err argument that tells fuse_dev_(read|write) to
>    return with ECONNABORTED instead of ENODEV
> 
>  - move fc->aborted to fch->abort_with_err
> 
>  - rename fuse_wait_aborted() to fuse_chan_wait_aborted()
> 
> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
> 
> [ 6.18 has no "struct fuse_chan" -- the connection object still plays
>   that role, and the surrounding series that splits it out is not in
>   stable.  Adapted as follows:
> 
>   - the renames (fuse_abort_conn() -> fuse_chan_abort(),
>     fuse_wait_aborted() -> fuse_chan_wait_aborted(), the "abort_conn"
>     label in fuse_check_timeout() -> "chan_abort") and the new
>     abort_with_err argument are taken as-is, but both helpers keep
>     taking "struct fuse_conn *".
> 
>   - the "move fc->aborted to fch->abort_with_err" bullet is dropped:
>     there is no fuse_chan to move the flag into, so fc->aborted stays
>     in struct fuse_conn.  fuse_chan_abort() only ever *sets* it, as
>     control.c did before, rather than assigning the new argument
>     unconditionally the way upstream does: on this tree the flag is
>     write-once and is what makes fuse_dev_do_read() and
>     fuse_uring_cmd() report ECONNABORTED instead of ENODEV, so letting
>     a later abort with abort_with_err=false clear it (umount -f,
>     fuse_conn_destroy(), fuse_dev_release(), the timeout worker) would
>     change what userspace sees after a sysfs abort on an abort_err
>     mount.  Consequently the fuse_dev_i.h and dev_uring.c hunks, which
>     only rename the field access, are dropped as well.
> 
>   - fs/fuse/dev.h and fs/fuse/req_timeout.c do not exist here: the
>     declarations stay in fuse_i.h and fuse_check_timeout() lives in
>     dev.c, so those two hunks were replayed there.
> 
>   - in request_wait_answer() the connection pointer is named "fch",
>     matching the name upstream gives it in 28d733cc3ecad ("fuse: change
>     req->fm to req->chan"), so that the follow-up fix applies here
>     unchanged. ]
> 
> [ sashal: Reduced backport -- upstream 4eeb5e6cb0fd8 touches 9 file(s), this
>   backport carries 5. Not backported here:
>   fs/fuse/dev.h
>   fs/fuse/dev_uring.c
>   fs/fuse/fuse_dev_i.h
>   fs/fuse/req_timeout.c
>   This note is generated from the file lists only; see the resolution record
>   for the reasoning. ]
> 
> Stable-dep-of: 64b0b5cacbd2 ("fuse: wait for FR_FINISHED on abort_on_kill to prevent use-after-free")
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> ---
>  fs/fuse/control.c |  4 +---
>  fs/fuse/cuse.c    |  4 ++--
>  fs/fuse/dev.c     | 35 +++++++++++++++++++----------------
>  fs/fuse/fuse_i.h  |  4 ++--
>  fs/fuse/inode.c   |  6 +++---
>  5 files changed, 27 insertions(+), 26 deletions(-)
> 
> diff --git a/fs/fuse/control.c b/fs/fuse/control.c
> index 2e300f6d646c3..5536d6ee65514 100644
> --- a/fs/fuse/control.c
> +++ b/fs/fuse/control.c
> @@ -37,9 +37,7 @@ static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
>  {
>  	struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
>  	if (fc) {
> -		if (fc->abort_err)
> -			fc->aborted = true;
> -		fuse_abort_conn(fc);
> +		fuse_chan_abort(fc, fc->abort_err);
>  		fuse_conn_put(fc);
>  	}
>  	return count;
> diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
> index 2bb98bf81b079..d90f138321fe9 100644
> --- a/fs/fuse/cuse.c
> +++ b/fs/fuse/cuse.c
> @@ -425,7 +425,7 @@ static void cuse_process_init_reply(struct fuse_mount *fm,
>  err_region:
>  	unregister_chrdev_region(devt, 1);
>  err:
> -	fuse_abort_conn(fc);
> +	fuse_chan_abort(fc, false);
>  	goto out;
>  }
>  
> @@ -593,7 +593,7 @@ static ssize_t cuse_class_abort_store(struct device *dev,
>  {
>  	struct cuse_conn *cc = dev_get_drvdata(dev);
>  
> -	fuse_abort_conn(&cc->fc);
> +	fuse_chan_abort(&cc->fc, false);
>  	return count;
>  }
>  static DEVICE_ATTR(abort, 0200, NULL, cuse_class_abort_store);
> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
> index 77c3982bca3d7..934f9ac5056ed 100644
> --- a/fs/fuse/dev.c
> +++ b/fs/fuse/dev.c
> @@ -87,13 +87,13 @@ void fuse_check_timeout(struct work_struct *work)
>  	expired = fuse_request_expired(fc, &fiq->pending);
>  	spin_unlock(&fiq->lock);
>  	if (expired)
> -		goto abort_conn;
> +		goto chan_abort;
>  
>  	spin_lock(&fc->bg_lock);
>  	expired = fuse_request_expired(fc, &fc->bg_queue);
>  	spin_unlock(&fc->bg_lock);
>  	if (expired)
> -		goto abort_conn;
> +		goto chan_abort;
>  
>  	spin_lock(&fc->lock);
>  	if (!fc->connected) {
> @@ -107,7 +107,7 @@ void fuse_check_timeout(struct work_struct *work)
>  		    fuse_fpq_processing_expired(fc, fpq->processing)) {
>  			spin_unlock(&fpq->lock);
>  			spin_unlock(&fc->lock);
> -			goto abort_conn;
> +			goto chan_abort;
>  		}
>  
>  		spin_unlock(&fpq->lock);
> @@ -115,15 +115,15 @@ void fuse_check_timeout(struct work_struct *work)
>  	spin_unlock(&fc->lock);
>  
>  	if (fuse_uring_request_expired(fc))
> -	    goto abort_conn;
> +	    goto chan_abort;
>  
>  out:
>  	queue_delayed_work(system_percpu_wq, &fc->timeout.work,
>  			   fuse_timeout_timer_freq);
>  	return;
>  
> -abort_conn:
> -	fuse_abort_conn(fc);
> +chan_abort:
> +	fuse_chan_abort(fc, false);
>  }
>  
>  static void fuse_request_init(struct fuse_mount *fm, struct fuse_req *req)
> @@ -180,7 +180,7 @@ static void fuse_drop_waiting(struct fuse_conn *fc)
>  {
>  	/*
>  	 * lockess check of fc->connected is okay, because atomic_dec_and_test()
> -	 * provides a memory barrier matched with the one in fuse_wait_aborted()
> +	 * provides a memory barrier matched with the one in fuse_chan_wait_aborted()
>  	 * to ensure no wake-up is missed.
>  	 */
>  	if (atomic_dec_and_test(&fc->num_waiting) &&
> @@ -551,11 +551,11 @@ bool fuse_remove_pending_req(struct fuse_req *req, spinlock_t *lock)
>  
>  static void request_wait_answer(struct fuse_req *req)
>  {
> -	struct fuse_conn *fc = req->fm->fc;
> -	struct fuse_iqueue *fiq = &fc->iq;
> +	struct fuse_conn *fch = req->fm->fc;
> +	struct fuse_iqueue *fiq = &fch->iq;
>  	int err;
>  
> -	if (!fc->no_interrupt) {
> +	if (!fch->no_interrupt) {
>  		/* Any signal may interrupt this */
>  		err = wait_event_interruptible(req->waitq,
>  					test_bit(FR_FINISHED, &req->flags));
> @@ -579,7 +579,7 @@ static void request_wait_answer(struct fuse_req *req)
>  			return;
>  
>  		if (req->args->abort_on_kill) {
> -			fuse_abort_conn(fc);
> +			fuse_chan_abort(fch, false);
>  			return;
>  		}
>  
> @@ -1491,7 +1491,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
>  	spin_lock(&fpq->lock);
>  	/*
>  	 *  Must not put request on fpq->io queue after having been shut down by
> -	 *  fuse_abort_conn()
> +	 *  fuse_chan_abort()
>  	 */
>  	if (!fpq->connected) {
>  		req->out.h.error = err = -ECONNABORTED;
> @@ -2475,10 +2475,13 @@ static void end_polls(struct fuse_conn *fc)
>   * is OK, the request will in that case be removed from the list before we touch
>   * it.
>   */
> -void fuse_abort_conn(struct fuse_conn *fc)
> +void fuse_chan_abort(struct fuse_conn *fc, bool abort_with_err)
>  {
>  	struct fuse_iqueue *fiq = &fc->iq;
>  
> +	if (abort_with_err)
> +		fc->aborted = true;
> +
>  	spin_lock(&fc->lock);
>  	if (fc->connected) {
>  		struct fuse_dev *fud;
> @@ -2547,9 +2550,9 @@ void fuse_abort_conn(struct fuse_conn *fc)
>  		spin_unlock(&fc->lock);
>  	}
>  }
> -EXPORT_SYMBOL_GPL(fuse_abort_conn);
> +EXPORT_SYMBOL_GPL(fuse_chan_abort);
>  
> -void fuse_wait_aborted(struct fuse_conn *fc)
> +void fuse_chan_wait_aborted(struct fuse_conn *fc)
>  {
>  	/* matches implicit memory barrier in fuse_drop_waiting() */
>  	smp_mb();
> @@ -2579,7 +2582,7 @@ int fuse_dev_release(struct inode *inode, struct file *file)
>  		/* Are we the last open device? */
>  		if (atomic_dec_and_test(&fc->dev_count)) {
>  			WARN_ON(fc->iq.fasync != NULL);
> -			fuse_abort_conn(fc);
> +			fuse_chan_abort(fc, false);
>  		}
>  		fuse_dev_free(fud);
>  	}
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index c288f28f6c6ea..8b745045f1ab3 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -1272,8 +1272,8 @@ void fuse_request_assign_unique(struct fuse_iqueue *fiq, struct fuse_req *req);
>  void fuse_request_end(struct fuse_req *req);
>  
>  /* Abort all requests */
> -void fuse_abort_conn(struct fuse_conn *fc);
> -void fuse_wait_aborted(struct fuse_conn *fc);
> +void fuse_chan_abort(struct fuse_conn *fc, bool abort_with_err);
> +void fuse_chan_wait_aborted(struct fuse_conn *fc);
>  
>  /* Check if any requests timed out */
>  void fuse_check_timeout(struct work_struct *work);
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index e9ed693fc7b37..399298816dea0 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -621,7 +621,7 @@ static void fuse_umount_begin(struct super_block *sb)
>  	if (fc->no_force_umount)
>  		return;
>  
> -	fuse_abort_conn(fc);
> +	fuse_chan_abort(fc, false);
>  
>  	// Only retire block-device-based superblocks.
>  	if (sb->s_bdev != NULL)
> @@ -2099,8 +2099,8 @@ void fuse_conn_destroy(struct fuse_mount *fm)
>  	if (fc->destroy)
>  		fuse_send_destroy(fm);
>  
> -	fuse_abort_conn(fc);
> -	fuse_wait_aborted(fc);
> +	fuse_chan_abort(fc, false);
> +	fuse_chan_wait_aborted(fc);
>  
>  	if (!list_empty(&fc->entry)) {
>  		mutex_lock(&fuse_mutex);
> -- 
> 2.53.0
> 
> 

Series did not apply :(

      parent reply	other threads:[~2026-09-09 12:34 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-31 12:23 FAILED: patch "[PATCH] fuse: wait for FR_FINISHED on abort_on_kill to prevent" failed to apply to 6.18-stable tree gregkh
2026-08-31 16:42 ` [PATCH 6.18.y 1/4] fuse: abort related layering cleanup Sasha Levin
2026-08-31 16:42   ` [PATCH 6.18.y 2/4] fuse: split off fuse_args and related definitions into a separate header Sasha Levin
2026-08-31 16:42   ` [PATCH 6.18.y 3/4] fuse: remove fm arg of args->end callback Sasha Levin
2026-08-31 16:42   ` [PATCH 6.18.y 4/4] fuse: wait for FR_FINISHED on abort_on_kill to prevent use-after-free Sasha Levin
2026-09-09 12:33   ` Greg KH [this message]

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=2026090913-courier-static-e571@gregkh \
    --to=greg@kroah.com \
    --cc=mszeredi@redhat.com \
    --cc=sashal@kernel.org \
    --cc=stable@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.