Linux PCI subsystem development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: alistair23@gmail.com
Cc: ojeda@kernel.org, linux-pci@vger.kernel.org
Subject: Re: [PATCH 13/18] lib: rspdm: Support SPDM negotiate_algorithms
Date: Fri, 08 May 2026 04:05:50 +0000	[thread overview]
Message-ID: <20260508040551.48C9CC2BCB0@smtp.kernel.org> (raw)
In-Reply-To: <20260508031710.514574-14-alistair.francis@wdc.com>

Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [Critical] Use-After-Free and Double Free of `shash_desc` allocation.
- [High] Invalid pointer dereference and kernel panic when `crypto_alloc_shash` fails.
- [High] Logic error in measurement capability check bypasses algorithm validation.
- [High] Missing upper-bound check on `rc` allows vector length to exceed capacity.
- [High] Endianness bug in `request.length` field generation.
- [High] Creating `&mut [u8]` slices over uninitialized memory is Undefined Behavior.
- [High] Memory leak of the `SpdmState` struct in `spdm_destroy()`.
--

commit 76d36cb1cc14535a6da5b5475b1186acce60ab8a
Author: Alistair Francis <alistair@alistair23.me>

lib: rspdm: Support SPDM negotiate_algorithms

This commit adds support for the NEGOTIATE_ALGORITHMS SPDM command.

> diff --git a/lib/rspdm/lib.rs b/lib/rspdm/lib.rs
> index 9628f258854c6..72886a5dfd695 100644
> --- a/lib/rspdm/lib.rs
> +++ b/lib/rspdm/lib.rs
[ ... ]
> @@ -123,4 +127,16 @@
>  ///
>  /// @spdm_state: SPDM session state
>  #[export]
> -pub unsafe extern "C" fn spdm_destroy(_state_ptr: *mut spdm_state) {}
> +pub unsafe extern "C" fn spdm_destroy(state_ptr: *mut spdm_state) {
> +    let state: &mut SpdmState = unsafe { &mut (*(state_ptr as *mut SpdmState)) };
> +
> +    if let Some(desc) = &mut state.desc {
> +        unsafe {
> +            bindings::kfree(*desc as *mut _ as *mut c_void);
> +        }
> +    }
> +

Does this leak the SpdmState allocation itself? The internal fields are cleaned
up, but state_ptr itself does not appear to be freed here.

> +    unsafe {
> +        bindings::crypto_free_shash(state.shash);
> +    }
> +}

If crypto_alloc_shash() fails earlier, it can return an ERR_PTR. If that
happens, state.shash holds an error pointer. Since crypto_free_shash()
only checks for NULL, will this cause a kernel panic when trying to free
an ERR_PTR here?

> diff --git a/lib/rspdm/state.rs b/lib/rspdm/state.rs
> index e7119ffa9a691..34676744e5094 100644
> --- a/lib/rspdm/state.rs
> +++ b/lib/rspdm/state.rs
[ ... ]
> @@ -367,4 +427,155 @@ pub(crate) fn get_capabilities(&mut self) -> Result<(), Error> {
[ ... ]
> +        let mut desc_vec: KVec<u8> = KVec::with_capacity(desc_len, GFP_KERNEL)?;
> +        // SAFETY: `desc_vec` is `desc_len` long
> +        let desc_buf = unsafe { from_raw_parts_mut(desc_vec.as_mut_ptr(), desc_len) };

Is this creating a reference to uninitialized memory? KVec::with_capacity()
leaves the underlying memory uninitialized, and forming a slice over
uninitialized memory is undefined behavior in Rust.

> +
> +        let desc = unsafe {
> +            core::mem::transmute::<*mut c_void, &mut bindings::shash_desc>(
> +                desc_buf.as_mut_ptr() as *mut c_void
> +            )
> +        };
> +        desc.tfm = self.shash;
> +
> +        self.desc = Some(desc);

Can this cause a use-after-free and a later double-free? desc_vec is a local
variable that will be dropped at the end of this function, freeing its
backing buffer. self.desc then holds a dangling reference. Furthermore,
when spdm_destroy() cleans up the session, it calls bindings::kfree() on
this dangling pointer, which seems like it would corrupt the kernel
allocator.

[ ... ]
> +    pub(crate) fn negotiate_algs(&mut self) -> Result<(), Error> {
> +        let mut request = NegotiateAlgsReq::default();
> +        request.version = self.version;
> +
> +        if self.version >= SPDM_VER_12 && (self.rsp_caps & SPDM_KEY_EX_CAP) == SPDM_KEY_EX_CAP {
> +            request.other_params_support = SPDM_OPAQUE_DATA_FMT_GENERAL;
> +        }
> +
> +        let req_sz = core::mem::size_of::<NegotiateAlgsReq>();
> +        let rsp_sz = core::mem::size_of::<NegotiateAlgsRsp>();
> +
> +        request.length = req_sz as u16;

The SPDM protocol requires multi-byte fields to be transmitted in
little-endian format. Will this send a corrupted, big-endian length value
on big-endian architectures? The base_asym_algo field uses to_le(), so
perhaps this should as well.

> +
> +        // SAFETY: `request` is repr(C) and packed, so we can convert it to a slice
> +        let request_buf = unsafe { from_raw_parts_mut(&mut request as *mut _ as *mut u8, req_sz) };
> +
> +        let mut response_vec: KVec<u8> = KVec::with_capacity(rsp_sz, GFP_KERNEL)?;
> +        // SAFETY: `response_vec` is rsp_sz length, initialised, aligned
> +        // and won't be mutated
> +        let response_buf = unsafe { from_raw_parts_mut(response_vec.as_mut_ptr(), rsp_sz) };

Is this also creating a reference to uninitialized memory? The safety
comment notes it is initialized, but KVec::with_capacity() does not initialize
the allocated memory.

> +
> +        let rc = self.spdm_exchange(request_buf, response_buf)?;
> +
> +        if rc < (rsp_sz as i32) {
> +            pr_err!("Truncated capabilities response\n");
> +            to_result(-(bindings::EIO as i32))?;
> +        }
> +
> +        // SAFETY: `rc` is the length of data read, which will be smaller
> +        // then the capacity of the vector
> +        unsafe { response_vec.inc_len(rc as usize) };

Does this code verify that rc is not larger than rsp_sz? If
spdm_exchange() returns a value greater than rsp_sz (for example, if a
device sends extra payload data), would this set the vector length beyond
its allocated capacity and lead to out-of-bounds memory accesses?

[ ... ]
> +        if self.rsp_caps & SPDM_MEAS_CAP_MASK == SPDM_MEAS_CAP_MASK
> +            && (self.meas_hash_alg.count_ones() != 1
> +                || response.measurement_specification_sel != SPDM_MEAS_SPEC_DMTF)
> +        {
> +            pr_err!("Malformed algorithms response\n");
> +            to_result(-(bindings::EPROTO as i32))?;
> +        }

Does this condition correctly check for measurement support?
SPDM_MEAS_CAP_MASK is defined as bits 3 and 4 (11b). According to the SPDM
specification, 11b is a reserved value, while valid measurement support is
01b or 10b. By checking for strict equality with the mask, it looks like
this evaluates to false for legitimate devices and bypasses the algorithm
validation.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260508031710.514574-1-alistair.francis@wdc.com?part=13

  reply	other threads:[~2026-05-08  4:05 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-08  3:16 [PATCH 00/18] lib: Rust implementation of SPDM alistair23
2026-05-08  3:16 ` [PATCH 01/18] rust: add untrusted data abstraction alistair23
2026-05-08  3:52   ` sashiko-bot
2026-05-08  5:17   ` Dirk Behme
2026-05-08  3:16 ` [PATCH 02/18] X.509: Make certificate parser public alistair23
2026-05-08  3:45   ` sashiko-bot
2026-05-08  3:16 ` [PATCH 03/18] X.509: Parse Subject Alternative Name in certificates alistair23
2026-05-08  3:16 ` [PATCH 04/18] X.509: Move certificate length retrieval into new helper alistair23
2026-05-08  3:39   ` sashiko-bot
2026-05-08  3:16 ` [PATCH 05/18] rust: add bindings for hash.h alistair23
2026-05-08  3:43   ` sashiko-bot
2026-05-08  3:16 ` [PATCH 06/18] rust: error: impl From<FromBytesWithNulError> for Kernel Error alistair23
2026-05-08  3:51   ` sashiko-bot
2026-05-08  3:16 ` [PATCH 07/18] lib: rspdm: Initial commit of Rust SPDM alistair23
2026-05-08  3:41   ` sashiko-bot
2026-05-08  3:17 ` [PATCH 08/18] PCI/TSM: Support connecting to PCIe CMA devices alistair23
2026-05-08  3:17 ` [PATCH 09/18] PCI/CMA: Add a PCI TSM CMA driver using SPDM alistair23
2026-05-08  5:02   ` sashiko-bot
2026-05-08  3:17 ` [PATCH 10/18] PCI/CMA: Validate Subject Alternative Name in certificates alistair23
2026-05-08  3:58   ` sashiko-bot
2026-05-08  3:17 ` [PATCH 11/18] lib: rspdm: Support SPDM get_version alistair23
2026-05-08  3:50   ` sashiko-bot
2026-05-08  3:17 ` [PATCH 12/18] lib: rspdm: Support SPDM get_capabilities alistair23
2026-05-08  4:05   ` sashiko-bot
2026-05-08  3:17 ` [PATCH 13/18] lib: rspdm: Support SPDM negotiate_algorithms alistair23
2026-05-08  4:05   ` sashiko-bot [this message]
2026-05-08  3:17 ` [PATCH 14/18] lib: rspdm: Support SPDM get_digests alistair23
2026-05-08  4:06   ` sashiko-bot
2026-05-08  3:17 ` [PATCH 15/18] lib: rspdm: Support SPDM get_certificate alistair23
2026-05-08  4:23   ` sashiko-bot
2026-05-08  3:17 ` [PATCH 16/18] lib: rspdm: Support SPDM certificate validation alistair23
2026-05-08  4:25   ` sashiko-bot
2026-05-08  3:17 ` [PATCH 17/18] rust: allow extracting the buffer from a CString alistair23
2026-05-08  3:17 ` [PATCH 18/18] lib: rspdm: Support SPDM challenge alistair23
2026-05-08  4:19   ` sashiko-bot

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=20260508040551.48C9CC2BCB0@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=alistair23@gmail.com \
    --cc=linux-pci@vger.kernel.org \
    --cc=ojeda@kernel.org \
    --cc=sashiko@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