From 4e22be36abf2ff7428b39675d878c6ed4c5f4c15 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Mon, 3 Mar 2025 10:45:42 +0530 Subject: [PATCH 01/10] qseecom: Remove virtual address print Printing virtual address can leak kernel addresses.So remove vaddr print to not leak kernel pointers to unprivileged users. Change-Id: I1823573a35fb16195a20a8362a4648dc12694271 Signed-off-by: Kuldeep Singh --- drivers/misc/qseecom.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 10dcb4691747..a1f12331d8e4 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -3,7 +3,7 @@ * QTI Secure Execution Environment Communicator (QSEECOM) driver * * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved. */ #define pr_fmt(fmt) "QSEECOM: %s: " fmt, __func__ @@ -2066,8 +2066,8 @@ static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data, if ((req.ifd_data_fd <= 0) || (req.virt_sb_base == NULL) || (req.sb_len == 0)) { - pr_err("Invalid input(s)ion_fd(%d), sb_len(%d), vaddr(0x%pK)\n", - req.ifd_data_fd, req.sb_len, req.virt_sb_base); + pr_err("Invalid input(s)ion_fd(%d), sb_len(%d), paddr: 0x%llx\n", + req.ifd_data_fd, req.sb_len, virt_to_phys(req.virt_sb_base)); return -EFAULT; } if (!access_ok((void __user *)req.virt_sb_base, From ab7a25805bf1c02e6374720a778f5b3f2303e83b Mon Sep 17 00:00:00 2001 From: Arun Khanna Date: Tue, 11 Mar 2025 11:12:21 +0530 Subject: [PATCH 02/10] defconfig: Disable upstream RTL8152 ETH-USB driver Disable upstream RTL815x Ethernet dongle support for sdxlemur. Change-Id: I07115ba5127921396644952c81d1652d06df1995 Signed-off-by: Arun Khanna --- arch/arm/configs/vendor/sdxlemur.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/vendor/sdxlemur.config b/arch/arm/configs/vendor/sdxlemur.config index 2646540a9f28..f51895fb5d48 100644 --- a/arch/arm/configs/vendor/sdxlemur.config +++ b/arch/arm/configs/vendor/sdxlemur.config @@ -250,7 +250,6 @@ CONFIG_USB_CONFIGFS_F_UAC2=y CONFIG_USB_CONFIGFS_F_CCID=y CONFIG_USB_G_QTI=y CONFIG_USB_BAM=y -CONFIG_USB_RTL8152=y CONFIG_USB_NET_SMSC75XX=y CONFIG_USB_NET_SMSC95XX=y CONFIG_ARM_PSCI=y From f7f8e585ba855f1becbafb8c7a241f78f4267b9f Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Thu, 13 Mar 2025 00:15:39 +0530 Subject: [PATCH 03/10] msm: Add Kconfig for RTL8152 driver Add a Kernel configuration option for the RTL8152 USB-to-ethernet adapter driver. Change-Id: If41cb9d5142acb2fc3036370c40625db9e3b51f6 Signed-off-by: Mohd Ayaan Anwar --- drivers/platform/msm/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig index c6a38ba5686f..5c16609c50d0 100644 --- a/drivers/platform/msm/Kconfig +++ b/drivers/platform/msm/Kconfig @@ -217,4 +217,13 @@ config AQFWD_IOSS aqc_ioss. If unsure, say N. +config USB_R8152_RTL + tristate "Realtek R8152 driver" + help + This option adds support for Realtek RTL8152 based USB to + Ethernet adapter. + + To compile this driver as a module, choose M here: the module + will be called r8152_rtl. If unsure, say N. + endmenu From e9f5566e7eb38999fc566888a6fad9d5ebd9acf5 Mon Sep 17 00:00:00 2001 From: Arun Khanna Date: Thu, 13 Mar 2025 00:15:53 +0530 Subject: [PATCH 04/10] defconfig: Enable RTL8152 ETH-USB driver Enable RTL815x Ethernet dongle support for sdxlemur. Change-Id: I4e7f0c825ede875df28e29972827f451b04898b5 Signed-off-by: Arun Khanna --- arch/arm/configs/vendor/sdxlemur.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/vendor/sdxlemur.config b/arch/arm/configs/vendor/sdxlemur.config index f51895fb5d48..2d12580404e8 100644 --- a/arch/arm/configs/vendor/sdxlemur.config +++ b/arch/arm/configs/vendor/sdxlemur.config @@ -250,6 +250,7 @@ CONFIG_USB_CONFIGFS_F_UAC2=y CONFIG_USB_CONFIGFS_F_CCID=y CONFIG_USB_G_QTI=y CONFIG_USB_BAM=y +CONFIG_USB_R8152_RTL=m CONFIG_USB_NET_SMSC75XX=y CONFIG_USB_NET_SMSC95XX=y CONFIG_ARM_PSCI=y From 91f42e0f9cae5ee5f9d8f4286762c3bfb2e66dd3 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 13 Mar 2025 23:22:48 +0530 Subject: [PATCH 05/10] FROMGIT: media: venus: hfi_parser: add check to avoid out of bound access There is a possibility that init_codecs is invoked multiple times during manipulated payload from video firmware. In such case, if codecs_count can get incremented to value more than MAX_CODEC_NUM, there can be OOB access. Reset the count so that it always starts from beginning. Cc: stable@vger.kernel.org Fixes: 1a73374a04e5 ("media: venus: hfi_parser: add common capability parser") Reviewed-by: Bryan O'Donoghue CRs-Fixed: 3935643 Change-Id: I6216e773af65082e4775b415789ffd549e0bed2d Git-commit: 172bf5a9ef70a399bb227809db78442dc01d9e48 Git-repo: https://gitlab.freedesktop.org/linux-media/media-committers.git Signed-off-by: Vikash Garodia --- drivers/media/platform/qcom/venus/hfi_parser.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index ad22b51765d4..6a8259bcf0be 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -19,6 +19,8 @@ static void init_codecs(struct venus_core *core) struct venus_caps *caps = core->caps, *cap; unsigned long bit; + core->codecs_count = 0; + if (hweight_long(core->dec_codecs) + hweight_long(core->enc_codecs) > MAX_CODEC_NUM) return; From fd9b658c8ab9faa6fbb96004ad4a853c9b30236f Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 13 Mar 2025 14:09:16 +0530 Subject: [PATCH 06/10] FROMGIT: media: venus: hfi_parser: refactor hfi packet parsing logic words_count denotes the number of words in total payload, while data points to payload of various property within it. When words_count reaches last word, data can access memory beyond the total payload. This can lead to OOB access. With this patch, the utility api for handling individual properties now returns the size of data consumed. Accordingly remaining bytes are calculated before parsing the payload, thereby eliminates the OOB access possibilities. Cc: stable@vger.kernel.org Fixes: 1a73374a04e5 ("media: venus: hfi_parser: add common capability parser") CRs-Fixed: 3935669 Change-Id: I692e4a8dea110f0650fe26e07207408087a4d19b Git-commit: 9edaaa8e3e15aab1ca413ab50556de1975bcb329 Git-repo: https://gitlab.freedesktop.org/linux-media/media-committers.git Signed-off-by: Vikash Garodia --- .../media/platform/qcom/venus/hfi_parser.c | 99 ++++++++++++++----- 1 file changed, 73 insertions(+), 26 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index 6a8259bcf0be..1cabe000f51a 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -64,7 +64,7 @@ fill_buf_mode(struct venus_caps *cap, const void *data, unsigned int num) cap->cap_bufs_mode_dynamic = true; } -static void +static int parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_buffer_alloc_mode_supported *mode = data; @@ -72,7 +72,7 @@ parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data) u32 *type; if (num_entries > MAX_ALLOC_MODE_ENTRIES) - return; + return -EINVAL; type = mode->data; @@ -84,6 +84,8 @@ parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data) type++; } + + return sizeof(*mode); } static void fill_profile_level(struct venus_caps *cap, const void *data, @@ -98,7 +100,7 @@ static void fill_profile_level(struct venus_caps *cap, const void *data, cap->num_pl += num; } -static void +static int parse_profile_level(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_profile_level_supported *pl = data; @@ -106,12 +108,14 @@ parse_profile_level(struct venus_core *core, u32 codecs, u32 domain, void *data) struct hfi_profile_level pl_arr[HFI_MAX_PROFILE_COUNT] = {}; if (pl->profile_count > HFI_MAX_PROFILE_COUNT) - return; + return -EINVAL; memcpy(pl_arr, proflevel, pl->profile_count * sizeof(*proflevel)); for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, fill_profile_level, pl_arr, pl->profile_count); + + return pl->profile_count * sizeof(*proflevel) + sizeof(u32); } static void @@ -126,7 +130,7 @@ fill_caps(struct venus_caps *cap, const void *data, unsigned int num) cap->num_caps += num; } -static void +static int parse_caps(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_capabilities *caps = data; @@ -135,12 +139,14 @@ parse_caps(struct venus_core *core, u32 codecs, u32 domain, void *data) struct hfi_capability caps_arr[MAX_CAP_ENTRIES] = {}; if (num_caps > MAX_CAP_ENTRIES) - return; + return -EINVAL; memcpy(caps_arr, cap, num_caps * sizeof(*cap)); for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, fill_caps, caps_arr, num_caps); + + return sizeof(*caps); } static void fill_raw_fmts(struct venus_caps *cap, const void *fmts, @@ -155,7 +161,7 @@ static void fill_raw_fmts(struct venus_caps *cap, const void *fmts, cap->num_fmts += num_fmts; } -static void +static int parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_uncompressed_format_supported *fmt = data; @@ -164,7 +170,8 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) struct raw_formats rawfmts[MAX_FMT_ENTRIES] = {}; u32 entries = fmt->format_entries; unsigned int i = 0; - u32 num_planes; + u32 num_planes = 0; + u32 size; while (entries) { num_planes = pinfo->num_planes; @@ -174,7 +181,7 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) i++; if (i >= MAX_FMT_ENTRIES) - return; + return -EINVAL; if (pinfo->num_planes > MAX_PLANES) break; @@ -186,9 +193,13 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, fill_raw_fmts, rawfmts, i); + size = fmt->format_entries * (sizeof(*constr) * num_planes + 2 * sizeof(u32)) + + 2 * sizeof(u32); + + return size; } -static void parse_codecs(struct venus_core *core, void *data) +static int parse_codecs(struct venus_core *core, void *data) { struct hfi_codec_supported *codecs = data; @@ -200,21 +211,27 @@ static void parse_codecs(struct venus_core *core, void *data) core->dec_codecs &= ~HFI_VIDEO_CODEC_SPARK; core->enc_codecs &= ~HFI_VIDEO_CODEC_HEVC; } + + return sizeof(*codecs); } -static void parse_max_sessions(struct venus_core *core, const void *data) +static int parse_max_sessions(struct venus_core *core, const void *data) { const struct hfi_max_sessions_supported *sessions = data; core->max_sessions_supported = sessions->max_sessions; + + return sizeof(*sessions); } -static void parse_codecs_mask(u32 *codecs, u32 *domain, void *data) +static int parse_codecs_mask(u32 *codecs, u32 *domain, void *data) { struct hfi_codec_mask_supported *mask = data; *codecs = mask->codecs; *domain = mask->video_domains; + + return sizeof(*mask); } static void parser_init(struct venus_inst *inst, u32 *codecs, u32 *domain) @@ -248,46 +265,76 @@ static void parser_fini(struct venus_inst *inst, u32 codecs, u32 domain) u32 hfi_parser(struct venus_core *core, struct venus_inst *inst, void *buf, u32 size) { - unsigned int words_count = size >> 2; - u32 *word = buf, *data, codecs = 0, domain = 0; + u32 *words = buf, *payload, codecs = 0, domain = 0; + u32 *frame_size = buf + size; + u32 rem_bytes = size; + int ret; if (size % 4) return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; parser_init(inst, &codecs, &domain); - while (words_count) { - data = word + 1; + while (words < frame_size) { + payload = words + 1; - switch (*word) { + switch (*words) { case HFI_PROPERTY_PARAM_CODEC_SUPPORTED: - parse_codecs(core, data); + if (rem_bytes <= sizeof(struct hfi_codec_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_codecs(core, payload); + if (ret < 0) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + init_codecs(core); break; case HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED: - parse_max_sessions(core, data); + if (rem_bytes <= sizeof(struct hfi_max_sessions_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_max_sessions(core, payload); break; case HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED: - parse_codecs_mask(&codecs, &domain, data); + if (rem_bytes <= sizeof(struct hfi_codec_mask_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_codecs_mask(&codecs, &domain, payload); break; case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED: - parse_raw_formats(core, codecs, domain, data); + if (rem_bytes <= sizeof(struct hfi_uncompressed_format_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_raw_formats(core, codecs, domain, payload); break; case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED: - parse_caps(core, codecs, domain, data); + if (rem_bytes <= sizeof(struct hfi_capabilities)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_caps(core, codecs, domain, payload); break; case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED: - parse_profile_level(core, codecs, domain, data); + if (rem_bytes <= sizeof(struct hfi_profile_level_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_profile_level(core, codecs, domain, payload); break; case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED: - parse_alloc_mode(core, codecs, domain, data); + if (rem_bytes <= sizeof(struct hfi_buffer_alloc_mode_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_alloc_mode(core, codecs, domain, payload); break; default: + ret = sizeof(u32); break; } - word++; - words_count--; + if (ret < 0) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + words += ret / sizeof(u32); + rem_bytes -= ret; } parser_fini(inst, codecs, domain); From 11f9d2350e2c6bce56f1aa27ffbab7085da38aae Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Tue, 5 Nov 2024 14:24:56 +0530 Subject: [PATCH 07/10] FROMGIT: media: venus: hfi: add check to handle incorrect queue size qsize represents size of shared queued between driver and video firmware. Firmware can modify this value to an invalid large value. In such situation, empty_space will be bigger than the space actually available. Since new_wr_idx is not checked, so the following code will result in an OOB write. ... qsize = qhdr->q_size if (wr_idx >= rd_idx) empty_space = qsize - (wr_idx - rd_idx) .... if (new_wr_idx < qsize) { memcpy(wr_ptr, packet, dwords << 2) --> OOB write Add check to ensure qsize is within the allocated size while reading and writing packets into the queue. Cc: stable@vger.kernel.org Fixes: d96d3f30c0f2 ("[media] media: venus: hfi: add Venus HFI files") Reviewed-by: Bryan O'Donoghue CRs-Fixed: 3935673 Change-Id: Ifb907d4a4c82f853081492e06e68180476367ed5 Git-commit: 69baf245b23e20efda0079238b27fc63ecf13de1 Git-repo: https://gitlab.freedesktop.org/linux-media/media-committers.git Signed-off-by: Vikash Garodia --- drivers/media/platform/qcom/venus/hfi_venus.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 306082e25943..2921486c3238 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -188,6 +188,9 @@ static int venus_write_queue(struct venus_hfi_device *hdev, /* ensure rd/wr indices's are read from memory */ rmb(); + if (qsize > IFACEQ_QUEUE_SIZE / 4) + return -EINVAL; + if (wr_idx >= rd_idx) empty_space = qsize - (wr_idx - rd_idx); else @@ -256,6 +259,9 @@ static int venus_read_queue(struct venus_hfi_device *hdev, wr_idx = qhdr->write_idx; qsize = qhdr->q_size; + if (qsize > IFACEQ_QUEUE_SIZE / 4) + return -EINVAL; + /* make sure data is valid before using it */ rmb(); From 56820042f93c80d21cd1442b6a6f4d8fa496598c Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Tue, 5 Nov 2024 14:24:57 +0530 Subject: [PATCH 08/10] FROMGIT: media: venus: hfi: add a check to handle OOB in sfr region sfr->buf_size is in shared memory and can be modified by malicious user. OOB write is possible when the size is made higher than actual sfr data buffer. Cap the size to allocated size for such cases. Cc: stable@vger.kernel.org Fixes: d96d3f30c0f2 ("[media] media: venus: hfi: add Venus HFI files") Reviewed-by: Bryan O'Donoghue CRs-Fixed: 3947576 Change-Id: I483a5feff3dfa35dae8f444e57601d2d1d85246f Git-commit: f4b211714bcc70effa60c34d9fa613d182e3ef1e Git-repo: https://gitlab.freedesktop.org/linux-media/media-committers.git Signed-off-by: Vikash Garodia --- drivers/media/platform/qcom/venus/hfi_venus.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 2921486c3238..1b37d77bf998 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -976,18 +976,26 @@ static void venus_sfr_print(struct venus_hfi_device *hdev) { struct device *dev = hdev->core->dev; struct hfi_sfr *sfr = hdev->sfr.kva; + u32 size; void *p; if (!sfr) return; - p = memchr(sfr->data, '\0', sfr->buf_size); + size = sfr->buf_size; + if (!size) + return; + + if (size > ALIGNED_SFR_SIZE) + size = ALIGNED_SFR_SIZE; + + p = memchr(sfr->data, '\0', size); /* * SFR isn't guaranteed to be NULL terminated since SYS_ERROR indicates * that Venus is in the process of crashing. */ if (!p) - sfr->data[sfr->buf_size - 1] = '\0'; + sfr->data[size - 1] = '\0'; dev_err_ratelimited(dev, "SFR message from FW: %s\n", sfr->data); } From 487f688a87f2aee20928c1c1b3ffb01ca25746e9 Mon Sep 17 00:00:00 2001 From: Subramanian Ananthanarayanan Date: Tue, 12 Jan 2021 10:39:18 +0530 Subject: [PATCH 09/10] msm: mhi_dev: Avoid BME check while sending ready On some x86 based Root complex devices we observe that BME gets set during PBL initialization sequence and gets cleared if the BAR configuration is yet to be complete. So depending on the timing of AMSS boot duration, when we read the PCIE20_COMMAND_STATUS register bit(5) during BME IRQ, three scenarios can happen. 1. AMSS boots quicker: The BME bit is set, we set dev->enumerated flag and indicate EP_PCIE_LINK_ENABLED and initiate MHI which in turn continues to do MMIO initialization sequence. This sequence involves call to mhi_dev_sm_set_ready() and mhi_dev_sm_init() APIs which check for ep_pcie_get_linkstatus() API which might end up failing thus preventing MHI from moving to ready state. 2. The BME bit is already cleared and set again before the first BME IRQ. So there is no disruption in the code flow. 3. The BME bit is cleared and hence we do not set dev->enumerated. The normal code flow happens as part of 2nd BME IRQ. In (2) and (3) there are no issues, but in (1) during mhi_dev_resume_mmio_mhi_init() we call ep_pcie_register_event() which will overwrite the previous EP_PCIE_EVENT_LINKUP registration. So during the 2nd BME IRQ that gets fired, EP PCIE driver does not give a callback to MHI as EP_PCIE_EVENT_LINKUP is not registered by MHI anymore. In current implementation, APIs mhi_dev_sm_set_ready() or mhi_dev_sm_init() fail as BME is deasserted. This results in MHI host driver not getting ready state. mhi_dev_resume_mmio_mhi_init() is called only if BME is set, mhi_dev_sm_set_ready() and mhi_dev_sm_init() APIs are called as part of this. As these APIs are called only if BME is set, BME check inside these APIs is not really needed. To avoid the issue of not sending ready state, removing checks for BME in mhi_dev_sm_set_ready() and mhi_dev_sm_init() APIs, so that ready state is sent to host and M0 is received after this. Added a warning log before polling for M0 to know if BME is not set again by host. Change-Id: I211e9e20e05211d2a0c6f0972e1468a4d452ff5d Signed-off-by: Subramanian Ananthanarayanan Signed-off-by: Sai Chaitanya Kaveti --- drivers/platform/msm/mhi_dev/mhi.c | 3 +++ drivers/platform/msm/mhi_dev/mhi_sm.c | 25 ++----------------------- drivers/platform/msm/mhi_dev/mhi_sm.h | 9 ++++++++- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 68e52b8191c9..d7d9ecad8d73 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -3936,6 +3936,9 @@ static void mhi_dev_enable(struct work_struct *work) "Cleared reset before waiting for M0\n"); } + if (ep_pcie_get_linkstatus(mhi->phandle) != EP_PCIE_LINK_ENABLED) + mhi_log(MHI_MSG_ERROR, "warning: PCIe BME unset error"); + while (state != MHI_DEV_M0_STATE && ((max_cnt < MHI_SUSPEND_TIMEOUT) || mhi->no_m0_timeout)) { /* Wait for Host to set the M0 state */ diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.c b/drivers/platform/msm/mhi_dev/mhi_sm.c index 5669fcfbd16a..89190bfeadfc 100644 --- a/drivers/platform/msm/mhi_dev/mhi_sm.c +++ b/drivers/platform/msm/mhi_dev/mhi_sm.c @@ -96,12 +96,6 @@ static inline const char *mhi_sm_mstate_str(enum mhi_dev_state state) return str; } -enum mhi_sm_ep_pcie_state { - MHI_SM_EP_PCIE_LINK_DISABLE, - MHI_SM_EP_PCIE_D0_STATE, - MHI_SM_EP_PCIE_D3_HOT_STATE, - MHI_SM_EP_PCIE_D3_COLD_STATE, -}; static inline const char *mhi_sm_dstate_str(enum mhi_sm_ep_pcie_state state) { @@ -1106,8 +1100,6 @@ unlock_and_exit: int mhi_dev_sm_init(struct mhi_dev *mhi_dev) { int res; - enum ep_pcie_link_status link_state; - MHI_SM_FUNC_ENTRY(); if (!mhi_dev) { @@ -1137,11 +1129,7 @@ int mhi_dev_sm_init(struct mhi_dev *mhi_dev) atomic_set(&mhi_sm_ctx->pending_device_events, 0); atomic_set(&mhi_sm_ctx->pending_pcie_events, 0); - link_state = ep_pcie_get_linkstatus(mhi_sm_ctx->mhi_dev->phandle); - if (link_state == EP_PCIE_LINK_ENABLED) - mhi_sm_ctx->d_state = MHI_SM_EP_PCIE_D0_STATE; - else - mhi_sm_ctx->d_state = MHI_SM_EP_PCIE_LINK_DISABLE; + mhi_sm_ctx->d_state = MHI_SM_EP_PCIE_D0_STATE; MHI_SM_FUNC_EXIT(); return 0; @@ -1238,16 +1226,7 @@ int mhi_dev_sm_set_ready(void) goto unlock_and_exit; } - if (mhi_sm_ctx->d_state != MHI_SM_EP_PCIE_D0_STATE) { - if (ep_pcie_get_linkstatus(mhi_sm_ctx->mhi_dev->phandle) == - EP_PCIE_LINK_ENABLED) { - mhi_sm_ctx->d_state = MHI_SM_EP_PCIE_D0_STATE; - } else { - MHI_SM_ERR("ERROR: ep-pcie link is not enabled\n"); - res = -EPERM; - goto unlock_and_exit; - } - } + mhi_sm_ctx->d_state = MHI_SM_EP_PCIE_D0_STATE; /* verify that MHISTATUS is configured to RESET*/ mhi_dev_mmio_masked_read(mhi_sm_ctx->mhi_dev, diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.h b/drivers/platform/msm/mhi_dev/mhi_sm.h index e061fed208ea..80ed0086472f 100644 --- a/drivers/platform/msm/mhi_dev/mhi_sm.h +++ b/drivers/platform/msm/mhi_dev/mhi_sm.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2015,2017-2018,2020 The Linux Foundation. All rights reserved.*/ +/* Copyright (c) 2015,2017-2018,2020-2021 The Linux Foundation. All rights reserved.*/ #ifndef MHI_SM_H #define MHI_SM_H @@ -31,6 +31,13 @@ enum mhi_dev_event { MHI_DEV_EVENT_MAX }; +enum mhi_sm_ep_pcie_state { + MHI_SM_EP_PCIE_LINK_DISABLE, + MHI_SM_EP_PCIE_D0_STATE, + MHI_SM_EP_PCIE_D3_HOT_STATE, + MHI_SM_EP_PCIE_D3_COLD_STATE, +}; + int mhi_dev_sm_init(struct mhi_dev *dev); int mhi_dev_sm_exit(struct mhi_dev *dev); int mhi_dev_sm_set_ready(void); From 59683ca0a0d60673dbe6da6fe8286a4a96814f09 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 30 Jul 2025 15:51:51 -0500 Subject: [PATCH 10/10] UPSTREAM: soc: qcom: mdt_loader: Deal with zero e_shentsize commit 25daf9af0ac1bf12490b723b5efaf8dcc85980bc upstream. Firmware that doesn't provide section headers leave both e_shentsize and e_shnum 0, which obvious isn't compatible with the newly introduced stricter checks. Make the section-related checks conditional on either of these values being non-zero. Fixes: 9f9967fed9d0 ("soc: qcom: mdt_loader: Ensure we don't read past the ELF header") Reported-by: Val Packett Closes: https://lore.kernel.org/all/ece307c3-7d65-440f-babd-88cf9705b908@packett.cool/ Reported-by: Neil Armstrong Closes: https://lore.kernel.org/all/aec9cd03-6fc2-4dc8-b937-8b7cf7bf4128@linaro.org/ Signed-off-by: Bjorn Andersson Fixes: 9f35ab0e53cc ("soc: qcom: mdt_loader: Fix error return values in mdt_header_valid()") Tested-by: Neil Armstrong # on SM8650-QRD Reviewed-by: Dmitry Baryshkov Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250730-mdt-loader-shentsize-zero-v1-1-04f43186229c@oss.qualcomm.com Signed-off-by: Bjorn Andersson Cc: Yongqin Liu Signed-off-by: Greg Kroah-Hartman Bug: 146449535 Change-Id: Iacfaffd1094a328aa884e08b99d42b45fe7e8c3f (cherry picked from commit 64faf7d6432bbc9a785e5079c48048e6b4a9ccfa from the upstream 5.4 lts branch of linux-5.4.y) Signed-off-by: Yongqin Liu --- drivers/soc/qcom/mdt_loader.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index c2bbde533e66..e13cde26f78c 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -39,12 +39,14 @@ static bool mdt_header_valid(const struct firmware *fw) if (phend > fw->size) return false; - if (ehdr->e_shentsize != sizeof(struct elf32_shdr)) - return false; + if (ehdr->e_shentsize || ehdr->e_shnum) { + if (ehdr->e_shentsize != sizeof(struct elf32_shdr)) + return false; - shend = size_add(size_mul(sizeof(struct elf32_shdr), ehdr->e_shnum), ehdr->e_shoff); - if (shend > fw->size) - return false; + shend = size_add(size_mul(sizeof(struct elf32_shdr), ehdr->e_shnum), ehdr->e_shoff); + if (shend > fw->size) + return false; + } return true; }