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
next prev parent 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