mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: dhowells@redhat.com
Cc: netdev@vger.kernel.org, marc.dionne@auristor.com,
	kuba@kernel.org, davem@davemloft.net, edumazet@google.com,
	pabeni@redhat.com, horms@kernel.org,
	linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH net v10 13/14] afs: Fix uncleared op->call pointer
Date: Tue, 15 Sep 2026 22:57:45 +0000	[thread overview]
Message-ID: <178951306557.22033.18218417627125166965@kernel.org> (raw)
In-Reply-To: <20260914151340.3227501-14-dhowells@redhat.com>

Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:

Critical: 0 · High: 0 (2) · Medium: 1 · Low: 0

- [Medium] The Fixes: tag is too narrow.

Pre-existing issues:
- [High] The asynchronous fileserver-rotation peer of the loop fixed here
  does not handle the 'issue helper returned without creating a call'…
- [High] An RPC that was never issued because of an allocation failure is
  reported to userspace as a successful operation.

--

afs: Fix uncleared op->call pointer

This adds op->call = NULL after the afs_put_call() in
afs_wait_for_operation(), so that a subsequent fileserver rotation
iteration cannot observe a pointer to a call that has already been put.

Link: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260907113743.1453210-1-dhowells%40redhat.com

A couple of questions about the Fixes: tag and the changelog wording, and
two observations about neighbouring paths that the new op->call = NULL
interacts with.

> Fixes: 6f2ff7e89bd0 ("afs: Don't put afs_call in afs_wait_for_call_to_complete()")

[Severity: Medium]
Is this tag scoped correctly?  6f2ff7e89bd0 moved the afs_put_call() out of
afs_wait_for_call_to_complete() and into afs_wait_for_operation(), but the
stale op->call looks like it predates that move.

At 6f2ff7e89bd0^ the loop in afs_wait_for_operation() reads:

	if (op->call)
		op->error = afs_wait_for_call_to_complete(op->call, &op->ac);

and the tail of afs_wait_for_call_to_complete() that the blamed commit
removed was:

out:
	_debug("call complete");
	afs_put_call(call);

so the call was already freed with op->call left pointing at it, and
git grep 'op->call =' at that revision finds only the assignment in
afs_make_op_call().  Since the tag names a v6.7-era commit, would the
older stable trees be skipped by the backport tooling while carrying the
same stale pointer?

> Fix uncleared op->call pointer in afs_wait_for_operation() lest server
> rotation occur and try to reuse the call.

Could the changelog say what the reuse actually is?  On a later rotation
iteration where the issue helper bails out through afs_op_nomem() without
assigning op->call, the stale pointer is handed to
afs_wait_for_call_to_complete() and afs_put_call() a second time, i.e. a
use-after-free of a freed afs_call rather than just a "reuse".

> diff --git a/fs/afs/fs_operation.c b/fs/afs/fs_operation.c
> index 20801b29521d1..94fa65548d712 100644
> --- a/fs/afs/fs_operation.c
> +++ b/fs/afs/fs_operation.c
> @@ -297,6 +297,7 @@ void afs_wait_for_operation(struct afs_operation *op)
>  			op->call_error = op->call->error;
>  			op->call_responded = op->call->responded;
>  			afs_put_call(op->call);
> +			op->call = NULL;
>  		}
>  	}

[Severity: High]
This is a pre-existing issue and not introduced by the patch, but with
op->call now guaranteed to be NULL at the top of every iteration, what
happens to an -ENOMEM from the issue helper?

Each iteration of the loop starts by clearing the per-call state:

		op->call_responded = false;
		op->call_error = 0;
		op->call_abort_code = 0;

and the issue helpers bail out on allocation failure with:

	call = afs_alloc_flat_call(op->net, &afs_RXFSFetchData, ...);
	if (!call)
		return afs_op_nomem(op);

while afs_op_nomem() in fs/afs/internal.h only records:

static inline void afs_op_nomem(struct afs_operation *op)
{
	op->cumul_error.error = -ENOMEM;
}

With op->call NULL the completion block above is skipped, so op->call_error
stays 0 and AFS_OPERATION_STOP is not set.  afs_select_fileserver() then
evaluates the previous "result":

	int error = op->call_error, ...
	switch (op->call_error) {
	case 0:
		...
		error = afs_update_volume_state(op);
		...
		fallthrough;
	default:
		/* Success or local failure.  Stop. */
		afs_op_set_error(op, error);

and afs_op_set_error() assigns unconditionally:

static inline int afs_op_set_error(struct afs_operation *op, int error)
{
	return op->cumul_error.error = error;
}

Does that erase the recorded -ENOMEM, so afs_wait_for_operation() takes the
!afs_op_error(op) branch and runs op->ops->success(op) on an afs_status_cb
that was never filled in?  For a store that reaches
afs_store_data_success():

	if (!afs_op_error(op)) {
		afs_pages_written_back(vnode, op->store.pos, op->store.size);

which would mark the pages written back and return success from write(2)
although no FS.StoreData was ever sent.  For create/mkdir, would
->success() and ->edit_dir() instantiate an inode and a directory entry
from a zeroed status and fid?

[Severity: High]
This isn't a bug introduced by this patch either, but the asynchronous peer
of this loop has no equivalent of the "no call was created" handling that
the if (op->call) test provides here.

In afs_issue_read() the async branch is:

		if (!afs_select_fileserver(op)) {
			afs_end_read(op);
			return;
		}

		afs_issue_read_call(op);

and afs_issue_read_call() returns void without inspecting op->call or
op->cumul_error:

static void afs_issue_read_call(struct afs_operation *op)
{
	op->call_responded = false;
	op->call_error = 0;
	op->call_abort_code = 0;
	if (test_bit(AFS_SERVER_FL_IS_YFS, &op->server->flags))
		yfs_fs_fetch_data(op);
	else
		afs_fs_fetch_data(op);
}

If afs_alloc_flat_call() fails in afs_fs_fetch_data()/yfs_fs_fetch_data(),
afs_make_op_call() is never reached, so op->call stays NULL and no rxrpc
call exists.  All the async completion work hangs off an existing call via
afs_fetch_data_async_rx() -> afs_read_receive() -> afs_end_read() ->
afs_fetch_data_notify() -> netfs_read_subreq_terminated().

Does that leave the netfs_io_subrequest unterminated for readahead and iocb
reads, with afs_put_operation() never called and the operation's
key/volume/server_list references leaked?

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260914151340.3227501-1-dhowells%40redhat.com

  reply	other threads:[~2026-09-15 22:57 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-14 15:13 [PATCH net v10 00/14] rxrpc: Miscellaneous fixes David Howells
2026-09-14 15:13 ` [PATCH net v10 01/14] rxrpc: Fix lack of short-send handling in rxrpc_kernel_send_data() David Howells
2026-09-14 21:11   ` David Laight
2026-09-15 13:36   ` Paolo Abeni
2026-09-15 22:57   ` netdev-bot+sashiko
2026-09-14 15:13 ` [PATCH net v10 02/14] afs: Fix afs to abort the rxrpc call on send error David Howells
2026-09-14 15:13 ` [PATCH net v10 03/14] rxrpc: Fix aborting in rxperf test server David Howells
2026-09-15 22:57   ` netdev-bot+sashiko
2026-09-14 15:13 ` [PATCH net v10 04/14] rxrpc: Fix sendmsg length David Howells
2026-09-14 15:13 ` [PATCH net v10 05/14] rxrpc: Fix update of call->tx_pending without holding lock David Howells
2026-09-15 22:57   ` netdev-bot+sashiko
2026-09-14 15:13 ` [PATCH net v10 06/14] rxrpc: Fix error handling in rxrpc_send_data() David Howells
2026-09-15 22:57   ` netdev-bot+sashiko
2026-09-14 15:13 ` [PATCH net v10 07/14] rxrpc: Fix packet encryption error handling David Howells
2026-09-15 22:57   ` netdev-bot+sashiko
2026-09-14 15:13 ` [PATCH net v10 08/14] rxrpc: Fix double IRQ enablement David Howells
2026-09-14 15:13 ` [PATCH net v10 09/14] rxrpc: Fix generation of notifications after call completion David Howells
2026-09-15 22:57   ` netdev-bot+sashiko
2026-09-14 15:13 ` [PATCH net v10 10/14] rxrpc: Fix RxGK key parser to check enctype is supported David Howells
2026-09-15 22:57   ` netdev-bot+sashiko
2026-09-14 15:13 ` [PATCH net v10 11/14] afs: Fix creation of RxGK CM channel token to have right size David Howells
2026-09-15 22:57   ` netdev-bot+sashiko
2026-09-14 15:13 ` [PATCH net v10 12/14] afs: Fix lack of setting call->server when doing FS.InlineBulkStatus David Howells
2026-09-14 15:13 ` [PATCH net v10 13/14] afs: Fix uncleared op->call pointer David Howells
2026-09-15 22:57   ` netdev-bot+sashiko [this message]
2026-09-14 15:13 ` [PATCH net v10 14/14] rxrpc: fix use-after-free in rxrpc_poke_conn() David Howells

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=178951306557.22033.18218417627125166965@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=davem@davemloft.net \
    --cc=dhowells@redhat.com \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-afs@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marc.dionne@auristor.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®