From 16996a5384b51cfa039b30f0f33cefe2207cda45 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 Jun 2023 20:45:52 +0200 Subject: [PATCH] 6.1-stable patches added patches: mm-fix-copy_from_user_nofault.patch tpm-tpm_tis-claim-locality-in-interrupt-handler.patch tpm_crb-add-support-for-crb-devices-based-on-pluton.patch --- queue-6.1/mm-fix-copy_from_user_nofault.patch | 86 ++++++ queue-6.1/series | 3 + ...-claim-locality-in-interrupt-handler.patch | 39 +++ ...port-for-crb-devices-based-on-pluton.patch | 244 ++++++++++++++++++ 4 files changed, 372 insertions(+) create mode 100644 queue-6.1/mm-fix-copy_from_user_nofault.patch create mode 100644 queue-6.1/tpm-tpm_tis-claim-locality-in-interrupt-handler.patch create mode 100644 queue-6.1/tpm_crb-add-support-for-crb-devices-based-on-pluton.patch diff --git a/queue-6.1/mm-fix-copy_from_user_nofault.patch b/queue-6.1/mm-fix-copy_from_user_nofault.patch new file mode 100644 index 00000000000..ba79c0ff354 --- /dev/null +++ b/queue-6.1/mm-fix-copy_from_user_nofault.patch @@ -0,0 +1,86 @@ +From d319f344561de23e810515d109c7278919bff7b0 Mon Sep 17 00:00:00 2001 +From: Alexei Starovoitov +Date: Mon, 10 Apr 2023 19:43:44 +0200 +Subject: mm: Fix copy_from_user_nofault(). + +From: Alexei Starovoitov + +commit d319f344561de23e810515d109c7278919bff7b0 upstream. + +There are several issues with copy_from_user_nofault(): + +- access_ok() is designed for user context only and for that reason +it has WARN_ON_IN_IRQ() which triggers when bpf, kprobe, eprobe +and perf on ppc are calling it from irq. + +- it's missing nmi_uaccess_okay() which is a nop on all architectures +except x86 where it's required. +The comment in arch/x86/mm/tlb.c explains the details why it's necessary. +Calling copy_from_user_nofault() from bpf, [ke]probe without this check is not safe. + +- __copy_from_user_inatomic() under CONFIG_HARDENED_USERCOPY is calling +check_object_size()->__check_object_size()->check_heap_object()->find_vmap_area()->spin_lock() +which is not safe to do from bpf, [ke]probe and perf due to potential deadlock. + +Fix all three issues. At the end the copy_from_user_nofault() becomes +equivalent to copy_from_user_nmi() from safety point of view with +a difference in the return value. + +Reported-by: Hsin-Wei Hung +Signed-off-by: Alexei Starovoitov +Signed-off-by: Florian Lehner +Tested-by: Hsin-Wei Hung +Tested-by: Florian Lehner +Link: https://lore.kernel.org/r/20230410174345.4376-2-dev@der-flo.net +Signed-off-by: Alexei Starovoitov +Cc: Javier Honduvilla Coto +Cc: Daniel Borkmann +Signed-off-by: Greg Kroah-Hartman +--- + mm/maccess.c | 16 +++++++++++----- + mm/usercopy.c | 2 +- + 2 files changed, 12 insertions(+), 6 deletions(-) + +--- a/mm/maccess.c ++++ b/mm/maccess.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + + bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src, + size_t size) +@@ -113,11 +114,16 @@ Efault: + long copy_from_user_nofault(void *dst, const void __user *src, size_t size) + { + long ret = -EFAULT; +- if (access_ok(src, size)) { +- pagefault_disable(); +- ret = __copy_from_user_inatomic(dst, src, size); +- pagefault_enable(); +- } ++ ++ if (!__access_ok(src, size)) ++ return ret; ++ ++ if (!nmi_uaccess_okay()) ++ return ret; ++ ++ pagefault_disable(); ++ ret = __copy_from_user_inatomic(dst, src, size); ++ pagefault_enable(); + + if (ret) + return -EFAULT; +--- a/mm/usercopy.c ++++ b/mm/usercopy.c +@@ -172,7 +172,7 @@ static inline void check_heap_object(con + return; + } + +- if (is_vmalloc_addr(ptr)) { ++ if (is_vmalloc_addr(ptr) && !pagefault_disabled()) { + struct vmap_area *area = find_vmap_area(addr); + + if (!area) diff --git a/queue-6.1/series b/queue-6.1/series index c212c16c409..7421d40dfaa 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -4,3 +4,6 @@ drm-amd-display-fix-the-system-hang-while-disable-ps.patch tty-serial-fsl_lpuart-make-rx_watermark-configurable.patch tty-serial-fsl_lpuart-reduce-rx-watermark-to-0-on-ls.patch ata-libata-scsi-avoid-deadlock-on-rescan-after-devic.patch +mm-fix-copy_from_user_nofault.patch +tpm-tpm_tis-claim-locality-in-interrupt-handler.patch +tpm_crb-add-support-for-crb-devices-based-on-pluton.patch diff --git a/queue-6.1/tpm-tpm_tis-claim-locality-in-interrupt-handler.patch b/queue-6.1/tpm-tpm_tis-claim-locality-in-interrupt-handler.patch new file mode 100644 index 00000000000..a6b92015f59 --- /dev/null +++ b/queue-6.1/tpm-tpm_tis-claim-locality-in-interrupt-handler.patch @@ -0,0 +1,39 @@ +From 0e069265bce5a40c4eee52e2364bbbd4dabee94a Mon Sep 17 00:00:00 2001 +From: Lino Sanfilippo +Date: Thu, 24 Nov 2022 14:55:35 +0100 +Subject: tpm, tpm_tis: Claim locality in interrupt handler +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Lino Sanfilippo + +commit 0e069265bce5a40c4eee52e2364bbbd4dabee94a upstream. + +Writing the TPM_INT_STATUS register in the interrupt handler to clear the +interrupts only has effect if a locality is held. Since this is not +guaranteed at the time the interrupt is fired, claim the locality +explicitly in the handler. + +Signed-off-by: Lino Sanfilippo +Tested-by: Michael Niewöhner +Tested-by: Jarkko Sakkinen +Reviewed-by: Jarkko Sakkinen +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/tpm/tpm_tis_core.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/char/tpm/tpm_tis_core.c ++++ b/drivers/char/tpm/tpm_tis_core.c +@@ -772,7 +772,9 @@ static irqreturn_t tis_int_handler(int d + wake_up_interruptible(&priv->int_queue); + + /* Clear interrupts handled with TPM_EOI */ ++ tpm_tis_request_locality(chip, 0); + rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt); ++ tpm_tis_relinquish_locality(chip, 0); + if (rc < 0) + return IRQ_NONE; + diff --git a/queue-6.1/tpm_crb-add-support-for-crb-devices-based-on-pluton.patch b/queue-6.1/tpm_crb-add-support-for-crb-devices-based-on-pluton.patch new file mode 100644 index 00000000000..629f32b2e26 --- /dev/null +++ b/queue-6.1/tpm_crb-add-support-for-crb-devices-based-on-pluton.patch @@ -0,0 +1,244 @@ +From 4d2732882703791ea4b670df433f88fc4b40a5cb Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Sat, 31 Dec 2022 01:14:32 -0800 +Subject: tpm_crb: Add support for CRB devices based on Pluton + +From: Matthew Garrett + +commit 4d2732882703791ea4b670df433f88fc4b40a5cb upstream. + +Pluton is an integrated security processor present in some recent Ryzen +parts. If it's enabled, it presents two devices - an MSFT0101 ACPI device +that's broadly an implementation of a Command Response Buffer TPM2, and an +MSFT0200 ACPI device whose functionality I haven't examined in detail yet. +This patch only attempts to add support for the TPM device. + +There's a few things that need to be handled here. The first is that the +TPM2 ACPI table uses a previously undefined start method identifier. The +table format appears to include 16 bytes of startup data, which corresponds +to one 64-bit address for a start message and one 64-bit address for a +completion response. The second is that the ACPI tables on the Thinkpad Z13 +I'm testing this on don't define any memory windows in _CRS (or, more +accurately, there are two empty memory windows). This check doesn't seem +strictly necessary, so I've skipped that. + +Finally, it seems like chip needs to be explicitly asked to transition into +ready status on every command. Failing to do this means that if two +commands are sent in succession without an idle/ready transition in +between, everything will appear to work fine but the response is simply the +original command. I'm working without any docs here, so I'm not sure if +this is actually the required behaviour or if I'm missing something +somewhere else, but doing this results in the chip working reliably. + +Reviewed-by: Jarkko Sakkinen +Signed-off-by: Matthew Garrett +Signed-off-by: Jarkko Sakkinen +Cc: "Limonciello, Mario" +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/tpm/tpm_crb.c | 100 ++++++++++++++++++++++++++++++++++++++++----- + include/acpi/actbl3.h | 1 + 2 files changed, 91 insertions(+), 10 deletions(-) + +--- a/drivers/char/tpm/tpm_crb.c ++++ b/drivers/char/tpm/tpm_crb.c +@@ -98,6 +98,8 @@ struct crb_priv { + u8 __iomem *rsp; + u32 cmd_size; + u32 smc_func_id; ++ u32 __iomem *pluton_start_addr; ++ u32 __iomem *pluton_reply_addr; + }; + + struct tpm2_crb_smc { +@@ -108,6 +110,11 @@ struct tpm2_crb_smc { + u32 smc_func_id; + }; + ++struct tpm2_crb_pluton { ++ u64 start_addr; ++ u64 reply_addr; ++}; ++ + static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, + unsigned long timeout) + { +@@ -127,6 +134,25 @@ static bool crb_wait_for_reg_32(u32 __io + return ((ioread32(reg) & mask) == value); + } + ++static int crb_try_pluton_doorbell(struct crb_priv *priv, bool wait_for_complete) ++{ ++ if (priv->sm != ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) ++ return 0; ++ ++ if (!crb_wait_for_reg_32(priv->pluton_reply_addr, ~0, 1, TPM2_TIMEOUT_C)) ++ return -ETIME; ++ ++ iowrite32(1, priv->pluton_start_addr); ++ if (wait_for_complete == false) ++ return 0; ++ ++ if (!crb_wait_for_reg_32(priv->pluton_start_addr, ++ 0xffffffff, 0, 200)) ++ return -ETIME; ++ ++ return 0; ++} ++ + /** + * __crb_go_idle - request tpm crb device to go the idle state + * +@@ -145,6 +171,8 @@ static bool crb_wait_for_reg_32(u32 __io + */ + static int __crb_go_idle(struct device *dev, struct crb_priv *priv) + { ++ int rc; ++ + if ((priv->sm == ACPI_TPM2_START_METHOD) || + (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || + (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC)) +@@ -152,6 +180,10 @@ static int __crb_go_idle(struct device * + + iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); + ++ rc = crb_try_pluton_doorbell(priv, true); ++ if (rc) ++ return rc; ++ + if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req, + CRB_CTRL_REQ_GO_IDLE/* mask */, + 0, /* value */ +@@ -188,12 +220,19 @@ static int crb_go_idle(struct tpm_chip * + */ + static int __crb_cmd_ready(struct device *dev, struct crb_priv *priv) + { ++ int rc; ++ + if ((priv->sm == ACPI_TPM2_START_METHOD) || + (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || + (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC)) + return 0; + + iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req); ++ ++ rc = crb_try_pluton_doorbell(priv, true); ++ if (rc) ++ return rc; ++ + if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req, + CRB_CTRL_REQ_CMD_READY /* mask */, + 0, /* value */ +@@ -371,6 +410,10 @@ static int crb_send(struct tpm_chip *chi + return -E2BIG; + } + ++ /* Seems to be necessary for every command */ ++ if (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) ++ __crb_cmd_ready(&chip->dev, priv); ++ + memcpy_toio(priv->cmd, buf, len); + + /* Make sure that cmd is populated before issuing start. */ +@@ -394,7 +437,10 @@ static int crb_send(struct tpm_chip *chi + rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id); + } + +- return rc; ++ if (rc) ++ return rc; ++ ++ return crb_try_pluton_doorbell(priv, false); + } + + static void crb_cancel(struct tpm_chip *chip) +@@ -524,15 +570,18 @@ static int crb_map_io(struct acpi_device + return ret; + acpi_dev_free_resource_list(&acpi_resource_list); + +- if (resource_type(iores_array) != IORESOURCE_MEM) { +- dev_err(dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n"); +- return -EINVAL; +- } else if (resource_type(iores_array + TPM_CRB_MAX_RESOURCES) == +- IORESOURCE_MEM) { +- dev_warn(dev, "TPM2 ACPI table defines too many memory resources\n"); +- memset(iores_array + TPM_CRB_MAX_RESOURCES, +- 0, sizeof(*iores_array)); +- iores_array[TPM_CRB_MAX_RESOURCES].flags = 0; ++ /* Pluton doesn't appear to define ACPI memory regions */ ++ if (priv->sm != ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) { ++ if (resource_type(iores_array) != IORESOURCE_MEM) { ++ dev_err(dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n"); ++ return -EINVAL; ++ } else if (resource_type(iores_array + TPM_CRB_MAX_RESOURCES) == ++ IORESOURCE_MEM) { ++ dev_warn(dev, "TPM2 ACPI table defines too many memory resources\n"); ++ memset(iores_array + TPM_CRB_MAX_RESOURCES, ++ 0, sizeof(*iores_array)); ++ iores_array[TPM_CRB_MAX_RESOURCES].flags = 0; ++ } + } + + iores = NULL; +@@ -656,6 +705,22 @@ out_relinquish_locality: + return ret; + } + ++static int crb_map_pluton(struct device *dev, struct crb_priv *priv, ++ struct acpi_table_tpm2 *buf, struct tpm2_crb_pluton *crb_pluton) ++{ ++ priv->pluton_start_addr = crb_map_res(dev, NULL, NULL, ++ crb_pluton->start_addr, 4); ++ if (IS_ERR(priv->pluton_start_addr)) ++ return PTR_ERR(priv->pluton_start_addr); ++ ++ priv->pluton_reply_addr = crb_map_res(dev, NULL, NULL, ++ crb_pluton->reply_addr, 4); ++ if (IS_ERR(priv->pluton_reply_addr)) ++ return PTR_ERR(priv->pluton_reply_addr); ++ ++ return 0; ++} ++ + static int crb_acpi_add(struct acpi_device *device) + { + struct acpi_table_tpm2 *buf; +@@ -663,6 +728,7 @@ static int crb_acpi_add(struct acpi_devi + struct tpm_chip *chip; + struct device *dev = &device->dev; + struct tpm2_crb_smc *crb_smc; ++ struct tpm2_crb_pluton *crb_pluton; + acpi_status status; + u32 sm; + int rc; +@@ -700,6 +766,20 @@ static int crb_acpi_add(struct acpi_devi + priv->smc_func_id = crb_smc->smc_func_id; + } + ++ if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) { ++ if (buf->header.length < (sizeof(*buf) + sizeof(*crb_pluton))) { ++ dev_err(dev, ++ FW_BUG "TPM2 ACPI table has wrong size %u for start method type %d\n", ++ buf->header.length, ++ ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON); ++ return -EINVAL; ++ } ++ crb_pluton = ACPI_ADD_PTR(struct tpm2_crb_pluton, buf, sizeof(*buf)); ++ rc = crb_map_pluton(dev, priv, buf, crb_pluton); ++ if (rc) ++ return rc; ++ } ++ + priv->sm = sm; + priv->hid = acpi_device_hid(device); + +--- a/include/acpi/actbl3.h ++++ b/include/acpi/actbl3.h +@@ -443,6 +443,7 @@ struct acpi_tpm2_phy { + #define ACPI_TPM2_RESERVED10 10 + #define ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC 11 /* V1.2 Rev 8 */ + #define ACPI_TPM2_RESERVED 12 ++#define ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON 13 + + /* Optional trailer appears after any start_method subtables */ + -- 2.47.2