From: sashiko-bot@kernel.org
To: "Ayush Singh" <ayush@beagleboard.org>
Cc: ojeda@kernel.org, robh@kernel.org, devicetree@vger.kernel.org,
conor+dt@kernel.org
Subject: Re: [PATCH 6/7] greybus: Add Rust UART node driver
Date: Thu, 20 Aug 2026 09:38:50 +0000 [thread overview]
Message-ID: <20260820093850.C3F201F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260820-gb-uart-transport-v1-6-282da14ab7b7@beagleboard.org>
Thank you for your contribution! Sashiko AI review found 8 potential issue(s) to consider:
- [High] Incorrect extraction of payload leaves part of the CRC in the message due to an off-by-one calculation.
- [High] The transmit CRC is incorrectly computed over the HDLC-escaped byte stream instead of the raw payload.
- [High] Unbounded memory allocation in the serial receive path allows an attacker to exhaust kernel memory.
- [High] Allocating memory with `GFP_KERNEL` while holding a spinlock causes a 'scheduling while atomic' kernel panic.
- [High] GbNode is registered with the Greybus core in `probe` before the serdev device is fully initialized, allowing premature and unsafe calls to `write`.
- [High] `GbNode::write` performs multiple non-atomic `write_all` operations to the UART without serialization, risking interleaved frames if called concurrently.
- [Medium] Returning early upon a buffer push failure clears the HDLC escape state prematurely, causing an infinite receive stall.
- [Low] Rust imports do not follow the kernel vertical import style.
--
--- Patch [6]: [PATCH 6/7] greybus: Add Rust UART node driver ---
commit 763ce224c179bf0f26e68cd794db14b2b9027390
Author: Ayush Singh <ayush@beagleboard.org>
greybus: Add Rust UART node driver
This commit adds a driver for Greybus nodes attached over a plain serial
port. The node is registered with the software SVC (gb-softsvc), which
handles the SVC protocol on behalf of the AP. Greybus messages are carried
over HDLC framing on the wire.
[ ... ]
> diff --git a/drivers/greybus/gb_uart_node.rs b/drivers/greybus/gb_uart_node.rs
> new file mode 100644
> index 0000000000000..1258122467585
> --- /dev/null
> +++ b/drivers/greybus/gb_uart_node.rs
> @@ -0,0 +1,231 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Greybus UART Node driver
> +
> +use kernel::crc_ccitt::crc_ccitt;
> +use kernel::device::AsBusDevice;
> +use kernel::device::{Bound, Core};
> +use kernel::error::code;
> +use kernel::sync::aref::ARef;
> +use kernel::sync::{Arc, SpinLock};
> +use kernel::{new_spinlock, of, prelude::*, serdev};
[Severity: Low]
Do these imports violate the kernel's vertical import guidelines for Rust
code?
[ ... ]
> + fn frame_finish(&self) -> Result<()> {
> + if self.rx_buf.len() < 4 {
> + return Err(code::EFAULT);
> + }
> +
> + let crc = crc_ccitt(0xffff, &self.rx_buf);
> + if crc != HDLC_EXPECTED_CRC {
> + dev_warn!(self.sdev.as_ref(), "CRC failed {}", crc);
> + return Ok(());
> + }
> +
> + let addr = self.rx_buf[0];
> + let _ctrl = self.rx_buf[1];
> + let payload = &self.rx_buf[2..self.rx_buf.len() - size_of::<u8>()];
[Severity: High]
Does this slice operation incorrectly leave 1 byte of the 2-byte CRC appended
to the payload? The CRC is 16-bit, so it appears subtracting size_of::<u8>()
would retain part of the CRC in the message.
[ ... ]
> + fn rx(&mut self, data: &[u8]) -> usize {
> + for (count, i) in data.iter().enumerate() {
> + match *i {
> + HDLC_FRAME => {
> + if !self.rx_buf.is_empty() {
> + if let Err(e) = self.frame_finish() {
> + dev_warn!(self.sdev.as_ref(), "bad frame: {e:?}\n");
> + }
> + }
> +
> + self.rx_buf.clear();
> + self.rx_in_esc = false;
> + }
> + HDLC_ESC => self.rx_in_esc = true,
> + _ => {
> + let c = if self.rx_in_esc { *i ^ HDLC_XOR } else { *i };
> + self.rx_in_esc = false;
> +
> + if self.rx_buf.push(c, GFP_KERNEL).is_err() {
[Severity: High]
Is there a bounds or MTU capacity check missing here? It looks like a
malfunctioning or malicious device on the serial port streaming endless
non-framing bytes could cause the vector to grow infinitely until kernel
memory is exhausted.
[Severity: Medium]
If the buffer push fails and we return early, does this clear the HDLC
escape state prematurely?
The escape state is mutated right before the error check:
self.rx_in_esc = false;
if self.rx_buf.push(c, GFP_KERNEL).is_err() {
When the serdev core retries passing the failed byte, the escape state
would already be lost, potentially causing an infinite receive stall.
[Severity: High]
Is it safe to use GFP_KERNEL here?
GbUartNode::receive() acquires a spinlock using this.rx.try_lock(), which
disables preemption. It then calls guard.rx(data), which invokes this
buffer push allocation.
Will allocating memory with GFP_KERNEL while holding a spinlock cause a
scheduling while atomic kernel panic?
> + return count;
> + }
> + }
> + }
> + }
[ ... ]
> + fn write_all(mut crc: u16, bound: &serdev::Device<Bound>, data: &[u8]) -> Result<u16> {
> + for i in data {
> + if *i == HDLC_ESC || *i == HDLC_FRAME {
> + let buf = &[HDLC_ESC, i ^ HDLC_XOR];
> + bound.write_all(buf, 0)?;
> + crc = crc_ccitt(crc, buf);
[Severity: High]
Is the transmit CRC incorrectly computed over the HDLC-escaped byte stream
instead of the raw payload?
GbNode::write_all() computes the CRC using crc_ccitt() on the escaped byte
sequence rather than the original raw byte. Could this result in an invalid
CRC that gets rejected by standard receivers?
[ ... ]
> +impl gb_softsvc::InterfaceOps for GbNode {
> + fn write(&self, data: &[u8], cport: u16) -> Result<()> {
> + // SAFETY: `GbNode` only exists while its serdev driver is bound, so the device is in the
> + // `Bound` state for the duration of this call.
> + let bound: &serdev::Device<Bound> =
> + unsafe { serdev::Device::from_device(self.sdev.as_ref().as_bound()) };
[Severity: High]
Could this unsafe block invalidly assume the serdev device is fully bound
before probe completes?
GbUartNode::probe() calls Self::init(), which registers the module with
gb_softsvc. If a write callback is invoked synchronously or asynchronously
before probe finishes, this assumption might be violated.
> +
> + let mut crc = 0xffff;
> +
> + bound.write_all(&[HDLC_FRAME], 0)?;
> +
> + crc = Self::write_all(crc, bound, &[ADDRESS_GREYBUS, 0x03])?;
> + crc = Self::write_all(crc, bound, &cport.to_le_bytes())?;
> + crc = Self::write_all(crc, bound, data)?;
[Severity: High]
Does GbNode::write() perform multiple non-atomic write_all operations to the
UART without serialization?
Since the Greybus core can send messages concurrently from different threads
for different CPorts, could interleaving these writes result in corrupted
HDLC framing and dropped packets on the wire?
[ ... ]
> + fn probe<'bound>(
> + sdev: &'bound serdev::Device<Core<'_>>,
> + _info: Option<&'bound Self::IdInfo>,
> + ) -> impl PinInit<Self, Error> + 'bound {
> + dev_dbg!(sdev.as_ref(), "Probe gb_uart_node.\n");
> + let rx = Self::init(sdev);
[Severity: High]
Is GbNode prematurely registered with the Greybus core here?
Calling Self::init() registers the module before the serdev device is
fully initialized, allowing premature and unsafe calls to GbNode::write().
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260820-gb-uart-transport-v1-0-282da14ab7b7@beagleboard.org?part=6
next prev parent reply other threads:[~2026-08-20 9:38 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-20 9:25 [PATCH 0/7] Add Greybus Sotfsvc and UART Node drivers Ayush Singh
2026-08-20 9:25 ` [PATCH 1/7] greybus: connection: Export gb_connection_get() and gb_connection_put() Ayush Singh
2026-08-20 9:41 ` sashiko-bot
2026-08-20 9:25 ` [PATCH 2/7] greybus: connection: Add gb_connection_hd_find_by_intf() Ayush Singh
2026-08-20 9:32 ` sashiko-bot
2026-08-20 9:25 ` [PATCH 3/7] rust: crc_ccitt: add CRC-CCITT abstraction Ayush Singh
2026-08-20 9:33 ` sashiko-bot
2026-08-20 9:25 ` [PATCH 4/7] rust: kernel: Add greybus abstractions Ayush Singh
2026-08-20 9:42 ` sashiko-bot
2026-08-20 9:25 ` [PATCH 5/7] drivers: greybus: Add software SVC implementation Ayush Singh
2026-08-20 9:40 ` sashiko-bot
2026-08-20 9:25 ` [PATCH 6/7] greybus: Add Rust UART node driver Ayush Singh
2026-08-20 9:38 ` sashiko-bot [this message]
2026-08-20 9:25 ` [PATCH 7/7] dt-bindings: beagle: Add BeagleConnect Freedom Ayush Singh
2026-08-20 9:31 ` sashiko-bot
2026-08-20 18:33 ` Conor Dooley
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=20260820093850.C3F201F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=ayush@beagleboard.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=ojeda@kernel.org \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.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