Devicetree
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Ayush Singh" <ayush@beagleboard.org>,
	"Jason Kridner" <jkridner@beagleboard.org>,
	robertcnelson@gmail.com, "Johan Hovold" <johan@kernel.org>,
	"Alex Elder" <elder@kernel.org>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"Daniel Almeida" <daniel.almeida@collabora.com>,
	"Tamir Duberstein" <tamird@kernel.org>,
	"Alexandre Courbot" <acourbot@nvidia.com>,
	"Onur Özkan" <work@onurozkan.dev>,
	"Eric Biggers" <ebiggers@kernel.org>,
	"Ard Biesheuvel" <ardb@kernel.org>,
	"Ayush Singh" <ayush@beagleboard.com>,
	"Rob Herring" <robh@kernel.org>,
	"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
	"Conor Dooley" <conor+dt@kernel.org>,
	"Lorenzo Stoakes" <ljs@kernel.org>,
	"Vlastimil Babka" <vbabka@kernel.org>,
	"Liam R. Howlett" <liam@infradead.org>,
	"Uladzislau Rezki" <urezki@gmail.com>,
	"Markus Probst" <markus.probst@posteo.de>
Cc: linux-crypto@vger.kernel.org, devicetree@vger.kernel.org
Subject: Re: [PATCH v5 3/9] greybus: operation: arm request timeout before sending
Date: Tue, 03 Nov 2026 16:27:16 +0000	[thread overview]
Message-ID: <sashiko-outbox-195721@kernel.org> (raw)
In-Reply-To: <20261103-gb-uart-transport-v5-3-f8e326d6561f@beagleboard.org>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Critical] greybus: operation: UAF and ref underflow in gb_operation_request_send()
- [Critical] greybus: operation: UAF from early timeout in gb_operation_request_send()
- [Critical] greybus: operation: timer leak in gb_operation_request_send() on cancel
--

commit 7b73a81d11f2d699f2c8ebeafd18ae6352191433
Author: Ayush Singh <ayush@beagleboard.org>

greybus: operation: arm request timeout before sending

This commit arms the operation timeout timer before calling
gb_message_send() in gb_operation_request_send() so that a fast response
completing before gb_message_send() returns does not leave an armed timer
behind, and calls timer_delete_sync() in the err_put_active error path.

> diff --git a/drivers/greybus/operation.c b/drivers/greybus/operation.c
> index a63bc2eb164e9..2d37acedf36f8 100644
> --- a/drivers/greybus/operation.c
> +++ b/drivers/greybus/operation.c
> @@ -782,20 +782,25 @@ int gb_operation_request_send(struct gb_operation *operation,
>  		return 0;
>  	}
>  
> +	/*
> +	 * Arm the timeout before sending: the response can arrive, and the
> +	 * operation complete, before the host driver returns.
> +	 */
> +	if (timeout) {
> +		operation->timer.expires = jiffies + msecs_to_jiffies(timeout);
> +		add_timer(&operation->timer);
> +	}

[Severity: Critical]
Could an operation still be cancelled between gb_operation_get_active() and
add_timer(&operation->timer) in gb_operation_request_send(), leaking an
armed timer in operation->timer?

Earlier in gb_operation_request_send(), operation->errno is initialized to
-EINPROGRESS and the first gb_operation_get_active() adds operation->links
to connection->operations.

If a concurrent thread disables the connection via gb_connection_disable()
or gb_connection_disable_forced() after the second
gb_operation_get_active() succeeds and before add_timer(&operation->timer)
runs:

CPU0                                    CPU1
gb_operation_request_send()
  gb_operation_result_set(-EINPROGRESS)
  gb_operation_get_active()
  gb_operation_get_active()
                                        gb_connection_cancel_operations()
                                          gb_operation_cancel(-ESHUTDOWN)
                                            gb_operation_result_set(-ESHUTDOWN)
                                            queue_work(&operation->work)

                                        gb_operation_work()
                                          timer_delete_sync(&operation->timer)
                                          operation->callback(operation)
                                          gb_operation_put_active(operation)
                                          gb_operation_put(operation)
  add_timer(&operation->timer)
  gb_message_send() -> returns 0

Because gb_operation_work() runs timer_delete_sync(&operation->timer) before
CPU0 calls add_timer(&operation->timer), nothing deletes operation->timer
afterward. When the caller later drops its reference via gb_operation_put(),
_gb_operation_destroy() frees struct gb_operation while operation->timer is
still queued in the timer wheel.

> +
>  	ret = gb_message_send(operation->request, gfp);

[Severity: Critical]
What happens if operation->timer expires after add_timer(&operation->timer)
is called, but before the host driver in gb_message_send() has submitted its
transport request?

For an asynchronous host driver such as drivers/greybus/es2.c, if the
sending thread is delayed or preempted before message_send() assigns
message->hcpriv and calls usb_submit_urb():

drivers/greybus/es2.c:message_send() {
	...
	spin_lock_irqsave(&es2->cport_out_urb_lock, flags);
	message->hcpriv = urb;
	spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags);
	...
	retval = usb_submit_urb(urb, gfp_mask);
}

If operation->timer fires first, gb_operation_timeout() sets
operation->errno to -ETIMEDOUT and schedules gb_operation_work():

gb_operation_timeout()
  gb_operation_result_set(operation, -ETIMEDOUT)
  queue_work(gb_operation_completion_wq, &operation->work)

gb_operation_work()
  timer_delete_sync(&operation->timer)
  gb_message_cancel(operation->request)
    es2.c:message_cancel() -> no-op because message->hcpriv is not yet active
  operation->callback(operation)
  gb_operation_put_active(operation)
  gb_operation_put(operation)

When the sending thread resumes in es2.c:message_send(), it submits the URB
and returns 0 to gb_operation_request_send(). Because operation->callback()
has already completed the operation, the caller can drop the final reference
to operation via gb_operation_put(), freeing operation->request and
operation->request->buffer in _gb_operation_destroy() while the URB is still
in flight.

>  	gb_operation_put_active(operation);
>  	gb_operation_put(operation);
>  	if (ret)
>  		goto err_put_active;
>  
> -	if (timeout) {
> -		operation->timer.expires = jiffies + msecs_to_jiffies(timeout);
> -		add_timer(&operation->timer);
> -	}
> -
>  	return 0;
>  
>  err_put_active:
> +	timer_delete_sync(&operation->timer);
>  	gb_operation_put_active(operation);
>  err_put:
>  	gb_operation_put(operation);

[Severity: Critical]
Can this error path underflow operation->active and operation->kref and
trigger a use-after-free on struct gb_operation when gb_message_send() fails
after operation->timer has already expired (or after gb_operation_cancel()
has been called)?

In gb_operation_request_send(), two pairs of kref and active references are
taken before gb_message_send(): one pair for operation completion, and one
pair held across gb_message_send().

With operation->timer armed before gb_message_send(), if gb_message_send()
sleeps or takes longer than timeout before returning an error (for example,
hdlc_tx_frames() in gb-beagleplay.c waiting on a full TX circular buffer
before returning -EAGAIN, or write_all() in gb_uart_node.rs returning
-EINTR), operation->timer can fire while gb_message_send() is still running:

gb_operation_timeout()
  if (gb_operation_result_set(operation, -ETIMEDOUT))
      queue_work(gb_operation_completion_wq, &operation->work);

gb_operation_work() then runs on gb_operation_completion_wq, invokes
operation->callback(operation), and drops the completion reference pair:

gb_operation_work()
  ...
  operation->callback(operation);
  gb_operation_put_active(operation);
  gb_operation_put(operation);

When gb_message_send() returns a non-zero ret, gb_operation_request_send()
drops the send-guard reference pair and jumps to err_put_active:

  ret = gb_message_send(operation->request, gfp);
  gb_operation_put_active(operation);
  gb_operation_put(operation);
  if (ret)
      goto err_put_active;

In err_put_active, timer_delete_sync(&operation->timer) only waits for the
timer callback to finish; it does not cancel the already-queued
operation->work, nor does err_put_active check gb_operation_result_set() to
see whether completion was already claimed.

Consequently, err_put_active drops gb_operation_put_active(operation) and
gb_operation_put(operation) a third time when only two pairs were acquired,
underflowing operation->active to -1 (which also causes wait_event() in
gb_operation_cancel() to hang) and dropping the caller's own kref on
operation (or accessing operation after it was already freed if an
asynchronous callback such as gb_loopback_async_operation_callback() dropped
the caller's reference before gb_operation_put() prior to err_put_active).

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261103-gb-uart-transport-v5-0-f8e326d6561f@beagleboard.org?part=3

  reply	other threads:[~2026-11-03 16:27 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-03 16:11 [PATCH v5 0/9] Add Greybus Sotfsvc and UART Node drivers Ayush Singh
2026-11-03 16:11 ` [PATCH v5 1/9] greybus: operation: keep request active across message_send Ayush Singh
2026-11-03 16:30   ` sashiko-bot
2026-11-03 16:11 ` [PATCH v5 2/9] greybus: svc: add gb_svc_flush() Ayush Singh
2026-11-03 16:11 ` [PATCH v5 3/9] greybus: operation: arm request timeout before sending Ayush Singh
2026-11-03 16:27   ` sashiko-bot [this message]
2026-11-03 16:11 ` [PATCH v5 4/9] greybus: connection: Add greybus_data_rcvd_by_intf() Ayush Singh
2026-11-03 16:11 ` [PATCH v5 5/9] rust: crc_ccitt: add CRC-CCITT abstraction Ayush Singh
2026-11-03 16:11 ` [PATCH v5 6/9] rust: kernel: Add greybus abstractions Ayush Singh
2026-11-03 16:28   ` sashiko-bot
2026-11-03 16:11 ` [PATCH v5 7/9] drivers: greybus: Add software SVC implementation Ayush Singh
2026-11-03 16:32   ` sashiko-bot
2026-11-03 16:11 ` [PATCH v5 8/9] dt-bindings: beagle: Add BeagleConnect Freedom Ayush Singh
2026-11-03 16:11 ` [PATCH v5 9/9] greybus: Add Rust UART node driver Ayush Singh

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=sashiko-outbox-195721@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=aliceryhl@google.com \
    --cc=ardb@kernel.org \
    --cc=ayush@beagleboard.com \
    --cc=ayush@beagleboard.org \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=devicetree@vger.kernel.org \
    --cc=ebiggers@kernel.org \
    --cc=elder@kernel.org \
    --cc=gary@garyguo.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=jkridner@beagleboard.org \
    --cc=johan@kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=liam@infradead.org \
    --cc=linux-crypto@vger.kernel.org \
    --cc=ljs@kernel.org \
    --cc=lossin@kernel.org \
    --cc=markus.probst@posteo.de \
    --cc=ojeda@kernel.org \
    --cc=robertcnelson@gmail.com \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=tamird@kernel.org \
    --cc=tmgross@umich.edu \
    --cc=urezki@gmail.com \
    --cc=vbabka@kernel.org \
    --cc=work@onurozkan.dev \
    /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