]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Jan 2026 14:55:42 +0000 (15:55 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Jan 2026 14:55:42 +0000 (15:55 +0100)
added patches:
alsa-hda-intel-dsp-config-prefer-legacy-driver-as-fallback.patch
tpm2-sessions-fix-out-of-range-indexing-in-name_size.patch

queue-6.12/alsa-hda-intel-dsp-config-prefer-legacy-driver-as-fallback.patch [new file with mode: 0644]
queue-6.12/series
queue-6.12/tpm2-sessions-fix-out-of-range-indexing-in-name_size.patch [new file with mode: 0644]

diff --git a/queue-6.12/alsa-hda-intel-dsp-config-prefer-legacy-driver-as-fallback.patch b/queue-6.12/alsa-hda-intel-dsp-config-prefer-legacy-driver-as-fallback.patch
new file mode 100644 (file)
index 0000000..c54624c
--- /dev/null
@@ -0,0 +1,67 @@
+From 161a0c617ab172bbcda7ce61803addeb2124dbff Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 10 Dec 2025 14:15:51 +0100
+Subject: ALSA: hda: intel-dsp-config: Prefer legacy driver as fallback
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 161a0c617ab172bbcda7ce61803addeb2124dbff upstream.
+
+When config table entries don't match with the device to be probed,
+currently we fall back to SND_INTEL_DSP_DRIVER_ANY, which means to
+allow any drivers to bind with it.
+
+This was set so with the assumption (or hope) that all controller
+drivers should cover the devices generally, but in practice, this
+caused a problem as reported recently.  Namely, when a specific
+kconfig for SOF isn't set for the modern Intel chips like Alderlake,
+a wrong driver (AVS) got probed and failed.  This is because we have
+entries like:
+
+ #if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE)
+ /* Alder Lake / Raptor Lake */
+       {
+               .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+               .device = PCI_DEVICE_ID_INTEL_HDA_ADL_S,
+       },
+ ....
+ #endif
+
+so this entry is effective only when CONFIG_SND_SOC_SOF_ALDERLAKE is
+set.  If not set, there is no matching entry, hence it returns
+SND_INTEL_DSP_DRIVER_ANY as fallback.  OTOH, if the kconfig is set, it
+explicitly falls back to SND_INTEL_DSP_DRIVER_LEGACY when no DMIC or
+SoundWire is found -- that was the working scenario.  That being said,
+the current setup may be broken for modern Intel chips that are
+supposed to work with either SOF or legacy driver when the
+corresponding kconfig were missing.
+
+For addressing the problem above, this patch changes the fallback
+driver to the legacy driver, i.e. return SND_INTEL_DSP_DRIVER_LEGACY
+type as much as possible.  When CONFIG_SND_HDA_INTEL is also disabled,
+the fallback is set to SND_INTEL_DSP_DRIVER_ANY type, just to be sure.
+
+Reported-by: Askar Safin <safinaskar@gmail.com>
+Closes: https://lore.kernel.org/all/20251014034156.4480-1-safinaskar@gmail.com/
+Tested-by: Askar Safin <safinaskar@gmail.com>
+Reviewed-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20251210131553.184404-1-tiwai@suse.de
+Signed-off-by: Askar Safin <safinaskar@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/hda/intel-dsp-config.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/sound/hda/intel-dsp-config.c
++++ b/sound/hda/intel-dsp-config.c
+@@ -676,7 +676,8 @@ int snd_intel_dsp_driver_probe(struct pc
+       /* find the configuration for the specific device */
+       cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table));
+       if (!cfg)
+-              return SND_INTEL_DSP_DRIVER_ANY;
++              return IS_ENABLED(CONFIG_SND_HDA_INTEL) ?
++                      SND_INTEL_DSP_DRIVER_LEGACY : SND_INTEL_DSP_DRIVER_ANY;
+       if (cfg->flags & FLAG_SOF) {
+               if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE &&
index 20d18dc4f7b1443d86b3d21775e13173031c8d28..59430ab08a1d12e39d6587c547cb4b3a5185b4f6 100644 (file)
@@ -114,3 +114,5 @@ alsa-hda-realtek-enable-woofer-speakers-on-medion-nm.patch
 asoc-fsl_sai-add-missing-registers-to-cache-default.patch
 scsi-sg-fix-occasional-bogus-elapsed-time-that-excee.patch
 spi-cadence-quadspi-prevent-lost-complete-call-durin.patch
+tpm2-sessions-fix-out-of-range-indexing-in-name_size.patch
+alsa-hda-intel-dsp-config-prefer-legacy-driver-as-fallback.patch
diff --git a/queue-6.12/tpm2-sessions-fix-out-of-range-indexing-in-name_size.patch b/queue-6.12/tpm2-sessions-fix-out-of-range-indexing-in-name_size.patch
new file mode 100644 (file)
index 0000000..4bd5b8a
--- /dev/null
@@ -0,0 +1,403 @@
+From 6e9722e9a7bfe1bbad649937c811076acf86e1fd Mon Sep 17 00:00:00 2001
+From: Jarkko Sakkinen <jarkko@kernel.org>
+Date: Sun, 30 Nov 2025 21:07:12 +0200
+Subject: tpm2-sessions: Fix out of range indexing in name_size
+
+From: Jarkko Sakkinen <jarkko@kernel.org>
+
+commit 6e9722e9a7bfe1bbad649937c811076acf86e1fd upstream.
+
+'name_size' does not have any range checks, and it just directly indexes
+with TPM_ALG_ID, which could lead into memory corruption at worst.
+
+Address the issue by only processing known values and returning -EINVAL for
+unrecognized values.
+
+Make also 'tpm_buf_append_name' and 'tpm_buf_fill_hmac_session' fallible so
+that errors are detected before causing any spurious TPM traffic.
+
+End also the authorization session on failure in both of the functions, as
+the session state would be then by definition corrupted.
+
+Cc: stable@vger.kernel.org # v6.10+
+Fixes: 1085b8276bb4 ("tpm: Add the rest of the session HMAC API")
+Reviewed-by: Jonathan McDowell <noodles@meta.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/tpm/tpm2-cmd.c               |   23 +++++-
+ drivers/char/tpm/tpm2-sessions.c          |  114 ++++++++++++++++++++----------
+ include/linux/tpm.h                       |   13 ++-
+ security/keys/trusted-keys/trusted_tpm2.c |   29 ++++++-
+ 4 files changed, 126 insertions(+), 53 deletions(-)
+
+--- a/drivers/char/tpm/tpm2-cmd.c
++++ b/drivers/char/tpm/tpm2-cmd.c
+@@ -253,7 +253,11 @@ int tpm2_pcr_extend(struct tpm_chip *chi
+       }
+       if (!disable_pcr_integrity) {
+-              tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
++              rc = tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
++              if (rc) {
++                      tpm_buf_destroy(&buf);
++                      return rc;
++              }
+               tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0);
+       } else {
+               tpm_buf_append_handle(chip, &buf, pcr_idx);
+@@ -268,8 +272,14 @@ int tpm2_pcr_extend(struct tpm_chip *chi
+                              chip->allocated_banks[i].digest_size);
+       }
+-      if (!disable_pcr_integrity)
+-              tpm_buf_fill_hmac_session(chip, &buf);
++      if (!disable_pcr_integrity) {
++              rc = tpm_buf_fill_hmac_session(chip, &buf);
++              if (rc) {
++                      tpm_buf_destroy(&buf);
++                      return rc;
++              }
++      }
++
+       rc = tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value");
+       if (!disable_pcr_integrity)
+               rc = tpm_buf_check_hmac_response(chip, &buf, rc);
+@@ -327,7 +337,12 @@ int tpm2_get_random(struct tpm_chip *chi
+                                               | TPM2_SA_CONTINUE_SESSION,
+                                               NULL, 0);
+               tpm_buf_append_u16(&buf, num_bytes);
+-              tpm_buf_fill_hmac_session(chip, &buf);
++              err = tpm_buf_fill_hmac_session(chip, &buf);
++              if (err) {
++                      tpm_buf_destroy(&buf);
++                      return err;
++              }
++
+               err = tpm_transmit_cmd(chip, &buf,
+                                      offsetof(struct tpm2_get_random_out,
+                                               buffer),
+--- a/drivers/char/tpm/tpm2-sessions.c
++++ b/drivers/char/tpm/tpm2-sessions.c
+@@ -144,16 +144,23 @@ struct tpm2_auth {
+ /*
+  * Name Size based on TPM algorithm (assumes no hash bigger than 255)
+  */
+-static u8 name_size(const u8 *name)
++static int name_size(const u8 *name)
+ {
+-      static u8 size_map[] = {
+-              [TPM_ALG_SHA1] = SHA1_DIGEST_SIZE,
+-              [TPM_ALG_SHA256] = SHA256_DIGEST_SIZE,
+-              [TPM_ALG_SHA384] = SHA384_DIGEST_SIZE,
+-              [TPM_ALG_SHA512] = SHA512_DIGEST_SIZE,
+-      };
+-      u16 alg = get_unaligned_be16(name);
+-      return size_map[alg] + 2;
++      u16 hash_alg = get_unaligned_be16(name);
++
++      switch (hash_alg) {
++      case TPM_ALG_SHA1:
++              return SHA1_DIGEST_SIZE + 2;
++      case TPM_ALG_SHA256:
++              return SHA256_DIGEST_SIZE + 2;
++      case TPM_ALG_SHA384:
++              return SHA384_DIGEST_SIZE + 2;
++      case TPM_ALG_SHA512:
++              return SHA512_DIGEST_SIZE + 2;
++      default:
++              pr_warn("tpm: unsupported name algorithm: 0x%04x\n", hash_alg);
++              return -EINVAL;
++      }
+ }
+ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name)
+@@ -234,9 +241,11 @@ static int tpm2_read_public(struct tpm_c
+  * As with most tpm_buf operations, success is assumed because failure
+  * will be caused by an incorrect programming model and indicated by a
+  * kernel message.
++ *
++ * Ends the authorization session on failure.
+  */
+-void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
+-                       u32 handle, u8 *name)
++int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
++                      u32 handle, u8 *name)
+ {
+ #ifdef CONFIG_TCG_TPM2_HMAC
+       enum tpm2_mso_type mso = tpm2_handle_mso(handle);
+@@ -247,18 +256,22 @@ void tpm_buf_append_name(struct tpm_chip
+       if (!tpm2_chip_auth(chip)) {
+               tpm_buf_append_handle(chip, buf, handle);
+-              return;
++              return 0;
+       }
+ #ifdef CONFIG_TCG_TPM2_HMAC
+       slot = (tpm_buf_length(buf) - TPM_HEADER_SIZE) / 4;
+       if (slot >= AUTH_MAX_NAMES) {
+-              dev_err(&chip->dev, "TPM: too many handles\n");
+-              return;
++              dev_err(&chip->dev, "too many handles\n");
++              ret = -EIO;
++              goto err;
+       }
+       auth = chip->auth;
+-      WARN(auth->session != tpm_buf_length(buf),
+-           "name added in wrong place\n");
++      if (auth->session != tpm_buf_length(buf)) {
++              dev_err(&chip->dev, "session state malformed");
++              ret = -EIO;
++              goto err;
++      }
+       tpm_buf_append_u32(buf, handle);
+       auth->session += 4;
+@@ -271,17 +284,29 @@ void tpm_buf_append_name(struct tpm_chip
+                               goto err;
+               }
+       } else {
+-              if (name)
+-                      dev_err(&chip->dev, "TPM: Handle does not require name but one is specified\n");
++              if (name) {
++                      dev_err(&chip->dev, "handle 0x%08x does not use a name\n",
++                              handle);
++                      ret = -EIO;
++                      goto err;
++              }
+       }
+       auth->name_h[slot] = handle;
+-      if (name)
+-              memcpy(auth->name[slot], name, name_size(name));
+-      return;
++      if (name) {
++              ret = name_size(name);
++              if (ret < 0)
++                      goto err;
++              memcpy(auth->name[slot], name, ret);
++      }
++#endif
++      return 0;
++
++#ifdef CONFIG_TCG_TPM2_HMAC
+ err:
+       tpm2_end_auth_session(chip);
++      return tpm_ret_to_err(ret);
+ #endif
+ }
+ EXPORT_SYMBOL_GPL(tpm_buf_append_name);
+@@ -599,11 +624,9 @@ static void tpm_buf_append_salt(struct t
+  * encryption key and encrypts the first parameter of the command
+  * buffer with it.
+  *
+- * As with most tpm_buf operations, success is assumed because failure
+- * will be caused by an incorrect programming model and indicated by a
+- * kernel message.
++ * Ends the authorization session on failure.
+  */
+-void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
++int tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
+ {
+       u32 cc, handles, val;
+       struct tpm2_auth *auth = chip->auth;
+@@ -614,9 +637,12 @@ void tpm_buf_fill_hmac_session(struct tp
+       u32 attrs;
+       u8 cphash[SHA256_DIGEST_SIZE];
+       struct sha256_state sctx;
++      int ret;
+-      if (!auth)
+-              return;
++      if (!auth) {
++              ret = -EIO;
++              goto err;
++      }
+       /* save the command code in BE format */
+       auth->ordinal = head->ordinal;
+@@ -625,9 +651,11 @@ void tpm_buf_fill_hmac_session(struct tp
+       i = tpm2_find_cc(chip, cc);
+       if (i < 0) {
+-              dev_err(&chip->dev, "Command 0x%x not found in TPM\n", cc);
+-              return;
++              dev_err(&chip->dev, "command 0x%08x not found\n", cc);
++              ret = -EIO;
++              goto err;
+       }
++
+       attrs = chip->cc_attrs_tbl[i];
+       handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0);
+@@ -641,9 +669,9 @@ void tpm_buf_fill_hmac_session(struct tp
+               u32 handle = tpm_buf_read_u32(buf, &offset_s);
+               if (auth->name_h[i] != handle) {
+-                      dev_err(&chip->dev, "TPM: handle %d wrong for name\n",
+-                                i);
+-                      return;
++                      dev_err(&chip->dev, "invalid handle 0x%08x\n", handle);
++                      ret = -EIO;
++                      goto err;
+               }
+       }
+       /* point offset_s to the start of the sessions */
+@@ -674,12 +702,14 @@ void tpm_buf_fill_hmac_session(struct tp
+               offset_s += len;
+       }
+       if (offset_s != offset_p) {
+-              dev_err(&chip->dev, "TPM session length is incorrect\n");
+-              return;
++              dev_err(&chip->dev, "session length is incorrect\n");
++              ret = -EIO;
++              goto err;
+       }
+       if (!hmac) {
+-              dev_err(&chip->dev, "TPM could not find HMAC session\n");
+-              return;
++              dev_err(&chip->dev, "could not find HMAC session\n");
++              ret = -EIO;
++              goto err;
+       }
+       /* encrypt before HMAC */
+@@ -711,8 +741,11 @@ void tpm_buf_fill_hmac_session(struct tp
+               if (mso == TPM2_MSO_PERSISTENT ||
+                   mso == TPM2_MSO_VOLATILE ||
+                   mso == TPM2_MSO_NVRAM) {
+-                      sha256_update(&sctx, auth->name[i],
+-                                    name_size(auth->name[i]));
++                      ret = name_size(auth->name[i]);
++                      if (ret < 0)
++                              goto err;
++
++                      sha256_update(&sctx, auth->name[i], ret);
+               } else {
+                       __be32 h = cpu_to_be32(auth->name_h[i]);
+@@ -733,6 +766,11 @@ void tpm_buf_fill_hmac_session(struct tp
+       sha256_update(&sctx, &auth->attrs, 1);
+       tpm2_hmac_final(&sctx, auth->session_key, sizeof(auth->session_key)
+                       + auth->passphrase_len, hmac);
++      return 0;
++
++err:
++      tpm2_end_auth_session(chip);
++      return ret;
+ }
+ EXPORT_SYMBOL(tpm_buf_fill_hmac_session);
+--- a/include/linux/tpm.h
++++ b/include/linux/tpm.h
+@@ -523,8 +523,8 @@ static inline struct tpm2_auth *tpm2_chi
+ #endif
+ }
+-void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
+-                       u32 handle, u8 *name);
++int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
++                      u32 handle, u8 *name);
+ void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
+                                u8 attributes, u8 *passphrase,
+                                int passphraselen);
+@@ -557,7 +557,7 @@ static inline void tpm_buf_append_hmac_s
+ #ifdef CONFIG_TCG_TPM2_HMAC
+ int tpm2_start_auth_session(struct tpm_chip *chip);
+-void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf);
++int tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf);
+ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
+                               int rc);
+ void tpm2_end_auth_session(struct tpm_chip *chip);
+@@ -571,10 +571,13 @@ static inline int tpm2_start_auth_sessio
+ static inline void tpm2_end_auth_session(struct tpm_chip *chip)
+ {
+ }
+-static inline void tpm_buf_fill_hmac_session(struct tpm_chip *chip,
+-                                           struct tpm_buf *buf)
++
++static inline int tpm_buf_fill_hmac_session(struct tpm_chip *chip,
++                                          struct tpm_buf *buf)
+ {
++      return 0;
+ }
++
+ static inline int tpm_buf_check_hmac_response(struct tpm_chip *chip,
+                                             struct tpm_buf *buf,
+                                             int rc)
+--- a/security/keys/trusted-keys/trusted_tpm2.c
++++ b/security/keys/trusted-keys/trusted_tpm2.c
+@@ -283,7 +283,10 @@ int tpm2_seal_trusted(struct tpm_chip *c
+               goto out_put;
+       }
+-      tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
++      rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
++      if (rc)
++              goto out;
++
+       tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT,
+                                   options->keyauth, TPM_DIGEST_SIZE);
+@@ -331,7 +334,10 @@ int tpm2_seal_trusted(struct tpm_chip *c
+               goto out;
+       }
+-      tpm_buf_fill_hmac_session(chip, &buf);
++      rc = tpm_buf_fill_hmac_session(chip, &buf);
++      if (rc)
++              goto out;
++
+       rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data");
+       rc = tpm_buf_check_hmac_response(chip, &buf, rc);
+       if (rc)
+@@ -448,7 +454,10 @@ static int tpm2_load_cmd(struct tpm_chip
+               return rc;
+       }
+-      tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
++      rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
++      if (rc)
++              goto out;
++
+       tpm_buf_append_hmac_session(chip, &buf, 0, options->keyauth,
+                                   TPM_DIGEST_SIZE);
+@@ -460,7 +469,10 @@ static int tpm2_load_cmd(struct tpm_chip
+               goto out;
+       }
+-      tpm_buf_fill_hmac_session(chip, &buf);
++      rc = tpm_buf_fill_hmac_session(chip, &buf);
++      if (rc)
++              goto out;
++
+       rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob");
+       rc = tpm_buf_check_hmac_response(chip, &buf, rc);
+       if (!rc)
+@@ -508,7 +520,9 @@ static int tpm2_unseal_cmd(struct tpm_ch
+               return rc;
+       }
+-      tpm_buf_append_name(chip, &buf, blob_handle, NULL);
++      rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
++      if (rc)
++              goto out;
+       if (!options->policyhandle) {
+               tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT,
+@@ -533,7 +547,10 @@ static int tpm2_unseal_cmd(struct tpm_ch
+                                               NULL, 0);
+       }
+-      tpm_buf_fill_hmac_session(chip, &buf);
++      rc = tpm_buf_fill_hmac_session(chip, &buf);
++      if (rc)
++              goto out;
++
+       rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing");
+       rc = tpm_buf_check_hmac_response(chip, &buf, rc);
+       if (rc > 0)