All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: alistair23@gmail.com
Cc: linux-cxl@vger.kernel.org, ojeda@kernel.org, linux-pci@vger.kernel.org
Subject: Re: [PATCH v2 16/21] lib: rspdm: Support SPDM negotiate_algorithms
Date: Tue, 23 Jun 2026 05:17:00 +0000	[thread overview]
Message-ID: <20260623051701.758C81F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260623045406.2589547-17-alistair.francis@wdc.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Incorrect generic type inference in `KVec::from_raw_parts` and lost capacity leads to Rust Undefined Behavior during descriptor destruction.
- [High] The NEGOTIATE_ALGORITHMS handler rejects valid SPDM 1.0 responses due to a hardcoded 36-byte size validation.
--

commit 886ea37ebdf0a050ca99e3d1c7b0a5330292a00a
Author: Alistair Francis <alistair@alistair23.me>

lib: rspdm: Support SPDM negotiate_algorithms

Support the NEGOTIATE_ALGORITHMS SPDM command.

> diff --git a/lib/rspdm/state.rs b/lib/rspdm/state.rs
> index 5ef14c8ed2375..e4eb009a977c3 100644
> --- a/lib/rspdm/state.rs
> +++ b/lib/rspdm/state.rs
[ ... ]
> @@ -72,9 +108,41 @@ pub(crate) struct SpdmState {
>      // Negotiated state
>      pub(crate) version: u8,
>      pub(crate) rsp_caps: u32,
> +    pub(crate) base_asym_alg: u32,
> +    pub(crate) base_hash_alg: u32,
> +    pub(crate) meas_hash_alg: u32,
> +
> +    /* Signature algorithm */
> +    base_asym_enc: &'a CStr,
> +    sig_len: usize,
> +
> +    /* Hash algorithm */
> +    base_hash_alg_name: &'a CStr,
> +    pub(crate) shash: *mut bindings::crypto_shash,
> +    pub(crate) desc: Option<&'a mut bindings::shash_desc>,
> +    pub(crate) hash_len: usize,
>  }
>  
> -impl SpdmState {
> +impl Drop for SpdmState<'_> {
> +    fn drop(&mut self) {
> +        if let Some(desc) = self.desc.take() {
> +            // SAFETY: `self.shash` is a valid handle
> +            let desc_len = core::mem::size_of::<bindings::shash_desc>()
> +                + unsafe { bindings::crypto_shash_descsize(self.shash) } as usize;
> +
> +            // SAFETY: `desc` was allocated and converted to a raw pointer with
> +            // into_raw_parts()
> +            let desc_vec = unsafe { KVec::from_raw_parts(desc, desc_len, desc_len) };

[Severity: High]
Does this code inadvertently cause Undefined Behavior by incorrectly inferring
the generic type of KVec?

Since `desc` is of type `&mut bindings::shash_desc`, `KVec::from_raw_parts`
infers the new vector as `KVec<bindings::shash_desc>`. Because `desc_len` is
calculated in bytes, this tells the allocator to free `desc_len` elements
of type `shash_desc` (which is 16 bytes) instead of `desc_len` bytes.

Also, it looks like the original allocation capacity was discarded when
`into_raw_parts()` was called in `update_response_algs()`, and here we are
passing `desc_len` as the capacity, which violates `from_raw_parts` invariants.

> +            drop(desc_vec);
> +        }
> +
> +        unsafe {
> +            bindings::crypto_free_shash(self.shash);
> +        }
> +    }
> +}
> +
[ ... ]
> +    fn update_response_algs(&mut self) -> Result<(), Error> {
[ ... ]
> +        // This is freed in when `SpdmState` is dropped, but this call
> +        // can happen multiple times.
> +        if self.shash != core::ptr::null_mut() {
> +            if let Some(desc) = self.desc.take() {
> +                // SAFETY: `self.shash` is a valid handle
> +                let desc_len = core::mem::size_of::<bindings::shash_desc>()
> +                    + unsafe { bindings::crypto_shash_descsize(self.shash) } as usize;
> +
> +                // SAFETY: `desc` was allocated and converted to a raw pointer with
> +                // into_raw_parts()
> +                let desc_vec = unsafe { KVec::from_raw_parts(desc, desc_len, desc_len) };

[Severity: High]
Will the same Undefined Behavior happen here when replacing an existing hash
algorithm context, since it also uses `desc` and `desc_len` to reconstruct the
`KVec`?

> +                drop(desc_vec);
> +            }
> +
> +            unsafe {
> +                bindings::crypto_free_shash(self.shash);
> +            }
> +        }
> +
> +        self.shash =
[ ... ]
> diff --git a/lib/rspdm/validator.rs b/lib/rspdm/validator.rs
> index 7b5aca5d50f89..c53828376fcaa 100644
> --- a/lib/rspdm/validator.rs
> +++ b/lib/rspdm/validator.rs
[ ... ]
> +impl Validate<Untrusted<&[u8]>> for &NegotiateAlgsRsp {
> +    type Err = Error;
> +
> +    fn validate(unvalidated: &[u8]) -> Result<Self, Self::Err> {
> +        if unvalidated.len() < mem::size_of::<NegotiateAlgsRsp>() {
> +            return Err(EINVAL);
> +        }

[Severity: High]
Could this hardcoded length check reject valid SPDM 1.0 responses?

`SpdmState` allows negotiating SPDM version 1.0, and the SPDM 1.0.0
specification states that the NEGOTIATE_ALGORITHMS response base header is
exactly 32 bytes long.

Because `mem::size_of::<NegotiateAlgsRsp>()` is 36 bytes (including fields
introduced in SPDM 1.1), when communicating with an SPDM 1.0 responder
that returns 32 bytes, this will fail with EINVAL and break negotiation.

> +
> +        let ptr = unvalidated.as_ptr();
> +        // CAST: `NegotiateAlgsRsp` only contains integers and has `repr(C)`.
> +        let ptr = ptr.cast::<NegotiateAlgsRsp>();
> +        // SAFETY: `ptr` came from a reference and the cast above is valid.
> +        let rsp: &NegotiateAlgsRsp = unsafe { &*ptr };
> +
> +        Ok(rsp)
> +    }
> +}

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

  reply	other threads:[~2026-06-23  5:17 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-23  4:53 [PATCH v2 00/21] lib: Rust implementation of SPDM alistair23
2026-06-23  4:53 ` [PATCH v2 01/21] rust: transmute: add `cast_slice[_mut]` functions alistair23
2026-06-23  5:05   ` sashiko-bot
2026-06-23  4:53 ` [PATCH v2 02/21] rust: create basic untrusted data API alistair23
2026-06-23  5:09   ` sashiko-bot
2026-06-23  4:53 ` [PATCH v2 03/21] rust: validate: add `Validate` trait alistair23
2026-06-23  5:10   ` sashiko-bot
2026-06-23  4:53 ` [PATCH v2 04/21] X.509: Make certificate parser public alistair23
2026-06-23  5:03   ` sashiko-bot
2026-06-23  4:53 ` [PATCH v2 05/21] X.509: Parse Subject Alternative Name in certificates alistair23
2026-06-23  5:07   ` sashiko-bot
2026-06-23  4:53 ` [PATCH v2 06/21] X.509: Move certificate length retrieval into new helper alistair23
2026-06-23  5:02   ` sashiko-bot
2026-06-23  4:53 ` [PATCH v2 07/21] rust: add bindings for hash.h alistair23
2026-06-23  7:01   ` sashiko-bot
2026-06-23  4:53 ` [PATCH v2 08/21] rust: error: impl From<FromBytesWithNulError> for Kernel Error alistair23
2026-06-23  5:01   ` sashiko-bot
2026-06-23  4:53 ` [PATCH v2 09/21] lib: rspdm: Initial commit of Rust SPDM alistair23
2026-06-23  5:09   ` sashiko-bot
2026-06-23  4:53 ` [PATCH v2 10/21] PCI/TSM: Rename pf0 to host alistair23
2026-06-23  5:12   ` sashiko-bot
2026-06-23  4:53 ` [PATCH v2 11/21] PCI/TSM: Support connecting to PCIe CMA devices alistair23
2026-06-23  5:16   ` sashiko-bot
2026-06-23  4:53 ` [PATCH v2 12/21] PCI/CMA: Add a PCI TSM CMA driver using SPDM alistair23
2026-06-23  5:07   ` sashiko-bot
2026-06-23  4:53 ` [PATCH v2 13/21] PCI/CMA: Validate Subject Alternative Name in certificates alistair23
2026-06-23  5:07   ` sashiko-bot
2026-06-23  4:53 ` [PATCH v2 14/21] lib: rspdm: Support SPDM get_version alistair23
2026-06-23  5:10   ` sashiko-bot
2026-06-23  4:54 ` [PATCH v2 15/21] lib: rspdm: Support SPDM get_capabilities alistair23
2026-06-23  5:09   ` sashiko-bot
2026-06-23  4:54 ` [PATCH v2 16/21] lib: rspdm: Support SPDM negotiate_algorithms alistair23
2026-06-23  5:17   ` sashiko-bot [this message]
2026-06-23  4:54 ` [PATCH v2 17/21] lib: rspdm: Support SPDM get_digests alistair23
2026-06-23  5:17   ` sashiko-bot
2026-06-23  4:54 ` [PATCH v2 18/21] lib: rspdm: Support SPDM get_certificate alistair23
2026-06-23  5:20   ` sashiko-bot
2026-06-23  4:54 ` [PATCH v2 19/21] lib: rspdm: Support SPDM certificate validation alistair23
2026-06-23  5:19   ` sashiko-bot
2026-06-23  4:54 ` [PATCH v2 20/21] rust: allow extracting the buffer from a CString alistair23
2026-06-23  5:13   ` sashiko-bot
2026-06-23  4:54 ` [PATCH v2 21/21] lib: rspdm: Support SPDM challenge alistair23
2026-06-23  5:21   ` 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=20260623051701.758C81F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=alistair23@gmail.com \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=ojeda@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.