6.12.110-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 395/1376 perf cs-etm: Queue context packets for frontend
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Clark <[email protected]>
[ Upstream commit 68ca50bc0fa64841cd73b8a1538df1d7f7eb4108 ]
PE_CONTEXT elements update the context ID and exception level, but the decoder may still have prior packets cached for frontend processing. Updating the context immediately in the decoder backend can make those cached packets get consumed with the wrong thread or EL state.
Add a CS_ETM_CONTEXT packet carrying the TID and EL to the frontend, this keeps context changes ordered with the rest of the packet stream and avoids mismatches when synthesizing samples from cached packets.
Separate the memory access function into one for the frontend and one for decoding. The frontend also needs memory access to attach the instruction to samples. Because the frontend does memory access for both previous and current packets, change all the frontend memory access function signatures to take both a tidq and packet. But backend always uses the current backend EL and thread from the tidq.
Treat context packets as a boundary for branch sample generation and remove tidq->prev_packet_thread because it's not possible to branch to a different thread, so only tracking the current thread is required for sample generation.
Stable-dep-of: 50cd0d54f1f6 ("perf cs-etm: Fix thread leaks on trace queue init failure")
--- .../perf/util/cs-etm-decoder/cs-etm-decoder.c | 21 +- tools/perf/util/cs-etm.c | 236 +++++++++++------- tools/perf/util/cs-etm.h | 8 +- 3 files changed, 163 insertions(+), 102 deletions(-)
tools/perf/util/cs-etm-decoder/cs-etm-decoder.c +16 -5
@@ -399,6 +399,8 @@ cs_etm_decoder__buffer_packet(struct cs_etm_queue *etmq, packet_queue->packet_buffer[et].flags =0 ; packet_queue->packet_buffer[et].exception_number =UINT32_MAX ; packet_queue->packet_buffer[et].trace_chan_id = trace_chan_id; + packet_queue->packet_buffer[et].el = ocsd_EL_unknown; + packet_queue->packet_buffer[et].tid =-1 ;if (packet_queue->packet_count ==CS_ETM_PACKET_MAX_BUFFER -1 )return OCSD_RESP_WAIT ;
@@ -446,6 +448,7 @@ cs_etm_decoder__buffer_range(struct cs_etm_queue *etmq, packet->last_instr_type = elem->last_i_type; packet->last_instr_subtype = elem->last_i_subtype; packet->last_instr_cond = elem->last_instr_cond; + packet->el = elem->context.exception_level;if (elem->last_i_type ==OCSD_INSTR_BR || elem->last_i_type ==OCSD_INSTR_BR_INDIRECT ) packet->last_instr_taken_branch = elem->last_instr_exec;
@@ -522,7 +525,9 @@ cs_etm_decoder__set_tid(struct cs_etm_queue *etmq,const ocsd_generic_trace_elem *elem, const uint8_t trace_chan_id) { + struct cs_etm_packet *packet;pid_t tid =-1 ; +int ret;/* * Process the PE_CONTEXT packets if we have a valid contextID or VMID.
@@ -543,12 +548,18 @@ cs_etm_decoder__set_tid(struct cs_etm_queue *etmq,break ; } -if (cs_etm__etmq_set_tid_el (etmq, tid, trace_chan_id, - elem->context.exception_level)) +if (cs_etm__etmq_update_decode_context (etmq, trace_chan_id, + elem->context.exception_level, tid))return OCSD_RESP_FATAL_SYS_ERR ; -if (tid ==-1 ) -return OCSD_RESP_CONT ; + ret =cs_etm_decoder__buffer_packet (etmq, packet_queue, trace_chan_id, +CS_ETM_CONTEXT ); +if (ret !=OCSD_RESP_CONT && ret !=OCSD_RESP_WAIT ) +return ret; + + packet = &packet_queue->packet_buffer[packet_queue->tail]; + packet->tid = tid; + packet->el = elem->context.exception_level;/* * A timestamp is generated after a PE_CONTEXT element so make sure
@@ -556,7 +567,7 @@ cs_etm_decoder__set_tid(struct cs_etm_queue *etmq,*/ cs_etm_decoder__reset_timestamp (packet_queue); -return OCSD_RESP_CONT ; +return ret; } static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
tools/perf/util/cs-etm.c +141 -95
533 lines not on this page · raw message
tools/perf/util/cs-etm.h +6 -2
@@ -158,6 +158,7 @@ enum cs_etm_sample_type {CS_ETM_DISCONTINUITY ,CS_ETM_EXCEPTION ,CS_ETM_EXCEPTION_RET , + CS_ETM_CONTEXT, }; enum cs_etm_isa {
@@ -184,6 +185,8 @@ struct cs_etm_packet {u8 last_instr_size;u8 trace_chan_id;int cpu; +int el; +pid_t tid; };#define CS_ETM_PACKET_MAX_BUFFER 1024
@@ -244,8 +247,9 @@ enum cs_etm_pid_fmt {#include <opencsd/ocsd_if_types.h> int cs_etm__get_cpu (struct cs_etm_queue *etmq,u8 trace_chan_id,int *cpu);enum cs_etm_pid_fmt cs_etm__get_pid_fmt (struct cs_etm_queue *etmq); -int cs_etm__etmq_set_tid_el (struct cs_etm_queue *etmq,pid_t tid, -u8 trace_chan_id,ocsd_ex_level el); +int cs_etm__etmq_update_decode_context (struct cs_etm_queue *etmq, +u8 trace_chan_id,ocsd_ex_level el, +pid_t tid);bool cs_etm__etmq_is_timeless (struct cs_etm_queue *etmq);void cs_etm__etmq_set_traceid_queue_timestamp (struct cs_etm_queue *etmq,u8 trace_chan_id);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 396/1376 perf cs-etm: Fix thread leaks on trace queue init failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leo Yan <[email protected]>
[ Upstream commit 50cd0d54f1f6dd9b3de7c0ad101bd41d06206ace ]
cs_etm__init_traceid_queue() allocates the frontend and decode threads, if a later allocation fails, the error path does not drop thread reference that was already acquired.
Release both thread pointers with thread__zput() on the error path, so does not leak thread references or leave stale pointers behind.
--- tools/perf/util/cs-etm.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/util/cs-etm.c +4 -0
@@ -620,6 +620,8 @@ static int cs_etm__init_traceid_queue(struct cs_etm_queue *etmq, queue->tid); tidq->decode_thread =machine__findnew_thread (&etm->session->machines.host,-1 , queue->tid); +if (!tidq->frontend_thread || !tidq->decode_thread) + goto out; tidq->packet =zalloc (sizeof (struct cs_etm_packet ));if (!tidq->packet)
@@ -654,6 +656,8 @@ static int cs_etm__init_traceid_queue(struct cs_etm_queue *etmq,zfree (&tidq->prev_packet);zfree (&tidq->packet); out: +thread__zput (tidq->frontend_thread); +thread__zput (tidq->decode_thread);return rc; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 397/1376 perf/x86/amd/uncore: Add group validation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sandipan Das <[email protected]>
[ Upstream commit edda9051e267b7390c7ce24b1b71434414ad156e ]
The amd_uncore driver currently does not validate event groups and allows creation of groups with more events than the number of available hardware counters. Because of this, pmu->event_init() succeeds but counter assignment fails later in pmu->add() which returns -EBUSY once all counters are exhausted.
Address this by introducing group validation in the pmu->event_init() path. Since the uncore PMUs have no per-event constraints and all counters of a PMU are interchangeable, validation is reduced to just counting the group members that target a PMU and ensuring that they fit within the available set of counters.
--- arch/x86/events/amd/uncore.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
arch/x86/events/amd/uncore.c +31 -0
@@ -206,6 +206,29 @@ static void amd_uncore_del(struct perf_event *event, int flags) hwc->idx =-1 ; } +static bool amd_uncore_group_valid (struct perf_event *event) +{ +struct amd_uncore_pmu *pmu =event_to_amd_uncore_pmu (event); +struct perf_event *leader = event->group_leader; +struct perf_event *sibling; +int counters =0 ; + +if (leader->pmu == event->pmu) + counters++; + +for_each_sibling_event (sibling, leader) { +if (sibling->pmu == event->pmu && + sibling->state >PERF_EVENT_STATE_OFF ) + counters++; + } + +/* +* When pmu->event_init() is called, the event is yet to be linked to +* its leader's sibling list, so it is counted separately +*/ +return (counters +1 ) <= pmu->num_counters; +} +static int amd_uncore_event_init (struct perf_event *event) {struct amd_uncore_pmu *pmu;
@@ -223,6 +246,14 @@ static int amd_uncore_event_init(struct perf_event *event)if (!ctx)return -ENODEV ; +/* +* Ensure that all events in a group can be scheduled together so that +* a failure can be reported at perf_event_open() time rather than +* silently at pmu->add() time when no free counter is found +*/ +if (event->group_leader != event && !amd_uncore_group_valid (event)) +return -EINVAL ; +/* * NB and Last level cache counters (MSRs) are shared across all cores * that share the same NB / Last level cache. On family 16h and below,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 398/1376 perf vendor events amd: Update Zen 5 core events
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sandipan Das <[email protected]>
[ Upstream commit 047979af3bf6a118066c81099162d518de63abb1 ]
Update definitions for the following events.
* PMCx00A - Add missing unit masks
* PMCx00B - Add missing unit masks and fix descriptions
* PMCx00C - Add missing unit masks
* PMCx00D - Add missing unit masks
* PMCx025 - Add missing unit masks and fix descriptions
--- .../arch/x86/amdzen5/floating-point.json | 130 +++++++++++++++--- .../arch/x86/amdzen5/load-store.json | 8 +- 2 files changed, 120 insertions(+), 18 deletions(-)
tools/perf/pmu-events/arch/x86/amdzen5/floating-point.json +113 -17
@@ -179,6 +179,30 @@ "BriefDescription": "Retired scalar floating-point blend ops.", "UMask": "0x09" }, + { + "EventName": "fp_ops_retired_by_type.scalar_mov", + "EventCode": "0x0a", + "BriefDescription": "Retired scalar floating-point MOV ops.", + "UMask": "0x0a" + }, + { + "EventName": "fp_ops_retired_by_type.scalar_shuffle", + "EventCode": "0x0a", + "BriefDescription": "Retired scalar floating-point shuffle ops (may include instructions not necessarily thought of as including shuffles e.g. horizontal add, dot product, and certain MOV instructions).", + "UMask": "0x0b" + }, + { + "EventName": "fp_ops_retired_by_type.scalar_bfloat", + "EventCode": "0x0a", + "BriefDescription": "Retired scalar floating-point bfloat ops.", + "UMask": "0x0c" + }, + { + "EventName": "fp_ops_retired_by_type.scalar_logical", + "EventCode": "0x0a", + "BriefDescription": "Retired scalar floating-point logical ops.", + "UMask": "0x0d" + }, { "EventName": "fp_ops_retired_by_type.scalar_other", "EventCode": "0x0a",
@@ -245,12 +269,24 @@ "BriefDescription": "Retired vector floating-point blend ops.", "UMask": "0x90" }, + { + "EventName": "fp_ops_retired_by_type.vector_mov", + "EventCode": "0x0a", + "BriefDescription": "Retired vector floating-point MOV ops.", + "UMask": "0xa0" + }, { "EventName": "fp_ops_retired_by_type.vector_shuffle", "EventCode": "0x0a", "BriefDescription": "Retired vector floating-point shuffle ops (may include instructions not necessarily thought of as including shuffles e.g. horizontal add, dot product, and certain MOV instructions).", "UMask": "0xb0" }, + { + "EventName": "fp_ops_retired_by_type.vector_bfloat", + "EventCode": "0x0a", + "BriefDescription": "Retired vector floating-point bfloat ops.", + "UMask": "0xc0" + }, { "EventName": "fp_ops_retired_by_type.vector_logical", "EventCode": "0x0a",
@@ -278,7 +314,7 @@ { "EventName": "sse_avx_ops_retired.mmx_add", "EventCode": "0x0b", - "BriefDescription": "Retired MMX integer add.", + "BriefDescription": "Retired MMX integer add ops.", "UMask": "0x01" }, {
@@ -299,16 +335,34 @@ "BriefDescription": "Retired MMX integer multiply-accumulate ops.", "UMask": "0x04" }, + { + "EventName": "sse_avx_ops_retired.mmx_aes", + "EventCode": "0x0b", + "BriefDescription": "Retired MMX integer AES ops.", + "UMask": "0x05" + }, + { + "EventName": "sse_avx_ops_retired.mmx_sha", + "EventCode": "0x0b", + "BriefDescription": "Retired MMX integer SHA ops.", + "UMask": "0x06" + }, { "EventName": "sse_avx_ops_retired.mmx_cmp", "EventCode": "0x0b", "BriefDescription": "Retired MMX integer compare ops.", "UMask": "0x07" }, + { + "EventName": "sse_avx_ops_retired.mmx_cvt", + "EventCode": "0x0b", + "BriefDescription": "Retired MMX integer convert or pack ops.", + "UMask": "0x08" + }, { "EventName": "sse_avx_ops_retired.mmx_shift", "EventCode": "0x0b", - "BriefDescription": "Retired MMX integer shift ops.", + "BriefDescription": "Retired MMX integer shift or rotate ops.", "UMask": "0x09" }, {
@@ -324,9 +378,9 @@ "UMask": "0x0b" }, { - "EventName": "sse_avx_ops_retired.mmx_pack", + "EventName": "sse_avx_ops_retired.mmx_vnni", "EventCode": "0x0b", - "BriefDescription": "Retired MMX integer pack ops.", + "BriefDescription": "Retired MMX integer VNNI ops.", "UMask": "0x0c" }, {
@@ -390,15 +444,15 @@ "UMask": "0x70" }, { - "EventName": "sse_avx_ops_retired.sse_avx_clm", + "EventName": "sse_avx_ops_retired.sse_avx_cvt", "EventCode": "0x0b", - "BriefDescription": "Retired SSE and AVX integer CLM ops.", + "BriefDescription": "Retired SSE and AVX integer convert or pack ops.", "UMask": "0x80" }, { "EventName": "sse_avx_ops_retired.sse_avx_shift", "EventCode": "0x0b", - "BriefDescription": "Retired SSE and AVX integer shift ops.", + "BriefDescription": "Retired SSE and AVX integer shift or rotate ops.", "UMask": "0x90" }, {
@@ -414,9 +468,9 @@ "UMask": "0xb0" }, { - "EventName": "sse_avx_ops_retired.sse_avx_pack", + "EventName": "sse_avx_ops_retired.sse_avx_vnni", "EventCode": "0x0b", - "BriefDescription": "Retired SSE and AVX integer pack ops.", + "BriefDescription": "Retired SSE and AVX integer VNNI ops.", "UMask": "0xc0" }, {
@@ -497,12 +551,24 @@ "BriefDescription": "Retired 128-bit packed floating-point blend ops.", "UMask": "0x09" }, + { + "EventName": "fp_pack_ops_retired.fp128_mov", + "EventCode": "0x0c", + "BriefDescription": "Retired 128-bit packed floating-point MOV ops.", + "UMask": "0x0a" + }, { "EventName": "fp_pack_ops_retired.fp128_shuffle", "EventCode": "0x0c", "BriefDescription": "Retired 128-bit packed floating-point shuffle ops (may include instructions not necessarily thought of as including shuffles e.g. horizontal add, dot product, and certain MOV instructions).", "UMask": "0x0b" }, + { + "EventName": "fp_pack_ops_retired.fp128_bfloat", + "EventCode": "0x0c", + "BriefDescription": "Retired 128-bit packed floating-point bfloat ops.", + "UMask": "0x0c" + }, { "EventName": "fp_pack_ops_retired.fp128_logical", "EventCode": "0x0c",
@@ -575,12 +641,24 @@ "BriefDescription": "Retired 256-bit packed floating-point blend ops.", "UMask": "0x90" }, + { + "EventName": "fp_pack_ops_retired.fp256_mov", + "EventCode": "0x0c", + "BriefDescription": "Retired 256-bit packed floating-point MOV ops.", + "UMask": "0xa0" + }, { "EventName": "fp_pack_ops_retired.fp256_shuffle", "EventCode": "0x0c", "BriefDescription": "Retired 256-bit packed floating-point shuffle ops (may include instructions not necessarily thought of as including shuffles e.g. horizontal add, dot product, and certain MOV instructions).", "UMask": "0xb0" }, + { + "EventName": "fp_pack_ops_retired.fp256_bfloat", + "EventCode": "0x0c", + "BriefDescription": "Retired 256-bit packed floating-point bfloat ops.", + "UMask": "0xc0" + }, { "EventName": "fp_pack_ops_retired.fp256_logical", "EventCode": "0x0c",
@@ -648,15 +726,15 @@ "UMask": "0x07" }, { - "EventName": "packed_int_op_type.int128_clm", + "EventName": "packed_int_op_type.int128_cvt", "EventCode": "0x0d", - "BriefDescription": "Retired 128-bit packed integer CLM ops.", + "BriefDescription": "Retired 128-bit packed integer convert or pack ops.", "UMask": "0x08" }, { "EventName": "packed_int_op_type.int128_shift", "EventCode": "0x0d", - "BriefDescription": "Retired 128-bit packed integer shift ops.", + "BriefDescription": "Retired 128-bit packed integer shift or rotate ops.", "UMask": "0x09" }, {
@@ -672,9 +750,9 @@ "UMask": "0x0b" }, { - "EventName": "packed_int_op_type.int128_pack", + "EventName": "packed_int_op_type.int128_vnni", "EventCode": "0x0d", - "BriefDescription": "Retired 128-bit packed integer pack ops.", + "BriefDescription": "Retired 128-bit packed integer VNNI ops.", "UMask": "0x0c" }, {
@@ -719,16 +797,34 @@ "BriefDescription": "Retired 256-bit packed integer multiply-accumulate ops.", "UMask": "0x40" }, + { + "EventName": "packed_int_op_type.int256_aes", + "EventCode": "0x0d", + "BriefDescription": "Retired 256-bit packed integer AES ops.", + "UMask": "0x50" + }, + { + "EventName": "packed_int_op_type.int256_sha", + "EventCode": "0x0d", + "BriefDescription": "Retired 256-bit packed integer SHA ops.", + "UMask": "0x60" + }, { "EventName": "packed_int_op_type.int256_cmp", "EventCode": "0x0d", "BriefDescription": "Retired 256-bit packed integer compare ops.", "UMask": "0x70" }, + { + "EventName": "packed_int_op_type.int256_cvt", + "EventCode": "0x0d", + "BriefDescription": "Retired 256-bit packed integer convert or pack ops.", + "UMask": "0x80" + }, { "EventName": "packed_int_op_type.int256_shift", "EventCode": "0x0d", - "BriefDescription": "Retired 256-bit packed integer shift ops.", + "BriefDescription": "Retired 256-bit packed integer shift or rotate ops.", "UMask": "0x90" }, {
@@ -744,9 +840,9 @@ "UMask": "0xb0" }, { - "EventName": "packed_int_op_type.int256_pack", + "EventName": "packed_int_op_type.int256_vnni", "EventCode": "0x0d", - "BriefDescription": "Retired 256-bit packed integer pack ops.", + "BriefDescription": "Retired 256-bit packed integer VNNI ops.", "UMask": "0xc0" }, {
tools/perf/pmu-events/arch/x86/amdzen5/load-store.json +7 -1
@@ -8,9 +8,15 @@ { "EventName": "ls_locks.bus_lock", "EventCode": "0x25", - "BriefDescription": "Retired Lock instructions which caused a bus lock.", + "BriefDescription": "Retired lock instructions which caused a bus lock.", "UMask": "0x01" }, + { + "EventName": "ls_locks.all", + "EventCode": "0x25", + "BriefDescription": "Retired lock instructions of all types.", + "UMask": "0x1f" + }, { "EventName": "ls_ret_cl_flush", "EventCode": "0x26",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 399/1376 hwrng: core - fix rng list on registration error
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manos Pitsidianakis <[email protected]>
[ Upstream commit 3a5834db2b1ce25649f330e78efe1ccde78967fd ]
hwrng_register(rng) does the following:
1. Checks if rng has name and read methods set
2. Checks if the name already exists
3. Adds rng to global rng_list
4. May try to set rng to current_rng
If step 4 fails, it returns an error. However, it does not remove the rng from rng_list, causing a dangling reference which can result in use-after-free if the caller frees rng, since registration failed.
Add a list_del_init() cleanup step.
--- drivers/char/hw_random/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/char/hw_random/core.c +3 -1
@@ -597,11 +597,13 @@ int hwrng_register(struct hwrng *rng)*/ err =set_current_rng (rng);if (err) - goto out_unlock; + goto out_list_del; } }mutex_unlock (&rng_mutex);return 0 ; +out_list_del: +list_del_init (&rng->list); out_unlock:mutex_unlock (&rng_mutex); out:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 400/1376 crypto: qat - cancel work on re-enable SR-IOV timeout
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Giovanni Cabiddu <[email protected]>
[ Upstream commit 455b0f3ac9e254edab9f5a873d337abe5e6e3604 ]
The QAT reset worker queues SR-IOV reenable work using a work_struct and completion embedded in an on-stack adf_sriov_dev_data. If the completion wait times out, the reset worker can return while device_sriov_wq still holds or executes the stack-backed work item.
Cancel the work on the device_sriov_wq on timeout before the stack frame unwinds.
--- drivers/crypto/intel/qat/qat_common/adf_aer.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/crypto/intel/qat/qat_common/adf_aer.c +2 -0
@@ -140,6 +140,8 @@ static void adf_device_reset_worker(struct work_struct *work)queue_work (device_sriov_wq, &sriov_data.sriov_work);if (wait_for_completion_timeout (&sriov_data.compl, wait_jiffies))adf_pf2vf_notify_restarted (accel_dev); +else +cancel_work_sync (&sriov_data.sriov_work);adf_dev_restarted_notify (accel_dev);clear_bit (ADF_STATUS_RESTARTING , &accel_dev->status);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 401/1376 crypto: qat - clear AES key schedule from stack
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Giovanni Cabiddu <[email protected]>
[ Upstream commit d41a9fcfb7f9ee36e4a4aaf5e7996bca6be1e7a9 ]
qat_alg_xts_reverse_key() expands the forward XTS AES key on the stack. That schedule contains key material and can remain in the stack frame.
Clear the temporary crypto_aes_ctx with memzero_explicit() after the copy.
--- drivers/crypto/intel/qat/qat_common/qat_algs.c | 1 + 1 file changed, 1 insertion(+)
drivers/crypto/intel/qat/qat_common/qat_algs.c +1 -0
@@ -481,6 +481,7 @@ static void qat_alg_xts_reverse_key(const u8 *key_forward, unsigned int keylen,memcpy (key_reverse +AES_BLOCK_SIZE , key -AES_BLOCK_SIZE ,AES_BLOCK_SIZE ); } +memzero_explicit (&aes_expanded,sizeof (aes_expanded)); } static void qat_alg_skcipher_init_dec(struct qat_alg_skcipher_ctx *ctx,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 402/1376 crypto: atmel-ecc - replace min_t with min
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
[ Upstream commit 5b085b2a038a1458f9398cb3b3b03cba6e38e1e0 ]
Use the simpler min() macro since the values are all unsigned and compatible.
Stable-dep-of: f240f9b588f4 ("crypto: atmel-ecc - reject hardware ECDH without a public key")
--- drivers/crypto/atmel-ecc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/crypto/atmel-ecc.c +2 -2
@@ -56,7 +56,7 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq, goto free_work_data;/* might want less than we've got */ - n_sz =min_t (size_t,ATMEL_ECC_NIST_P256_N_SIZE , req->dst_len); + n_sz =min (ATMEL_ECC_NIST_P256_N_SIZE , req->dst_len);/* copy the shared secret */ copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst, n_sz),
@@ -150,7 +150,7 @@ static int atmel_ecdh_generate_public_key(struct kpp_request *req)return -EINVAL ;/* might want less than we've got */ - nbytes =min_t (size_t,ATMEL_ECC_PUBKEY_SIZE , req->dst_len); + nbytes =min (ATMEL_ECC_PUBKEY_SIZE , req->dst_len);/* public key was saved at private key generation */ copied = sg_copy_from_buffer(req->dst,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 403/1376 crypto: atmel-ecc - clean up and improve ECDH comments
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
[ Upstream commit 3e84fb698abada239d3e35ed3d52a24dbfda5f6a ]
Improve the kerneldoc for struct atmel_ecdh_ctx by removing the stale "unsupported curves" wording, since the device only supports a single curve (P-256), and move the set_secret() constraint to the description.
In atmel_ecdh_set_secret(), clarify that the device generates the private key, and drop the redundant "only supports NIST P256" comment.
In atmel_ecdh_done() and atmel_ecdh_generate_public_key(), clarify the truncation comments. Also note that a P-256 public key consists of two 32-byte coordinates in atmel_ecdh_compute_shared_secret(), and remove the unnecessary fall-through comment and other redundant comments.
Stable-dep-of: f240f9b588f4 ("crypto: atmel-ecc - reject hardware ECDH without a public key")
--- drivers/crypto/atmel-ecc.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-)
drivers/crypto/atmel-ecc.c +14 -24
@@ -27,15 +27,14 @@ static struct atmel_ecc_driver_data driver_data;/** * struct atmel_ecdh_ctx - transformation context -* @client : pointer to i2c client device -* @fallback : used for unsupported curves or when user wants to use its own -* private key. -* @public_key : generated when calling set_secret(). It's the responsibility -* of the user to not call set_secret() while -* generate_public_key() or compute_shared_secret() are in flight. -* @curve_id : elliptic curve id -* @do_fallback: true when the device doesn't support the curve or when the user -* wants to use its own private key. +* @client: I2C client device +* @fallback: ECDH fallback used for caller-provided private keys +* @public_key: cached public key for the device-generated private key +* @curve_id: elliptic curve id +* @do_fallback: true when ECDH operations should use @fallback +* +* The caller must not invoke set_secret() while generate_public_key() +* or compute_shared_secret() are in flight. */ struct atmel_ecdh_ctx {struct i2c_client *client;
@@ -55,7 +54,7 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq,if (status) goto free_work_data; -/* might want less than we've got */ +/* copy only as much as requested, capped at 32 bytes */ n_sz =min (ATMEL_ECC_NIST_P256_N_SIZE , req->dst_len);/* copy the shared secret */
@@ -64,15 +63,15 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq,if (copied != n_sz) status = -EINVAL ; -/* fall through */ free_work_data:kfree_sensitive (work_data);kpp_request_complete (req, status); }/* -* A random private key is generated and stored in the device. The device -* returns the pair public key. +* If no private key is provided, generate one in the device and cache +* the corresponding public key. The generated private key never leaves +* the device. */ static int atmel_ecdh_set_secret (struct crypto_kpp *tfm,const void *buf,unsigned int len)
@@ -83,9 +82,7 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,struct ecdh params;int ret = -ENOMEM ; -/* free the old public key, if any */ kfree (ctx->public_key); -/* make sure you don't free the old public key twice */ ctx->public_key =NULL ;if (crypto_ecdh_decode_key (buf, len, ¶ms) <0 ) {
@@ -94,7 +91,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, }if (params.key_size) { -/* fallback to ecdh software implementation */ ctx->do_fallback = true;return crypto_kpp_set_secret (ctx->fallback, buf, len); }
@@ -103,11 +99,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,if (!cmd)return -ENOMEM ; -/* -* The device only supports NIST P256 ECC keys. The public key size will -* always be the same. Use a macro for the key size to avoid unnecessary -* computations. -*/ public_key =kmalloc (ATMEL_ECC_PUBKEY_SIZE ,GFP_KERNEL );if (!public_key) goto free_cmd;
@@ -120,7 +111,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,if (ret) goto free_public_key; -/* save the public key */ memcpy (public_key, &cmd->data[RSP_DATA_IDX ],ATMEL_ECC_PUBKEY_SIZE ); ctx->public_key = public_key;
@@ -149,7 +139,7 @@ static int atmel_ecdh_generate_public_key(struct kpp_request *req)if (!ctx->public_key)return -EINVAL ; -/* might want less than we've got */ +/* copy only as much as requested, capped at 64 bytes */ nbytes =min (ATMEL_ECC_PUBKEY_SIZE , req->dst_len);/* public key was saved at private key generation */
@@ -175,7 +165,7 @@ static int atmel_ecdh_compute_shared_secret(struct kpp_request *req)return crypto_kpp_compute_shared_secret (req); } -/* must have exactly two points to be on the curve */ +/* A P-256 public key must contain two 32-byte coordinates */ if (req->src_len !=ATMEL_ECC_PUBKEY_SIZE )return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 404/1376 crypto: atmel-ecc - reject hardware ECDH without a public key
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
[ Upstream commit f240f9b588f4e2de89822adebf560a96b5d263ed ]
The hardware ECDH path in atmel_ecdh_compute_shared_secret() uses the private key stored in the device. However, the public key is cached only after atmel_ecdh_set_secret() successfully generated that private key for the current tfm.
atmel_ecdh_generate_public_key() already rejects requests when no public key is cached. Add the same check to atmel_ecdh_compute_shared_secret() to prevent the device from using a private key that was not generated for the current tfm.
--- drivers/crypto/atmel-ecc.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/crypto/atmel-ecc.c +3 -0
@@ -165,6 +165,9 @@ static int atmel_ecdh_compute_shared_secret(struct kpp_request *req)return crypto_kpp_compute_shared_secret (req); } +if (!ctx->public_key) +return -EINVAL ; +/* A P-256 public key must contain two 32-byte coordinates */ if (req->src_len !=ATMEL_ECC_PUBKEY_SIZE )return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 405/1376 crypto: atmel-sha204a - fix heap info leak on I2C transfer failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lothar Rubusch <[email protected]>
[ Upstream commit 72bbf11ba14bd7d5fbf31a1ec42fff608b657f74 ]
The nonblocking RNG path allocates a work_data structure to track the state of an in-flight asynchronous I2C request. This pointer is stored in rng->priv and later consumed by the read path once the transaction completes.
If the underlying I2C transfer fails, the completion callback is invoked with a non-zero status. In this case, the allocated work_data is not usable for producing RNG output and must not remain associated with the hwrng state.
Previously, the failure path only logged a warning but left the pointer state uncleared, which can result in subsequent read attempts observing stale state and interpreting it as valid completion data.
Fix this by freeing the pending work_data. The I2C transaction reports an error. This ensures that failed requests do not leave residual state behind that could be interpreted as valid RNG data on later reads. Clearing rng->priv is done at the subsequent call to nonblocking read.
--- drivers/crypto/atmel-sha204a.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/crypto/atmel-sha204a.c +5 -1
@@ -31,10 +31,14 @@ static void atmel_sha204a_rng_done(struct atmel_i2c_work_data *work_data,struct atmel_i2c_client_priv *i2c_priv = work_data->ctx;struct hwrng *rng = areq; -if (status) +if (status) {dev_warn_ratelimited (&i2c_priv->client->dev,"i2c transaction failed (%d)\n" , status); +kfree (work_data); +atomic_dec (&i2c_priv->tfm_count); +return ; + } rng->priv = (unsigned long )work_data;atomic_dec (&i2c_priv->tfm_count);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 406/1376 crypto: sa2ul - stop probe if context pool creation fails
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit d03f980a25853f6a380895119a572a3bb1194e8d ]
sa_ul_probe() calls sa_init_mem() to create the DMA pool used for security context buffers, but ignores its return value. If pool creation fails, probe still continues with DMA setup, algorithm registration and child population even though later request setup depends on that pool.
Stop probing when sa_init_mem() fails, and route that failure to the PM cleanup path without attempting to destroy an uncreated DMA pool.
--- drivers/crypto/sa2ul.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/crypto/sa2ul.c +5 -1
@@ -2426,7 +2426,10 @@ static int sa_ul_probe(struct platform_device *pdev)return ret; } -sa_init_mem (dev_data); + ret =sa_init_mem (dev_data); +if (ret) + goto disable_pm; + ret =sa_dma_init (dev_data);if (ret) goto destroy_dma_pool;
@@ -2461,6 +2464,7 @@ static int sa_ul_probe(struct platform_device *pdev) destroy_dma_pool:dma_pool_destroy (dev_data->sc_pool); +disable_pm:pm_runtime_put_sync (dev);pm_runtime_disable (dev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 407/1376 crypto: rk3288 - fail ahash requests on HASH idle timeout
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit ae150db7826f21e8d19e54fb6243169628809c4d ]
rk_hash_run() waits for RK_CRYPTO_HASH_STS to become idle after the final DMA transfer, but ignores the poll result. If the hash engine never becomes idle, the driver still reads the digest registers and finalizes the request with the previous success value.
Store the poll result and finalize the request with the timeout error before reading the digest registers.
--- drivers/crypto/rockchip/rk3288_crypto_ahash.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/crypto/rockchip/rk3288_crypto_ahash.c +6 -1
@@ -322,7 +322,12 @@ static int rk_hash_run(struct crypto_engine *engine, void *breq)* efficiency, and make it response quickly when dma * complete. */ -readl_poll_timeout (rkc->reg +RK_CRYPTO_HASH_STS , v, v ==0 ,10 ,1000 ); + err =readl_poll_timeout (rkc->reg +RK_CRYPTO_HASH_STS , v, + v ==0 ,10 ,1000 ); +if (err) { +dev_err (rkc->dev,"HASH idle timeout\n" ); + goto theend; + }for (i =0 ; i <crypto_ahash_digestsize (tfm) /4 ; i++) { v =readl (rkc->reg +RK_CRYPTO_HASH_DOUT_0 + i *4 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 408/1376 crypto: keembay - Fix AEAD unregister count in error path
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <[email protected]>
[ Upstream commit e264401ce4776a288524e5b87593d4d864147115 ]
register_aes_algs() registers the AEAD algorithms before registering the skcipher algorithms. If skcipher registration fails, the function unwinds the earlier AEAD registration with crypto_engine_unregister_aeads(), but it passes ARRAY_SIZE(algs), which is the skcipher table size.
Use ARRAY_SIZE(algs_aead) for the AEAD unwind path so the unregister helper iterates over the same table that was registered. Also clarify the nearby
comment: the crypto registration helpers clean up algorithms registered within the same call, while this function must still unwind earlier successful registration steps.
--- drivers/crypto/intel/keembay/keembay-ocs-aes-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/crypto/intel/keembay/keembay-ocs-aes-core.c +2 -2
@@ -1541,7 +1541,7 @@ static int register_aes_algs(struct ocs_aes_dev *aes_dev)/* * If any algorithm fails to register, all preceding algorithms that -* were successfully registered will be automatically unregistered. +* were registered in the same call are automatically unregistered. */ ret =crypto_engine_register_aeads (algs_aead,ARRAY_SIZE (algs_aead));if (ret)
@@ -1549,7 +1549,7 @@ static int register_aes_algs(struct ocs_aes_dev *aes_dev) ret =crypto_engine_register_skciphers (algs,ARRAY_SIZE (algs));if (ret) -crypto_engine_unregister_aeads (algs_aead,ARRAY_SIZE (algs)); +crypto_engine_unregister_aeads (algs_aead,ARRAY_SIZE (algs_aead));return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 409/1376 nvme-apple: Use acquire/release for queue enabled state
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gui-Dong Han <[email protected]>
[ Upstream commit f61c934aa084b7440fec681be3f4b481eb5a8609 ]
apple_nvme_init_queue() initializes queue state and then marks the queue enabled. The interrupt and request paths check enabled before using that queue state.
The old wmb() after WRITE_ONCE(enabled, true) does not publish the earlier initialization before enabled becomes visible. Use a release store when enabling the queue and acquire loads when testing it.
Although the shutdown-side enabled accesses are not used for publishing queue initialization, use helpers for them as well for consistency.
--- drivers/nvme/host/apple.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-)
drivers/nvme/host/apple.c +23 -7
@@ -149,6 +149,23 @@ struct apple_nvme_queue {bool enabled; }; +static inline bool apple_nvme_queue_enabled (struct apple_nvme_queue *q) +{ +/* Pair with apple_nvme_enable_queue(). */ +return smp_load_acquire (&q->enabled); +} + +static inline void apple_nvme_enable_queue (struct apple_nvme_queue *q) +{ +/* Publish queue initialization before setting q->enabled. */ +smp_store_release (&q->enabled, true); +} + +static inline void apple_nvme_disable_queue (struct apple_nvme_queue *q) +{ +WRITE_ONCE (q->enabled, false); +} +/* * The apple_nvme_iod describes the data in an I/O. *
@@ -645,7 +662,7 @@ static bool apple_nvme_handle_cq(struct apple_nvme_queue *q, bool force)bool found;DEFINE_IO_COMP_BATCH (iob); -if (!READ_ONCE (q->enabled) && !force) +if (!apple_nvme_queue_enabled (q) && !force)return false; found =apple_nvme_poll_cq (q, &iob);
@@ -748,7 +765,7 @@ static blk_status_t apple_nvme_queue_rq(struct blk_mq_hw_ctx *hctx,* We should not need to do this, but we're still using this to * ensure we can drain requests on a dying queue. */ -if (unlikely (!READ_ONCE (q->enabled))) +if (unlikely (!apple_nvme_queue_enabled (q)))return BLK_STS_IOERR ;if (!nvme_check_ready (&anv->ctrl, req, true))
@@ -826,7 +843,7 @@ static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown)nvme_quiesce_io_queues (&anv->ctrl);if (!dead) { -if (READ_ONCE (anv->ioq.enabled)) { +if (apple_nvme_queue_enabled (&anv->ioq)) {apple_nvme_remove_sq (anv);apple_nvme_remove_cq (anv); }
@@ -850,8 +867,8 @@ static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown)nvme_disable_ctrl (&anv->ctrl, false); } -WRITE_ONCE (anv->ioq.enabled, false); -WRITE_ONCE (anv->adminq.enabled, false); +apple_nvme_disable_queue (&anv->ioq); +apple_nvme_disable_queue (&anv->adminq);mb ();/* ensure that nvme_queue_rq() sees that enabled is cleared */ nvme_quiesce_admin_queue (&anv->ctrl);
@@ -976,8 +993,7 @@ static void apple_nvme_init_queue(struct apple_nvme_queue *q)memset (q->tcbs,0 ,APPLE_ANS_MAX_QUEUE_DEPTH *sizeof (struct apple_nvmmu_tcb ));memset (q->cqes,0 , depth *sizeof (struct nvme_completion )); -WRITE_ONCE (q->enabled, true); -wmb ();/* ensure the first interrupt sees the initialization */ +apple_nvme_enable_queue (q); }static void apple_nvme_reset_work (struct work_struct *work)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 410/1376 nvmet-rdma: factor out response resource cleanup
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shin'ichiro Kawasaki <[email protected]>
[ Upstream commit 90096175473f7c86e39c3f74f10343f965f5a05d ]
Move the RDMA read/write context teardown and the request SGL freeing out of nvmet_rdma_release_rsp() into a new helper function nvmet_rdma_free_rsp_resources().
This is a refactoring with no functional change, in preparation for the following patch that uses nvmet_rdma_free_rsp_resources().
Stable-dep-of: 0114dd303b37 ("nvmet-rdma: fix response resource leak on queue teardown")
--- drivers/nvme/target/rdma.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/nvme/target/rdma.c +10 -3
@@ -658,18 +658,25 @@ static void nvmet_rdma_rw_ctx_destroy(struct nvmet_rdma_rsp *rsp) req->sg, req->sg_cnt, nvmet_data_dir(req)); } -static void nvmet_rdma_release_rsp (struct nvmet_rdma_rsp *rsp) +static void nvmet_rdma_free_rsp_resources (struct nvmet_rdma_rsp *rsp) {struct nvmet_rdma_queue *queue = rsp->queue; -atomic_add (1 + rsp->n_rdma, &queue->sq_wr_avail); -if (rsp->n_rdma)nvmet_rdma_rw_ctx_destroy (rsp);if (rsp->req.sg < rsp->cmd->inline_sg || rsp->req.sg >= rsp->cmd->inline_sg + queue->dev->inline_page_count)nvmet_req_free_sgls (&rsp->req); +} + +static void nvmet_rdma_release_rsp (struct nvmet_rdma_rsp *rsp) +{ +struct nvmet_rdma_queue *queue = rsp->queue; + +atomic_add (1 + rsp->n_rdma, &queue->sq_wr_avail); + +nvmet_rdma_free_rsp_resources (rsp);if (unlikely (!list_empty_careful (&queue->rsp_wr_wait_list)))nvmet_rdma_process_wr_wait_list (queue);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 411/1376 nvmet-rdma: fix response resource leak on queue teardown
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shin'ichiro Kawasaki <[email protected]>
[ Upstream commit 0114dd303b373522dea06053aabae34bdd33a7c4 ]
When an nvme target with rdma transport is removed while I/Os are in flight, a response can be posted but its send completion is never delivered before the connection is torn down. As a result nvmet_rdma_send_done() and nvmet_rdma_release_rsp() are never called for the response, and this leaks the allocated RDMA read/write context and request SGLs.
These leaks are recreated by running blktests nvme/061 with the rdma transport and the siw driver. Kernel kmemleak feature reports them as follows:
unreferenced object 0xffff88812bc490c0 (size 32):
comm "kworker/2:1H", pid 409, jiffies 4307744490
backtrace (crc 89afd339):
__kmalloc_noprof+0x5f9/0x890
sgl_alloc_order+0x7b/0x380
nvmet_req_alloc_sgls+0x290/0x4f0 [nvmet]
nvmet_rdma_map_sgl_keyed+0x241/0x12e0 [nvmet_rdma]
nvmet_rdma_handle_command+0x73e/0xb80 [nvmet_rdma]
__ib_process_cq+0x149/0x4c0 [ib_core]
ib_cq_poll_work+0x49/0x160 [ib_core]
process_one_work+0x8b2/0x1640
worker_thread+0x5fd/0xfe0
kthread+0x367/0x460
ret_from_fork+0x655/0x9d0
ret_from_fork_asm+0x1a/0x30 unreferenced object 0xffff88814bd05e80 (size 64):
comm "kworker/3:1H", pid 148, jiffies 4295195428
backtrace (crc e35510cb):
__kmalloc_noprof+0x5f9/0x890
rdma_rw_ctx_init+0x333/0x1fa0 [ib_core]
nvmet_rdma_map_sgl_keyed+0x5c8/0x12e0 [nvmet_rdma]
nvmet_rdma_handle_command+0x73e/0xb80 [nvmet_rdma]
__ib_process_cq+0x149/0x4c0 [ib_core]
ib_cq_poll_work+0x49/0x160 [ib_core]
process_one_work+0x8b2/0x1640
worker_thread+0x5fd/0xfe0
kthread+0x367/0x460
ret_from_fork+0x655/0x9d0
ret_from_fork_asm+0x1a/0x30To avoid the memory leaks, reclaim the memory of the in-flight responses when the queue QP is torn down. Call nvmet_rdma_free_rsp_resources() that frees up the RDMA read/write context and the request SGLs of such responses.
--- drivers/nvme/target/rdma.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
drivers/nvme/target/rdma.c +18 -0
@@ -1347,9 +1347,27 @@ static int nvmet_rdma_create_queue_ib(struct nvmet_rdma_queue *queue) goto out; } +static bool nvmet_rdma_reclaim_rsp (struct sbitmap *sb,unsigned int bitnr, +void *data) +{ +struct nvmet_rdma_queue *queue = data; + +nvmet_rdma_free_rsp_resources (&queue->rsps[bitnr]); + +return true; +} +static void nvmet_rdma_destroy_queue_ib (struct nvmet_rdma_queue *queue) {ib_drain_qp (queue->qp); + +/* +* Reclaim resources of a response that is still in-flight when the +* queue is being torn down. This happens when the connection was +* forcefully disconnected while an I/O is in flight. +*/ +sbitmap_for_each_set (&queue->rsp_tags, nvmet_rdma_reclaim_rsp, queue); +if (queue->cm_id)rdma_destroy_id (queue->cm_id);ib_destroy_qp (queue->qp);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 412/1376 bus: ti-sysc: Fix /chosen node reference leak
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 6342de0aed216b6df460b492ddb532b3e0ed16f1 ]
sysc_init_stdout_path() gets the /chosen node with of_find_node_by_path() to read stdout-path. The function then overwrites the local node pointer with the stdout-path lookup result, or exits on error, without dropping the /chosen reference.
Keep the /chosen node in a separate variable and put it after the stdout-path value has been used for the lookup. The successful stdout node lookup remains referenced by the cached stdout_path pointer.
--- drivers/bus/ti-sysc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/bus/ti-sysc.c +8 -4
@@ -682,6 +682,7 @@ static struct device_node *stdout_path;static void sysc_init_stdout_path (struct sysc *ddata) { +struct device_node *chosen;struct device_node *np =NULL ;const char *uart;
@@ -691,15 +692,18 @@ static void sysc_init_stdout_path(struct sysc *ddata)if (stdout_path)return ; - np =of_find_node_by_path ("/chosen" ); -if (!np) + chosen =of_find_node_by_path ("/chosen" ); +if (!chosen) goto err; - uart =of_get_property (np,"stdout-path" ,NULL ); -if (!uart) + uart =of_get_property (chosen,"stdout-path" ,NULL ); +if (!uart) { +of_node_put (chosen); goto err; + } np =of_find_node_by_path (uart); +of_node_put (chosen);if (!np) goto err;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 413/1376 PM: sleep: Fix off-by-one in wakelocks number limit check
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haowen Tu <[email protected]>
[ Upstream commit 6058646587dded0ce0ba91bd5a6afbf14fe42055 ]
CONFIG_PM_WAKELOCKS_LIMIT is documented as the maximum number of user-space wakeup sources, but the limit check is performed before the counter is incremented and only rejects new wakeup sources when the current number is greater than the limit. This allows one extra wakeup source to be created.
Reject new wakeup sources once the counter has reached the limit.
--- kernel/power/wakelock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/power/wakelock.c +1 -1
@@ -63,7 +63,7 @@ static unsigned int number_of_wakelocks;static inline bool wakelocks_limit_exceeded (void ) { -return number_of_wakelocks >CONFIG_PM_WAKELOCKS_LIMIT ; +return number_of_wakelocks >=CONFIG_PM_WAKELOCKS_LIMIT ; }static inline void increment_wakelocks_number (void )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 414/1376 cgroup/cpuset: Make nr_deadline_tasks an atomic_t
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Waiman Long <[email protected]>
[ Upstream commit 95220e1f18f6321008f021abc7d6f581f64bcb82 ]
The nr_deadline_tasks variable in the cpuset structure was introduced by commit 6c24849f5515 ("sched/cpuset: Keep track of SCHED_DEADLINE task in cpusets"). It is reported by sashiko [1] that nr_deadline_tasks can currently be modified by inc_dl_tasks_cs() under rq->lock and by cpuset_attach() under cpuset_mutex. So if both updates happen simultaneously, the nr_deadline_tasks variable can be corrupted leading to incorrect operations down the road.
Fix that by changing its type to atomic_t so that nr_deadline_tasks are always atomically updated. This fix patch is a low hanging fruit. It can handle some of the races between a concurrent sched_setscheduler() and cpuset_can_attach()/cpuset_attach() calls, but not all of them like the other issue raised by sashiko [2]. This will be handled hopefully in a future follow up patch.
[1] https://sashiko.dev/#/patchset/20260626181923.133658-1-longman%40redhat.com
[2] https://sashiko.dev/#/patchset/20260630033344.352702-1-longman%40redhat.com
--- kernel/cgroup/cpuset-internal.h | 2 +- kernel/cgroup/cpuset.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-)
kernel/cgroup/cpuset-internal.h +1 -1
@@ -166,7 +166,7 @@ struct cpuset {* number of SCHED_DEADLINE tasks attached to this cpuset, so that we * know when to rebuild associated root domain bandwidth information. */ -int nr_deadline_tasks; +atomic_t nr_deadline_tasks;int nr_migrate_dl_tasks;u64 sum_migrate_dl_bw;
kernel/cgroup/cpuset.c +5 -5
@@ -145,14 +145,14 @@ void inc_dl_tasks_cs(struct task_struct *p) {struct cpuset *cs =task_cs (p); - cs->nr_deadline_tasks++; +atomic_inc (&cs->nr_deadline_tasks); }void dec_dl_tasks_cs (struct task_struct *p) {struct cpuset *cs =task_cs (p); - cs->nr_deadline_tasks--; +atomic_dec (&cs->nr_deadline_tasks); }static inline int is_partition_valid (const struct cpuset *cs)
@@ -956,7 +956,7 @@ static void dl_update_tasks_root_domain(struct cpuset *cs)struct css_task_iter it;struct task_struct *task; -if (cs->nr_deadline_tasks ==0 ) +if (atomic_read (&cs->nr_deadline_tasks) ==0 )return ;css_task_iter_start (&cs->css,0 , &it);
@@ -3142,8 +3142,8 @@ static void cpuset_attach(struct cgroup_taskset *tset) cs->old_mems_allowed = cpuset_attach_nodemask_to;if (cs->nr_migrate_dl_tasks) { - cs->nr_deadline_tasks += cs->nr_migrate_dl_tasks; - oldcs->nr_deadline_tasks -= cs->nr_migrate_dl_tasks; +atomic_add (cs->nr_migrate_dl_tasks, &cs->nr_deadline_tasks); +atomic_sub (cs->nr_migrate_dl_tasks, &oldcs->nr_deadline_tasks);reset_migrate_dl_data (cs); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 415/1376 arm64: dts: qcom: sm7225-fairphone-fp4: Fix address in fb node name
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luca Weiss <[email protected]>
[ Upstream commit f6e65005fe55c3d09287851523de06367cbf0bc2 ]
'reg' is 0xa0000000 so the node name is missing a zero. Add it, so that the reg and address in the node name matches.
No functional impact.
--- arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts +1 -1
@@ -47,7 +47,7 @@ chosen { stdout-path = "serial0:115200n8"; - framebuffer0: framebuffer@a000000 { + framebuffer0: framebuffer@a0000000 { compatible = "simple-framebuffer"; reg = <0 0xa0000000 0 (2340 * 1080 * 4)>; width = <1080>;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 416/1376 arm64: dts: qcom: hamoa: Fix clocks for HSPHYs
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Dybcio <[email protected]>
[ Upstream commit 115894bc201b0cd1799d239875a1b40924f0ef7b ]
The tertiary controller's HSPHY has its own toggle in TCSR, while the primary one is wired directly to the XO clock. Fix that.
--- arch/arm64/boot/dts/qcom/x1e80100.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/qcom/x1e80100.dtsi +2 -2
@@ -2596,7 +2596,7 @@ usb_1_ss0_hsphy: phy@fd3000 { reg = <0 0x00fd3000 0 0x154>; #phy-cells = <0>; - clocks = <&tcsr TCSR_USB2_1_CLKREF_EN>; + clocks = <&rpmhcc RPMH_CXO_CLK>; clock-names = "ref"; resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
@@ -2736,7 +2736,7 @@ usb_1_ss2_hsphy: phy@fde000 { reg = <0 0x00fde000 0 0x154>; #phy-cells = <0>; - clocks = <&tcsr TCSR_USB2_1_CLKREF_EN>; + clocks = <&tcsr TCSR_USB2_2_CLKREF_EN>; clock-names = "ref"; resets = <&gcc GCC_QUSB2PHY_TERT_BCR>;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 417/1376 bus: qcom-ebi2: Simplify with scoped for each OF child loop
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
[ Upstream commit 9c252f3c8f390fae4ca09de36c9262a35ae88ace ]
Use scoped for-each loop when iterating over device nodes to make code a bit simpler.
Stable-dep-of: 64774dea5896 ("bus: qcom-ebi2: Fix clock leak on probe failure")
--- drivers/bus/qcom-ebi2.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/bus/qcom-ebi2.c +2 -5
@@ -292,7 +292,6 @@ static void qcom_ebi2_setup_chipselect(struct device_node *np,static int qcom_ebi2_probe (struct platform_device *pdev) {struct device_node *np = pdev->dev.of_node; -struct device_node *child;struct device *dev = &pdev->dev;struct resource *res;void __iomem *ebi2_base;
@@ -348,15 +347,13 @@ static int qcom_ebi2_probe(struct platform_device *pdev)writel (val, ebi2_base);/* Walk over the child nodes and see what chipselects we use */ -for_each_available_child_of_node (np, child) { +for_each_available_child_of_node_scoped (np, child) {u32 csindex;/* Figure out the chipselect */ ret =of_property_read_u32 (child,"reg" , &csindex); -if (ret) { -of_node_put (child); +if (ret)return ret; - }if (csindex >5 ) { dev_err(dev,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 418/1376 bus: qcom-ebi2: Fix clock leak on probe failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit 64774dea58969194ea5c27fa639954e551a87024 ]
qcom_ebi2_probe() enables the EBI2X and EBI2 clocks before it walks child nodes and populates child devices. If reading a child node's reg property fails, or if of_platform_default_populate() fails, probe returns without disabling either clock.
Route those failure paths through the existing clock cleanup labels so a failed probe does not leave the clocks prepared and enabled.
--- drivers/bus/qcom-ebi2.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/bus/qcom-ebi2.c +7 -3
@@ -353,7 +353,7 @@ static int qcom_ebi2_probe(struct platform_device *pdev)/* Figure out the chipselect */ ret =of_property_read_u32 (child,"reg" , &csindex);if (ret) -return ret; + goto err_disable_clk;if (csindex >5 ) { dev_err(dev,
@@ -372,8 +372,12 @@ static int qcom_ebi2_probe(struct platform_device *pdev) have_children = true; } -if (have_children) -return of_platform_default_populate (np,NULL , dev); +if (have_children) { + ret =of_platform_default_populate (np,NULL , dev); +if (ret) + goto err_disable_clk; + } +return 0 ; err_disable_clk:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 419/1376 wifi: mac80211_hwsim: avoid NULL skb in stop queue drain
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang <[email protected]>
[ Upstream commit 158438cd6ad69d6dd7d871582c38baf22169fede ]
mac80211_hwsim_stop() drops any frames left in data->pending. The loop currently checks skb_queue_empty() and then dequeues separately.
That split is racy with TX status handling, which can remove a pending frame under the queue lock. If the last entry is removed after the empty check, skb_dequeue() returns NULL and the stop path passes that NULL skb to ieee80211_free_txskb().
Use skb_dequeue() as the loop condition instead. The dequeue result is the object that stop owns and frees, and a concurrent status completion that empties the queue simply makes the loop terminate.
--- drivers/net/wireless/virtual/mac80211_hwsim.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/wireless/virtual/mac80211_hwsim.c +3 -2
@@ -2117,6 +2117,7 @@ static int mac80211_hwsim_start(struct ieee80211_hw *hw)static void mac80211_hwsim_stop (struct ieee80211_hw *hw,bool suspend) {struct mac80211_hwsim_data *data = hw->priv; +struct sk_buff *skb;int i; data->started = false;
@@ -2124,8 +2125,8 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw, bool suspend)for (i =0 ; i <ARRAY_SIZE (data->link_data); i++)hrtimer_cancel (&data->link_data[i].beacon_timer); -while (!skb_queue_empty (&data->pending)) -ieee80211_free_txskb (hw,skb_dequeue (&data->pending)); +while ((skb =skb_dequeue (&data->pending))) +ieee80211_free_txskb (hw, skb);wiphy_dbg (hw->wiphy,"%s\n" , __func__); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 420/1376 staging: greybus: audio: correct sscanf() return value check
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander A. Klimov <[email protected]>
[ Upstream commit f883fa1a0a0212f63acb18c50e5f900301f3bb1e ]
manager_sysfs_add_store() passes 6 pointers to sscanf(), but required latter to return 7 which always failed the operation. I corrected it to 6.
--- drivers/staging/greybus/audio_manager_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/greybus/audio_manager_sysfs.c +1 -1
@@ -23,7 +23,7 @@ static ssize_t manager_sysfs_add_store(struct kobject *kobj, desc.name, &desc.vid, &desc.pid, &desc.intf_id, &desc.ip_devices, &desc.op_devices); -if (num !=7 ) +if (num !=6 )return -EINVAL ; num =gb_audio_manager_add (&desc);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 421/1376 staging: sm750fb: gate dualview dataflow using g_dualview
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ahmet Sezgin Duran <[email protected]>
[ Upstream commit d352778979d2eed09e266ed0f3a5e3ccd3983940 ]
In sm750fb_setup and sm750fb_set_drv functions, the dualview related code is guarded by sm750_dev->fb_count > 1 condition. That value is updated only after each framebuffer is registered, while both guards are used before any increment.
Current flow:
lynxfb_pci_probe()
sm750fb_setup() // fb_count is 0
for each fb:
sm750fb_framebuffer_alloc()
lynxfb_set_fbinfo()
sm750fb_set_drv() // fb_count is 0 or 1
register_framebuffer()
sm750_dev->fb_count++; // fb_count is incrementedThus even if dualview=1 parameter is passed down to the driver, fb_count is never > 1 at either check, so dualview dataflows are not selected and crtc->vidmem_size is never halved.
Use g_dualview global variable instead of fb_count > 1 to correctly enable dualview capabilities.
--- drivers/staging/sm750fb/sm750.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/staging/sm750fb/sm750.c +2 -2
@@ -599,7 +599,7 @@ static int sm750fb_set_drv(struct lynxfb_par *par) crtc = &par->crtc; crtc->vidmem_size = sm750_dev->vidmem_size; -if (sm750_dev->fb_count >1 ) +if (g_dualview) crtc->vidmem_size >>=1 ;/* setup crtc and output member */
@@ -966,7 +966,7 @@ static void sm750fb_setup(struct sm750_dev *sm750_dev, char *src) NO_PARAM:if (sm750_dev->revid !=SM750LE_REVISION_ID ) { -if (sm750_dev->fb_count >1 ) { +if (g_dualview) {if (swap) sm750_dev->dataflow = sm750_dual_swap;else
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 422/1376 staging: sm750fb: Add missing Kconfig dependency
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rong Zhang <[email protected]>
[ Upstream commit da8fd33e7d6af4c069668c2d42234b969f706885 ]
The sm750 frame buffer driver depends on FB_IOMEM_FOPS, but its Kconfig somehow misses it.
Fix it by making FB_SM750 select FB_IOMEM_FOPS, as other frame buffer drivers do.
--- drivers/staging/sm750fb/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/staging/sm750fb/Kconfig +1 -0
@@ -6,6 +6,7 @@ config FB_SM750 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select FB_IOMEM_FOPS help Frame buffer driver for the Silicon Motion SM750 chip with 2D acceleration and dual head support.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 423/1376 greybus: audio: bound the topology section sizes against the fetched size
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
[ Upstream commit 33d8c7b794d2a30637c9d3fcb478f1d3222bef1e ]
gb_audio_gb_get_topology() fetches a topology blob of a module-supplied size, and gbaudio_tplg_parse_data() then walks it by adding the module-supplied size_dais, size_controls and size_widgets fields to form the control, widget and route section offsets. Those le32 sizes are never checked against the fetched blob, so a module reporting a small topology size but large section sizes makes the offsets point past the allocation, and parsing reads out of bounds.
Reject a topology whose section sizes do not fit within the fetched size before it is parsed.
--- drivers/staging/greybus/audio_gb.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/staging/greybus/audio_gb.c +13 -0
@@ -37,6 +37,19 @@ int gb_audio_gb_get_topology(struct gb_connection *connection,return ret; } +/* +* The size_* fields are supplied by the module and are used by +* gbaudio_tplg_parse_data() to compute offsets into the blob; make +* sure the sections fit within the fetched topology, so walking it +* cannot read out of bounds. +*/ +if ((u64 )le32_to_cpu (topo->size_dais) +le32_to_cpu (topo->size_controls) + +le32_to_cpu (topo->size_widgets) +le32_to_cpu (topo->size_routes) > + size -sizeof (*topo)) { +kfree (topo); +return -EINVAL ; + } + *topology = topo;return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 424/1376 staging: fbtft: Use sysfs_emit_at() to print to sysfs file
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 221192a784c25e28b489a7e75fabf59be4f63d57 ]
This scnprintf() uses the wrong limit. It should be "PAGE_SIZE - len" instead of just PAGE_SIZE. We're not going to hit the limit in real life since we are printing at most FBTFT_GAMMA_MAX_VALUES_TOTAL (128) u32 values, however, it's still worth fixing.
Use sysfs_emit_at() to fix this since this is a sysfs file.
--- drivers/staging/fbtft/fbtft-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/fbtft/fbtft-sysfs.c +1 -1
@@ -98,7 +98,7 @@ sprintf_gamma(struct fbtft_par *par, u32 *curves, char *buf)mutex_lock (&par->gamma.lock);for (i =0 ; i < par->gamma.num_curves; i++) {for (j =0 ; j < par->gamma.num_values; j++) - len +=scnprintf (&buf[len],PAGE_SIZE , + len +=sysfs_emit_at (buf, len,"%04x " , curves[i * par->gamma.num_values + j]); buf[len -1 ] ='\n' ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 425/1376 staging: octeon: add missing tasklet_kill in cvm_oct_tx_shutdown
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ayush Mukkanwar <[email protected]>
[ Upstream commit b9af44b0d20b2247c4eb0ea5cfca907d643eea50 ]
The TX cleanup tasklet can be scheduled by the watchdog IRQ handler to execute cvm_oct_tx_do_cleanup. There can be a pending tasklet in the queue which might run after the cvm_oct_remove() frees net_device structures, causing a use-after-free in cvm_oct_tx_do_cleanup() as it iterates cvm_oct_device[] which is an array of netdevice pointers. Add tasklet_kill() after free_irq() to ensure the tasklet is no longer scheduled or running before teardown proceeds.
--- drivers/staging/octeon/ethernet-tx.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/staging/octeon/ethernet-tx.c +2 -0
@@ -711,4 +711,6 @@ void cvm_oct_tx_shutdown(void) {/* Free the interrupt handler */ free_irq (OCTEON_IRQ_TIMER1 , cvm_oct_device); + +tasklet_kill (&cvm_oct_tx_cleanup_tasklet); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 426/1376 staging: octeon: fix free_irq dev_id mismatch in cvm_oct_rx_shutdown
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuvraj Singh Chauhan <[email protected]>
[ Upstream commit 41db5b76eeb4cc11a1097384caba7cfc659f7293 ]
In cvm_oct_rx_initialize(), request_irq() is called with &oct_rx_group[i].napi as the dev_id:
request_irq(oct_rx_group[i].irq, cvm_oct_do_interrupt, 0, "Ethernet", &oct_rx_group[i].napi);
However, cvm_oct_rx_shutdown() passes cvm_oct_device (an array of struct net_device pointers) as the dev_id to free_irq():
free_irq(oct_rx_group[i].irq, cvm_oct_device);
Since __free_irq() matches the action to remove by comparing dev_id pointers, the mismatched cookie means the IRQ handler is never found, triggering a WARN and leaving the IRQ line permanently allocated. This prevents proper driver cleanup on module removal.
Fix the mismatch by passing &oct_rx_group[i].napi as the dev_id to free_irq(), matching what was used during request_irq().
Stable-dep-of: c0a9a8586a63 ("staging: octeon: add missing napi_disable in cvm_oct_rx_shutdown")
--- drivers/staging/octeon/ethernet-rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/octeon/ethernet-rx.c +1 -1
@@ -535,7 +535,7 @@ void cvm_oct_rx_shutdown(void)cvmx_write_csr (CVMX_POW_WQ_INT_THRX (i),0 );/* Free the interrupt handler */ -free_irq (oct_rx_group[i].irq, cvm_oct_device); +free_irq (oct_rx_group[i].irq, &oct_rx_group[i].napi);netif_napi_del (&oct_rx_group[i].napi); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 427/1376 staging: octeon: ethernet-mem: replace pr_warn with dev_warn in free functions
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ayush Mukkanwar <[email protected]>
[ Upstream commit be5e8d5f61b31105e0ed7f51cd591653aea5054f ]
Add struct platform_device parameter to cvm_oct_free_hw_skbuff, cvm_oct_free_hw_memory and cvm_oct_mem_empty_fpa. Replace pr_warn calls with dev_warn, using &pdev->dev for device-aware logging.
Stable-dep-of: c0a9a8586a63 ("staging: octeon: add missing napi_disable in cvm_oct_rx_shutdown")
--- drivers/staging/octeon/ethernet-mem.c | 31 ++++++++++++++++----------- drivers/staging/octeon/ethernet-mem.h | 5 ++++- drivers/staging/octeon/ethernet.c | 6 +++--- 3 files changed, 25 insertions(+), 17 deletions(-)
drivers/staging/octeon/ethernet-mem.c +18 -13
@@ -5,6 +5,7 @@* Copyright (c) 2003-2010 Cavium Networks */ +#include <linux/platform_device.h> #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/slab.h>
@@ -40,11 +41,13 @@ static int cvm_oct_fill_hw_skbuff(int pool, int size, int elements)/** * cvm_oct_free_hw_skbuff- free hardware pool skbuffs +* @pdev: Platform device for logging * @pool: Pool to allocate an skbuff for * @size: Size of the buffer needed for the pool * @elements: Number of buffers to allocate */ -static void cvm_oct_free_hw_skbuff (int pool,int size,int elements) +static void cvm_oct_free_hw_skbuff (struct platform_device *pdev, +int pool,int size,int elements) {char *memory;
@@ -59,11 +62,11 @@ static void cvm_oct_free_hw_skbuff(int pool, int size, int elements) }while (memory);if (elements <0 ) -pr_warn ("Freeing of pool %u had too many skbuffs (%d)\n" , - pool, elements); +dev_warn (&pdev->dev,"Freeing of pool %u had too many skbuffs (%d)\n" , + pool, elements);else if (elements >0 ) -pr_warn ("Freeing of pool %u is missing %d skbuffs\n" , - pool, elements); +dev_warn (&pdev->dev,"Freeing of pool %u is missing %d skbuffs\n" , + pool, elements); }/**
@@ -107,11 +110,13 @@ static int cvm_oct_fill_hw_memory(int pool, int size, int elements)/** * cvm_oct_free_hw_memory - Free memory allocated by cvm_oct_fill_hw_memory +* @pdev: Platform device for logging * @pool: FPA pool to free * @size: Size of each buffer in the pool * @elements: Number of buffers that should be in the pool */ -static void cvm_oct_free_hw_memory (int pool,int size,int elements) +static void cvm_oct_free_hw_memory (struct platform_device *pdev, +int pool,int size,int elements) {char *memory;char *fpa;
@@ -127,11 +132,11 @@ static void cvm_oct_free_hw_memory(int pool, int size, int elements) }while (fpa);if (elements <0 ) -pr_warn ("Freeing of pool %u had too many buffers (%d)\n" , - pool, elements); +dev_warn (&pdev->dev,"Freeing of pool %u had too many buffers (%d)\n" , + pool, elements);else if (elements >0 ) -pr_warn ("Warning: Freeing of pool %u is missing %d buffers\n" , - pool, elements); +dev_warn (&pdev->dev,"Freeing of pool %u is missing %d buffers\n" , + pool, elements); }int cvm_oct_mem_fill_fpa (int pool,int size,int elements)
@@ -145,10 +150,10 @@ int cvm_oct_mem_fill_fpa(int pool, int size, int elements)return freed; } -void cvm_oct_mem_empty_fpa (int pool,int size,int elements) +void cvm_oct_mem_empty_fpa (struct platform_device *pdev,int pool,int size,int elements) {if (pool ==CVMX_FPA_PACKET_POOL ) -cvm_oct_free_hw_skbuff (pool, size, elements); +cvm_oct_free_hw_skbuff (pdev, pool, size, elements);else -cvm_oct_free_hw_memory (pool, size, elements); +cvm_oct_free_hw_memory (pdev, pool, size, elements); }
drivers/staging/octeon/ethernet-mem.h +4 -1
@@ -6,4 +6,7 @@*/ int cvm_oct_mem_fill_fpa (int pool,int size,int elements); -void cvm_oct_mem_empty_fpa (int pool,int size,int elements); +struct platform_device ; + +void cvm_oct_mem_empty_fpa (struct platform_device *pdev,int pool,int size, +int elements);
drivers/staging/octeon/ethernet.c +3 -3
@@ -958,12 +958,12 @@ static void cvm_oct_remove(struct platform_device *pdev)cvmx_ipd_free_ptr ();/* Free the HW pools */ -cvm_oct_mem_empty_fpa (CVMX_FPA_PACKET_POOL ,CVMX_FPA_PACKET_POOL_SIZE , +cvm_oct_mem_empty_fpa (pdev,CVMX_FPA_PACKET_POOL ,CVMX_FPA_PACKET_POOL_SIZE , num_packet_buffers); -cvm_oct_mem_empty_fpa (CVMX_FPA_WQE_POOL ,CVMX_FPA_WQE_POOL_SIZE , +cvm_oct_mem_empty_fpa (pdev,CVMX_FPA_WQE_POOL ,CVMX_FPA_WQE_POOL_SIZE , num_packet_buffers);if (CVMX_FPA_OUTPUT_BUFFER_POOL !=CVMX_FPA_PACKET_POOL ) -cvm_oct_mem_empty_fpa (CVMX_FPA_OUTPUT_BUFFER_POOL , +cvm_oct_mem_empty_fpa (pdev,CVMX_FPA_OUTPUT_BUFFER_POOL ,CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE ,128 ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 428/1376 staging: octeon: replace pr_warn with dev_warn in fill and rx paths
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ayush Mukkanwar <[email protected]>
[ Upstream commit 2191a8dfd1f5a3091e9f388899beb137686c6532 ]
Add struct platform_device parameter to cvm_oct_fill_hw_memory, cvm_oct_mem_fill_fpa, cvm_oct_rx_refill_pool and cvm_oct_rx_initialize to support device-aware logging. Replace pr_warn with dev_warn using &pdev->dev.
To avoid passing these parameters through global state, introduce struct octeon_ethernet_platform to hold per-device state including the rx_refill_work and the oct_rx_group array. This ensures all receive group state and workers are correctly associated with the platform device.
Define struct oct_rx_group and struct octeon_ethernet_platform in octeon-ethernet.h so they are shared across compilation units.
Stable-dep-of: c0a9a8586a63 ("staging: octeon: add missing napi_disable in cvm_oct_rx_shutdown")
--- drivers/staging/octeon/ethernet-mem.c | 12 +++--- drivers/staging/octeon/ethernet-mem.h | 3 +- drivers/staging/octeon/ethernet-rx.c | 49 ++++++++++++------------ drivers/staging/octeon/ethernet-rx.h | 11 ++++-- drivers/staging/octeon/ethernet.c | 37 +++++++++++------- drivers/staging/octeon/octeon-ethernet.h | 14 +++++++ 6 files changed, 78 insertions(+), 48 deletions(-)
drivers/staging/octeon/ethernet-mem.c +7 -5
@@ -71,13 +71,15 @@ static void cvm_oct_free_hw_skbuff(struct platform_device *pdev,/** * cvm_oct_fill_hw_memory - fill a hardware pool with memory. +* @pdev: Platform device for logging * @pool: Pool to populate * @size: Size of each buffer in the pool * @elements: Number of buffers to allocate * * Returns the actual number of buffers allocated. */ -static int cvm_oct_fill_hw_memory (int pool,int size,int elements) +static int cvm_oct_fill_hw_memory (struct platform_device *pdev,int pool,int size, +int elements) {char *memory;char *fpa;
@@ -96,8 +98,8 @@ static int cvm_oct_fill_hw_memory(int pool, int size, int elements)*/ memory =kmalloc (size +256 ,GFP_ATOMIC );if (unlikely (!memory)) { -pr_warn ("Unable to allocate %u bytes for FPA pool %d\n" , - elements * size, pool); +dev_warn (&pdev->dev,"Unable to allocate %u bytes for FPA pool %d\n" , + elements * size, pool);break ; } fpa = (char *)(((unsigned long )memory +256 ) & ~0x7fUL );
@@ -139,14 +141,14 @@ static void cvm_oct_free_hw_memory(struct platform_device *pdev, pool, elements); } -int cvm_oct_mem_fill_fpa (int pool,int size,int elements) +int cvm_oct_mem_fill_fpa (struct platform_device *pdev,int pool,int size,int elements) {int freed;if (pool ==CVMX_FPA_PACKET_POOL ) freed =cvm_oct_fill_hw_skbuff (pool, size, elements);else - freed =cvm_oct_fill_hw_memory (pool, size, elements); + freed =cvm_oct_fill_hw_memory (pdev, pool, size, elements);return freed; }
drivers/staging/octeon/ethernet-mem.h +2 -1
@@ -5,8 +5,9 @@* Copyright (c) 2003-2007 Cavium Networks */ -int cvm_oct_mem_fill_fpa (int pool,int size,int elements);struct platform_device ; +int cvm_oct_mem_fill_fpa (struct platform_device *pdev,int pool,int size, +int elements);void cvm_oct_mem_empty_fpa (struct platform_device *pdev,int pool,int size,int elements);
drivers/staging/octeon/ethernet-rx.c +25 -24
125 lines not on this page · raw message
drivers/staging/octeon/ethernet-rx.h +7 -4
@@ -5,11 +5,14 @@* Copyright (c) 2003-2007 Cavium Networks */ +struct platform_device ; +void cvm_oct_poll_controller (struct net_device *dev); -void cvm_oct_rx_initialize (void ); -void cvm_oct_rx_shutdown (void ); +void cvm_oct_rx_initialize (struct platform_device *pdev); +void cvm_oct_rx_shutdown (struct platform_device *pdev); -static inline void cvm_oct_rx_refill_pool (int fill_threshold) +static inline void cvm_oct_rx_refill_pool (struct platform_device *pdev, +int fill_threshold) {int number_to_free;int num_freed;
@@ -20,7 +23,7 @@ static inline void cvm_oct_rx_refill_pool(int fill_threshold)if (number_to_free > fill_threshold) {cvmx_fau_atomic_add32 (FAU_NUM_PACKET_BUFFERS_TO_FREE , -number_to_free); - num_freed =cvm_oct_mem_fill_fpa (CVMX_FPA_PACKET_POOL , + num_freed =cvm_oct_mem_fill_fpa (pdev,CVMX_FPA_PACKET_POOL ,CVMX_FPA_PACKET_POOL_SIZE , number_to_free);if (num_freed != number_to_free) {
drivers/staging/octeon/ethernet.c +23 -14
@@ -104,11 +104,10 @@ struct net_device *cvm_oct_device[TOTAL_NUMBER_OF_PORTS];u64 cvm_oct_tx_poll_interval; -static void cvm_oct_rx_refill_worker (struct work_struct *work); -static DECLARE_DELAYED_WORK(cvm_oct_rx_refill_work, cvm_oct_rx_refill_worker); -static void cvm_oct_rx_refill_worker (struct work_struct *work) { +struct octeon_ethernet_platform *plat =container_of (work, + struct octeon_ethernet_platform, rx_refill_work.work);/* * FPA 0 may have been drained, try to refill it if we need * more than num_packet_buffers / 2, otherwise normal receive
@@ -116,10 +115,10 @@ static void cvm_oct_rx_refill_worker(struct work_struct *work)* could be received so cvm_oct_napi_poll would never be * invoked to do the refill. */ -cvm_oct_rx_refill_pool (num_packet_buffers /2 ); +cvm_oct_rx_refill_pool (plat->pdev, num_packet_buffers /2 );if (!atomic_read (&cvm_oct_poll_queue_stopping)) -schedule_delayed_work (&cvm_oct_rx_refill_work,HZ ); +schedule_delayed_work (&plat->rx_refill_work,HZ ); }static void cvm_oct_periodic_worker (struct work_struct *work)
@@ -138,16 +137,16 @@ static void cvm_oct_periodic_worker(struct work_struct *work)schedule_delayed_work (&priv->port_periodic_work,HZ ); } -static void cvm_oct_configure_common_hw (void ) +static void cvm_oct_configure_common_hw (struct platform_device *pdev) {/* Setup the FPA */ cvmx_fpa_enable (); -cvm_oct_mem_fill_fpa (CVMX_FPA_PACKET_POOL ,CVMX_FPA_PACKET_POOL_SIZE , +cvm_oct_mem_fill_fpa (pdev,CVMX_FPA_PACKET_POOL ,CVMX_FPA_PACKET_POOL_SIZE , num_packet_buffers); -cvm_oct_mem_fill_fpa (CVMX_FPA_WQE_POOL ,CVMX_FPA_WQE_POOL_SIZE , +cvm_oct_mem_fill_fpa (pdev,CVMX_FPA_WQE_POOL ,CVMX_FPA_WQE_POOL_SIZE , num_packet_buffers);if (CVMX_FPA_OUTPUT_BUFFER_POOL !=CVMX_FPA_PACKET_POOL ) -cvm_oct_mem_fill_fpa (CVMX_FPA_OUTPUT_BUFFER_POOL , +cvm_oct_mem_fill_fpa (pdev,CVMX_FPA_OUTPUT_BUFFER_POOL ,CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE ,1024 );#ifdef __LITTLE_ENDIAN
@@ -678,6 +677,15 @@ static int cvm_oct_probe(struct platform_device *pdev)int qos;struct device_node *pip;int mtu_overhead =ETH_HLEN +ETH_FCS_LEN ; +struct octeon_ethernet_platform *plat; + + plat =devm_kzalloc (&pdev->dev,sizeof (*plat),GFP_KERNEL ); +if (!plat) +return -ENOMEM ; + + plat->pdev = pdev; +INIT_DELAYED_WORK (&plat->rx_refill_work, cvm_oct_rx_refill_worker); +platform_set_drvdata (pdev, plat);#if IS_ENABLED (CONFIG_VLAN_8021Q ) mtu_overhead +=VLAN_HLEN ;
@@ -689,7 +697,7 @@ static int cvm_oct_probe(struct platform_device *pdev)return -EINVAL ; } -cvm_oct_configure_common_hw (); +cvm_oct_configure_common_hw (pdev);cvmx_helper_initialize_packet_io_global ();
@@ -912,28 +920,29 @@ static int cvm_oct_probe(struct platform_device *pdev) }cvm_oct_tx_initialize (); -cvm_oct_rx_initialize (); +cvm_oct_rx_initialize (pdev);/* * 150 uS: about 10 1500-byte packets at 1GE. */ cvm_oct_tx_poll_interval =150 * (octeon_get_clock_rate () /1000000 ); -schedule_delayed_work (&cvm_oct_rx_refill_work,HZ ); +schedule_delayed_work (&plat->rx_refill_work,HZ );return 0 ; }static void cvm_oct_remove (struct platform_device *pdev) { +struct octeon_ethernet_platform *plat =platform_get_drvdata (pdev);int port;cvmx_ipd_disable ();atomic_inc_return (&cvm_oct_poll_queue_stopping); -cancel_delayed_work_sync (&cvm_oct_rx_refill_work); +cancel_delayed_work_sync (&plat->rx_refill_work); -cvm_oct_rx_shutdown (); +cvm_oct_rx_shutdown (pdev);cvm_oct_tx_shutdown ();cvmx_pko_disable ();
drivers/staging/octeon/octeon-ethernet.h +14 -0
@@ -11,6 +11,7 @@#ifndef OCTEON_ETHERNET_H #define OCTEON_ETHERNET_H +#include <linux/netdevice.h> #include <linux/of.h> #include <linux/phy.h>
@@ -74,6 +75,19 @@ struct octeon_ethernet {struct device_node *of_node; }; +struct oct_rx_group { +int irq; +int group; +struct napi_struct napi; +struct platform_device *pdev; +}; + +struct octeon_ethernet_platform { +struct platform_device *pdev; +struct delayed_work rx_refill_work; +struct oct_rx_group rx_group[16 ]; +}; +int cvm_oct_free_work (void *work_queue_entry);int cvm_oct_rgmii_open (struct net_device *dev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 429/1376 staging: octeon: add missing napi_disable in cvm_oct_rx_shutdown
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ayush Mukkanwar <[email protected]>
[ Upstream commit c0a9a8586a63fda49e61a6b83360feac2a60d898 ]
cvm_oct_rx_shutdown calls free_irq and netif_napi_del without disabling the napi instance first. As the free_irq only waits for completion of hard interrupt handlers, the napi poll function could still be active. If cvm_oct_remove proceeds to free the plat structure (which holds the NAPI instances), the active poll function will access freed memory, resulting in a use-after-free crash.
--- drivers/staging/octeon/ethernet-rx.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/staging/octeon/ethernet-rx.c +2 -0
@@ -535,6 +535,8 @@ void cvm_oct_rx_shutdown(struct platform_device *pdev)else cvmx_write_csr (CVMX_POW_WQ_INT_THRX (i),0 ); +napi_disable (&plat->rx_group[i].napi); +/* Free the interrupt handler */ free_irq (plat->rx_group[i].irq, &plat->rx_group[i].napi);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 430/1376 staging: rtl8723bs: fix mismatched free of HalData in rtw_sdio_if1_init()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dawei Feng <[email protected]>
[ Upstream commit 264676418b726baca7be49171e306b6aa05cceb0 ]
padapter->HalData is allocated via vzalloc(), but incorrectly freed using kfree() in the rtw_sdio_if1_init() error path. Using kfree() to release this vmalloc-backed buffer can lead to memory corruption.
Use rtw_hal_data_deinit() to pair the free correctly and free HalData with vfree().
The bug was first flagged by an experimental static analysis tool we are developing for kernel memory-management bugs. Manual inspection confirms that the issue is still present in current mainline.
An x86_64 allyesconfig build showed no new warnings. As we do not have suitable RTL8723BS SDIO hardware to test with, no runtime testing was able to be performed.
--- drivers/staging/rtl8723bs/os_dep/sdio_intf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/staging/rtl8723bs/os_dep/sdio_intf.c +2 -2
@@ -309,8 +309,8 @@ static struct adapter *rtw_sdio_if1_init(struct dvobj_priv *dvobj, const struct status = _SUCCESS; free_hal_data: -if (status != _SUCCESS && padapter->HalData) -kfree (padapter->HalData); +if (status != _SUCCESS) +rtw_hal_data_deinit (padapter);if (status != _SUCCESS) {rtw_wdev_unregister (padapter->rtw_wdev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 431/1376 ALSA: via82xx: Remove unreachable branch in snd_via686_pcm_pointer()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Evgenii Burenchev <[email protected]>
[ Upstream commit cd3447e1b6425efd1704ed07f1f245c842927eb0 ]
The condition
if (count && size < count)
can never evaluate to true.
The VIA DMA count register is masked with 0x00ffffff before use, while the DMA buffer size is limited to 0x00fffffe bytes. As a result, 'count' can never exceed 'size', making the condition permanently false.
This branch has therefore been unreachable since the driver was introduced. Remove the unreachable branch without changing runtime behavior.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- sound/pci/via82xx_modem.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-)
sound/pci/via82xx_modem.c +10 -16
@@ -576,24 +576,18 @@ static inline unsigned int calc_linear_pos(struct via82xx_modem *chip, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count);#endif -if (count && size < count) { +if (! count) +/* bogus count 0 on the DMA boundary? */ + res = viadev->idx_table[idx].offset; +else +/* count register returns full size +* when end of buffer is reached +*/ + res = viadev->idx_table[idx].offset + size; +if (check_invalid_pos (viadev, res)) {dev_dbg (chip->card->dev, -"invalid via82xx_cur_ptr, using last valid pointer\n" ); +"invalid via82xx_cur_ptr (2), using last valid pointer\n" ); res = viadev->lastpos; - }else { -if (! count) -/* bogus count 0 on the DMA boundary? */ - res = viadev->idx_table[idx].offset; -else -/* count register returns full size -* when end of buffer is reached -*/ - res = viadev->idx_table[idx].offset + size; -if (check_invalid_pos (viadev, res)) { -dev_dbg (chip->card->dev, -"invalid via82xx_cur_ptr (2), using last valid pointer\n" ); - res = viadev->lastpos; - } } } viadev->lastpos = res;/* remember the last position */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 432/1376 selftests/bpf: Fix memory leak in msg_alloc_iov error path
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Malaya Kumar Rout <[email protected]>
[ Upstream commit 0bebfaa39deadec21638f6fba553eae12627a26d ]
In msg_alloc_iov(), when calloc() fails for an individual iov_base allocation, the error path frees all previously allocated iov_base entries but fails to free the iov array itself that was allocated with calloc() at the beginning of the function. This results in a memory leak of the iov array.
Add free(iov) in the unwind_iov error path to ensure proper cleanup of all allocated memory.
--- tools/testing/selftests/bpf/test_sockmap.c | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/bpf/test_sockmap.c +1 -0
@@ -515,6 +515,7 @@ static int msg_alloc_iov(struct msghdr *msg, unwind_iov:for (i--; i >=0 ; i--)free (msg->msg_iov[i].iov_base); +free (iov);return -ENOMEM ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 433/1376 selftests/bpf: Fix memory leak in msg_alloc_iov
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Feng Yang <[email protected]>
[ Upstream commit 602701718649936eb287bf6c7ecf870ec54c6f71 ]
In the msg_alloc_iov function, the iov pointer is only assigned to msg->msg_iov after all memory allocations complete successfully. Therefore, when a calloc failure triggers the unwind_iov cleanup branch, we should use the local variable iov instead of msg->msg_iov.
--- tools/testing/selftests/bpf/test_sockmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/test_sockmap.c +1 -1
@@ -514,7 +514,7 @@ static int msg_alloc_iov(struct msghdr *msg,return 0 ; unwind_iov:for (i--; i >=0 ; i--) -free (msg->msg_iov[i].iov_base); +free (iov[i].iov_base);free (iov);return -ENOMEM ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 434/1376 selftests/lsm: Fix memory leak in attr_lsm_count
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wang Yan <[email protected]>
[ Upstream commit 0cee720cfd51402cfcb14d96cb326a36c13b823a ]
The calloc-allocated buffer in attr_lsm_count() is never released on any exit path, including both the normal return path and the early return when read_sysfs_lsms fails, resulting in a heap memory leak.
Add free() for the buffer on all return branches to fix the leak.
--- tools/testing/selftests/lsm/common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/testing/selftests/lsm/common.c +3 -1
@@ -76,7 +76,7 @@ int attr_lsm_count(void)return 0 ;if (read_sysfs_lsms (names,sysconf (_SC_PAGESIZE))) -return 0 ; + goto out;if (strstr (names,"selinux" )) count++;
@@ -85,5 +85,7 @@ int attr_lsm_count(void)if (strstr (names,"apparmor" )) count++; +out: +free (names);return count; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 435/1376 irqchip/gic-v3-its: Fix memleak in its_probe_one()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kemeng Shi <[email protected]>
[ Upstream commit 1efffab6fe336a5c4fd3c2886f255cd2f998e65f ]
Fix collection leak when its_init_domain() failed in its_probe_one().
--- drivers/irqchip/irq-gic-v3-its.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/irqchip/irq-gic-v3-its.c +3 -1
@@ -5216,7 +5216,7 @@ static int __init its_probe_one(struct its_node *its) err =its_init_domain (its);if (err) - goto out_free_tables; + goto out_free_collection;raw_spin_lock (&its_lock);list_add (&its->entry, &its_nodes);
@@ -5224,6 +5224,8 @@ static int __init its_probe_one(struct its_node *its)return 0 ; +out_free_collection: +kfree (its->collections); out_free_tables:its_free_tables (its); out_free_cmd:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 436/1376 irqchip/gic-v3-its: Fix its node leak in gic_acpi_parse_madt_its()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kemeng Shi <[email protected]>
[ Upstream commit 698a8648ca8051d34722b09b8a8088c741120ac3 ]
Fix its node leak when its_probe_one() failed ingic_acpi_parse_madt_its().
--- drivers/irqchip/irq-gic-v3-its.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/irqchip/irq-gic-v3-its.c +6 -2
@@ -5638,9 +5638,13 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header, its->flags |=ITS_FLAGS_FORCE_NON_SHAREABLE ; err =its_probe_one (its); -if (!err) -return 0 ; +if (err) + goto probe_err; + +return 0 ; +probe_err: +its_node_destroy (its); node_err:iort_deregister_domain_token (its_entry->translation_id); dom_err:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 437/1376 selftests: timers: leap-a-day: Fix -w option and update usage comment
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiangshan Yi <[email protected]>
[ Upstream commit b4b66151a71445f3a71574136ddc82968c7b175e ]
Commit 98b74e1f3104 ("kselftests: timers: leap-a-day: Change default arguments to help test runs") replaced the -s option with -w and made "wait for the leap second" the non-default behaviour, but it only updated the switch/case handling. Two things were left inconsistent:
- The getopt() option string still lists 's' instead of 'w', so passing -w is rejected as an invalid option and the new behaviour cannot be selected at all.
- The file header comment still documents the removed -s option and an outdated default for -i.
Fix the getopt() string to accept 'w' (matching the existing case 'w':
handler) and update the header comment to describe -w, -t and the current -i default.
--- tools/testing/selftests/timers/leap-a-day.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
tools/testing/selftests/timers/leap-a-day.c +11 -8
@@ -9,16 +9,19 @@* kernel's leap-second behavior, as well as how well applications * handle the leap-second discontinuity. * -* Usage: leap-a-day [-s] [-i <num>] +* Usage: leap-a-day [-w] [-i <num>] [-t] * * Options: -* -s: Each iteration, set the date to 10 seconds before midnight GMT. -* This speeds up the number of leapsecond transitions tested, -* but because it calls settimeofday frequently, advancing the -* time by 24 hours every ~16 seconds, it may cause application -* disruption. +* -w: Only set the leap-second flag and wait for the leap second +* each iteration, instead of advancing the time. By default the +* date is set to 10 seconds before midnight GMT, which speeds up +* the number of leapsecond transitions tested, but because it +* calls settimeofday frequently, advancing the time by 24 hours +* every ~16 seconds, it may cause application disruption. * -* -i: Number of iterations to run (default: infinite) +* -i: Number of iterations to run (-1 = infinite, default: 10) +* +* -t: Print TAI time. * * Other notes: Disabling NTP prior to running this is advised, as the two * may conflict in their commands to the kernel.
@@ -186,7 +189,7 @@ int main(int argc, char **argv)int opt;/* Process arguments */ -while ((opt =getopt (argc, argv,"sti:" )) !=-1 ) { +while ((opt =getopt (argc, argv,"wti:" )) !=-1 ) {switch (opt) {case 'w' :printf ("Only setting leap-flag, not changing time. It could take up to a day for leap to trigger.\n" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 438/1376 clocksource: Unregister subsystem on device registration failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 3dee6537e728bd8137fda6eaf859f26e685943f7 ]
init_clocksource_sysfs() registers the clocksource subsystem before registering the clocksource device. If device_register() fails, the function returns the error while leaving the subsystem registered.
Unregister the clocksource subsystem on that failure path so the successful subsystem registration is unwound before returning.
--- kernel/time/clocksource.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
kernel/time/clocksource.c +6 -2
@@ -1510,8 +1510,12 @@ static int __init init_clocksource_sysfs(void) {int error =subsys_system_register (&clocksource_subsys,NULL ); -if (!error) - error =device_register (&device_clocksource); +if (error) +return error; + + error =device_register (&device_clocksource); +if (error) +bus_unregister (&clocksource_subsys);return error; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 439/1376 y2038: uapi: Use 64-bit __kernel_old_timespec::tv_nsec on x32
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Weißschuh <[email protected]>
[ Upstream commit 79ced850e549e8c86b772a79ea417a1425b5c04b ]
'struct __kernel_old_timespec' represents the 'native' time ABI of the kernel. On 32-bit systems it uses 32-bit fields and on 64-bit systems it uses 64-bit fields.
However the x86 x32 ABI uses the 64-bit time ABI natively. This is correctly handled for the 'tv_sec' fields, through the typedefs of '__kernel_old_time_t' -> '__kernel_long_t' -> 'long long'. The same treatment was missed for 'tv_nsec'.
In practice this might not make much of a difference as the value of 'tv_nsec' will always fit into 32 bits and the missing bits fall into the padding of the structure.
When introspecting the structure however, a difference can be observed.
Switch to 64-bit tv_nsec on x32. No other architectures or ABIs are affected.
While this could be interpreted as violating the POSIX requirement of 'timespec::tv_nsec' being 'long':
* __kernel_old_timespec is not actually the POSIX timespec type
* the requirement is gone in newer versions of POSIX
* this matches glibc
--- include/uapi/linux/time_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/uapi/linux/time_types.h +1 -1
@@ -30,7 +30,7 @@ struct __kernel_old_timeval {struct __kernel_old_timespec {__kernel_old_time_t tv_sec;/* seconds */ -long tv_nsec;/* nanoseconds */ +__kernel_long_t tv_nsec;/* nanoseconds */ };struct __kernel_old_itimerval {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 440/1376 timekeeping: Account for monotonicity adjustment in ntp_error
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Woodhouse <[email protected]>
[ Upstream commit b7befd6d91207cf3f4cecd68fea0c212093906cf ]
timekeeping_apply_adjustment() modifies xtime_nsec to ensure monotonicity when mult changes:
xtime_nsec -= offset
This ensures that the time reported to userspace does not jump when the multiplier is adjusted from one tick to the next. However, the ntp_error accumulator which tracks the difference between intended and actual clock position was not being updated to reflect this additional discrepancy.
An earlier attempt at this compensation existed as:
ntp_error -= (interval - offset) << ntp_error_shift
but was removed in commit c2cda2a5bda9 ("timekeeping/ntp: Don't align NTP frequency adjustments to ticks") because it was a major source of NTP error. That's because (interval - offset) was wrong: the subtraction of "interval" prematurely accounted for the changed xtime_interval of the next tick, which would be correctly accounted in the next accumulation anyway — a double subtraction.
What is actually needed is just the "offset" part: ntp_error must be told that xtime_nsec moved by "offset" without a corresponding change in the intended position. For the normal ±1 mult dithering this is negligible (the adjustments cancel over time), but for larger mult changes — such as when an external reference clock sets a new frequency — the one-time uncompensated offset is significant.
Fix by adjusting ntp_error by the correct amount:
ntp_error += offset << ntp_error_shift
This keeps ntp_error consistent with the actual xtime_nsec position after the adjustment, and ensures the discrepancy is correctly smoothed away over time and the clock returns to where it should have been.
--- kernel/time/timekeeping.c | 6 ++++++ 1 file changed, 6 insertions(+)
kernel/time/timekeeping.c +6 -0
@@ -2015,6 +2015,11 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,* xtime_nsec_2 = xtime_nsec_1 - offset * Which simplifies to: * xtime_nsec -= offset +* +* When subtracting offset from xtime_nsec, the same amount +* (in appropriate units) has to be added to ntp_error, in +* order to correctly track the delta between the time +* reported in xtime_nsec, and the intended time. */ if ((mult_adj >0 ) && (tk->tkr_mono.mult + mult_adj < mult_adj)) {/* NTP adjustment caused clocksource mult overflow */
@@ -2025,6 +2030,7 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk, tk->tkr_mono.mult += mult_adj; tk->xtime_interval += interval; tk->tkr_mono.xtime_nsec -= offset; + tk->ntp_error += offset << tk->ntp_error_shift; }/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 441/1376 clk: qcom: gdsc: propagate gdsc_check_status() errors from gdsc_poll_status
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herman van Hazendonk <[email protected]>
[ Upstream commit d69f0c2b8d292b4890c9f0fbe184dfc26c4de86c ]
gdsc_check_status() returns negative errno when the underlying regmap_read() fails -- e.g. when a parent regmap dies during system suspend, a CSR is removed by an HW debug tool, or the bus controller goes into protection. gdsc_poll_status() treats the result as a plain boolean ("is the GDSC in the requested state?"), so any negative error return is truncated to "true" and the poll exits with success even though the rail's real state is unknown:
do {
if (gdsc_check_status(sc, status))
return 0;
} while (ktime_us_delta(ktime_get(), start) < STATUS_POLL_TIMEOUT_US);
if (gdsc_check_status(sc, status))
return 0;
return -ETIMEDOUT;This silently misleads gdsc_toggle_logic() (which writes/un-writes SW_COLLAPSE on the strength of the poll succeeding) and the gdsc_init() sync path (which assumes the readback represents real silicon state).
Latch the return value, propagate negative errno immediately, and only treat a strictly-positive value as "reached the target state". Make the same change in the post-timeout final check so a regmap that comes back after the deadline does not silently degrade to -ETIMEDOUT.
--- drivers/clk/qcom/gdsc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/clk/qcom/gdsc.c +9 -2
@@ -103,14 +103,21 @@ static int gdsc_hwctrl(struct gdsc *sc, bool en)static int gdsc_poll_status (struct gdsc *sc,enum gdsc_status status) {ktime_t start; +int ret; start =ktime_get ();do { -if (gdsc_check_status (sc, status)) + ret =gdsc_check_status (sc, status); +if (ret <0 ) +return ret; +if (ret)return 0 ; }while (ktime_us_delta (ktime_get (), start) <STATUS_POLL_TIMEOUT_US ); -if (gdsc_check_status (sc, status)) + ret =gdsc_check_status (sc, status); +if (ret <0 ) +return ret; +if (ret)return 0 ;return -ETIMEDOUT ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 442/1376 clk: qcom: gdsc: propagate gdsc_enable() failure for ALWAYS_ON domains
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herman van Hazendonk <[email protected]>
[ Upstream commit eea55fc694e132aacbe2cf4be7f345115e3d1801 ]
GENPD_FLAG_ALWAYS_ON requires the underlying domain to be on at genpd_init() time -- the framework will refuse to register the domain otherwise. When the cold readback in gdsc_init() finds an ALWAYS_ON GDSC powered down, the driver tries to bring it back up:
} else if (sc->flags & ALWAYS_ON) {
/* If ALWAYS_ON GDSCs are not ON, turn them ON */
gdsc_enable(&sc->pd);
on = true;
}but discards the return value: if gdsc_enable() fails (regmap write error, the long-form sequence's status poll times out, or the HW_CTRL hand-off errors) the code still sets on=true and falls through to pm_genpd_init(..., !on) -- which then registers the domain in the ON state and sets GENPD_FLAG_ALWAYS_ON, even though the silicon is actually off. Subsequent consumer probes will see genpd report "on" while accessing dead registers and hang or read garbage.
Catch the failure and surface it: returning the error from gdsc_init() makes the provider probe fail with the underlying errno, which propagates to consumers as -EPROBE_DEFER (or fatal if the hardware really is broken) rather than silently lying about the rail state.
--- drivers/clk/qcom/gdsc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/clk/qcom/gdsc.c +3 -1
@@ -481,7 +481,9 @@ static int gdsc_init(struct gdsc *sc) }else if (sc->flags &ALWAYS_ON ) {/* If ALWAYS_ON GDSCs are not ON, turn them ON */ -gdsc_enable (&sc->pd); + ret =gdsc_enable (&sc->pd); +if (ret) +return ret; on = true; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 443/1376 clk: qcom: gdsc: tear down per-domain genpds in gdsc_unregister()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herman van Hazendonk <[email protected]>
[ Upstream commit 86b23609d5e17a770d03037e53c6a443e742a6e6 ]
gdsc_unregister() removes the OF provider entry and tears down the parent/subdomain wiring, but never calls pm_genpd_remove() on the individual generic_pm_domain structures registered by gdsc_init():
void gdsc_unregister(struct gdsc_desc *desc)
{
struct device *dev = desc->dev;
size_t num = desc->num;
gdsc_pm_subdomain_remove(desc, num);
of_genpd_del_provider(dev->of_node);
}That leaves dangling entries on the global gpd_list. After a provider unbind/rebind cycle (deferred-probe replay during early boot, real module unload of a clk driver that owns GDSCs, or an OF-overlay tear- down) the next gdsc_init() will end up trying to re-register a name that is still in the list and pm_genpd_init() returns -EEXIST.
While we are here, flip the order so the consumer-facing OF provider entry is the first thing removed -- otherwise a fresh of_genpd_get_from_provider() call racing with the teardown could attach to a domain that is mid-removal.
Iterate the scs[] array and pm_genpd_remove() each registered domain after the subdomain links are torn down. The regulators stay devm- managed (devm_regulator_get_optional() in gdsc_register()), so the release happens automatically when the underlying device is unbound; just the genpd accounting needs to be undone explicitly.
--- drivers/clk/qcom/gdsc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/clk/qcom/gdsc.c +9 -1
@@ -600,10 +600,18 @@ int gdsc_register(struct gdsc_desc *desc,void gdsc_unregister (struct gdsc_desc *desc) {struct device *dev = desc->dev; +struct gdsc **scs = desc->scs;size_t num = desc->num; +int i; -gdsc_pm_subdomain_remove (desc, num);of_genpd_del_provider (dev->of_node); +gdsc_pm_subdomain_remove (desc, num); + +for (i =0 ; i < num; i++) { +if (!scs[i]) +continue ; +pm_genpd_remove (&scs[i]->pd); + } }/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 444/1376 arm64: dts: qcom: sc8180x-primus: Rename regulator nodes
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Dybcio <[email protected]>
[ Upstream commit ae51d9396f9318189e91578878409d8ada152edb ]
The nodes would be sorted correctly, if their names started with "regulator-" (which is the style used in the latest submissions). Touch that up.
Stable-dep-of: 80bf2eb87bfb ("arm64: dts: qcom: sc8180x-primus: Describe the display power net")
--- arch/arm64/boot/dts/qcom/sc8180x-primus.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arm64/boot/dts/qcom/sc8180x-primus.dts +4 -4
@@ -165,7 +165,7 @@ reserved-region@9a500000 { }; }; - vreg_nvme_0p9: nvme-0p9-regulator { + vreg_nvme_0p9: regulator-nvme-0p9 { compatible = "regulator-fixed"; regulator-name = "vreg_nvme_0p9";
@@ -175,7 +175,7 @@ vreg_nvme_0p9: nvme-0p9-regulator { regulator-always-on; }; - vreg_nvme_3p3: nvme-3p3-regulator { + vreg_nvme_3p3: regulator-nvme-3p3 { compatible = "regulator-fixed"; regulator-name = "vreg_nvme_3p3";
@@ -188,7 +188,7 @@ vreg_nvme_3p3: nvme-3p3-regulator { regulator-always-on; }; - vdd_kb_tp_3v3: vdd-kb-tp-3v3-regulator { + vdd_kb_tp_3v3: regulator-vdd-kb-tp-3v3 { compatible = "regulator-fixed"; regulator-name = "vdd_kb_tp_3v3"; regulator-min-microvolt = <3300000>;
@@ -203,7 +203,7 @@ vdd_kb_tp_3v3: vdd-kb-tp-3v3-regulator { pinctrl-0 = <&kb_tp_3v3_en_active_state>; }; - vph_pwr: vph-pwr-regulator { + vph_pwr: regulator-vph-pwr { compatible = "regulator-fixed"; regulator-name = "vph_pwr"; regulator-min-microvolt = <3700000>;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 445/1376 arm64: dts: qcom: sc8180x-primus: Describe the display power net
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Dybcio <[email protected]>
[ Upstream commit 80bf2eb87bfbf1b7bc7b12228cbcc710b0a26275 ]
Describe and wire up the power supplies for the eDP panel and its backlight. Previously, this was only working because of settings inherited from the bootloader.
--- arch/arm64/boot/dts/qcom/sc8180x-primus.dts | 48 ++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-)
arch/arm64/boot/dts/qcom/sc8180x-primus.dts +47 -1
@@ -27,9 +27,10 @@ backlight: backlight { compatible = "pwm-backlight"; pwms = <&pmc8180c_lpg 4 1000000>; enable-gpios = <&pmc8180c_gpios 8 GPIO_ACTIVE_HIGH>; + power-supply = <&vled_bl_pw>; - pinctrl-names = "default"; pinctrl-0 = <&bl_pwm_default>; + pinctrl-names = "default"; }; chosen {
@@ -165,6 +166,38 @@ reserved-region@9a500000 { }; }; + vled_bl_pw: regulator-vled-bl-pw { + compatible = "regulator-fixed"; + + regulator-name = "VLED_BL_PW"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&pmc8180_2_gpios 1 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&bl_pwr_en>; + pinctrl-names = "default"; + + regulator-boot-on; + }; + + vreg_lcm_3v3: regulator-edp-3p3 { + compatible = "regulator-fixed"; + + regulator-name = "VREG_LCM_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 130 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&lcm_3v3_en>; + pinctrl-names = "default"; + + regulator-boot-on; + }; + vreg_nvme_0p9: regulator-nvme-0p9 { compatible = "regulator-fixed"; regulator-name = "vreg_nvme_0p9";
@@ -541,6 +574,7 @@ &mdss_edp { aux-bus { panel { compatible = "edp-panel"; + power-supply = <&vreg_lcm_3v3>; backlight = <&backlight>;
@@ -778,6 +812,12 @@ &xo_board_clk { }; /* PINCTRL */ +&pmc8180_2_gpios { + bl_pwr_en: bl-pwr-en-state { + pins = "gpio1"; + function = "normal"; + }; +}; &pmc8180c_gpios { bl_pwm_default: bl-pwm-default-state {
@@ -959,4 +999,10 @@ rx-pins { bias-pull-up; }; }; + + lcm_3v3_en: lcm-3v3-en-state { + pins = "gpio130"; + function = "gpio"; + bias-disable; + }; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 446/1376 arm64: dts: qcom: sc8180x-lenovo-flex-5g: Rename regulator nodes
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Dybcio <[email protected]>
[ Upstream commit 0b1c6d2a65fc41aa0d5f6617dd04043384678d61 ]
Align with the contemporary way of naming regulator nodes (regulator- prefix) in preparation for adding more of them.
Reorder the renamed entries to match the expectations of the DT coding style doc.
Stable-dep-of: d5f5c089858f ("arm64: dts: qcom: sc8180x-lenovo-flex-5g: Describe the display power net")
--- .../boot/dts/qcom/sc8180x-lenovo-flex-5g.dts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts +8 -8
@@ -162,14 +162,7 @@ cdsp_mem: cdsp-region@98900000 { }; }; - vph_pwr: vph-pwr-regulator { - compatible = "regulator-fixed"; - regulator-name = "vph_pwr"; - regulator-min-microvolt = <3700000>; - regulator-max-microvolt = <3700000>; - }; - - vreg_s4a_1p8: pm8150-s4-regulator { + vreg_s4a_1p8: regulator-pm8150-s4 { compatible = "regulator-fixed"; regulator-name = "vreg_s4a_1p8";
@@ -182,6 +175,13 @@ vreg_s4a_1p8: pm8150-s4-regulator { vin-supply = <&vph_pwr>; }; + vph_pwr: regulator-vph-pwr { + compatible = "regulator-fixed"; + regulator-name = "vph_pwr"; + regulator-min-microvolt = <3700000>; + regulator-max-microvolt = <3700000>; + }; + usbprim-sbu-mux { compatible = "pericom,pi3usb102", "gpio-sbu-mux";
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 447/1376 arm64: dts: qcom: sc8180x-lenovo-flex-5g: Describe the display power net
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Dybcio <[email protected]>
[ Upstream commit d5f5c089858f7accd1e4574c0c09d811e90eb51f ]
Describe and wire up the power supplies for the eDP panel and its backlight. Previously, this was only working because of settings inherited from the bootloader.
--- .../boot/dts/qcom/sc8180x-lenovo-flex-5g.dts | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+)
arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts +47 -0
@@ -26,6 +26,7 @@ backlight: backlight { compatible = "pwm-backlight"; pwms = <&pmc8180c_lpg 4 1000000>; enable-gpios = <&pmc8180c_gpios 8 GPIO_ACTIVE_HIGH>; + power-supply = <&vled_bl_pw>; pinctrl-0 = <&bl_pwm_default>; pinctrl-names = "default";
@@ -162,6 +163,38 @@ cdsp_mem: cdsp-region@98900000 { }; }; + vled_bl_pw: regulator-vled-bl-pw { + compatible = "regulator-fixed"; + + regulator-name = "VLED_BL_PW"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&pmc8180_2_gpios 1 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&bl_pwr_en>; + pinctrl-names = "default"; + + regulator-boot-on; + }; + + vreg_lcm_3v3: regulator-edp-3p3 { + compatible = "regulator-fixed"; + + regulator-name = "VREG_LCM_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 130 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&lcm_3v3_en>; + pinctrl-names = "default"; + + regulator-boot-on; + }; + vreg_s4a_1p8: regulator-pm8150-s4 { compatible = "regulator-fixed"; regulator-name = "vreg_s4a_1p8";
@@ -446,6 +479,7 @@ &mdss_edp { aux-bus { panel { compatible = "edp-panel"; + power-supply = <&vreg_lcm_3v3>; no-hpd; backlight = <&backlight>;
@@ -484,6 +518,13 @@ &pcie3_phy { status = "okay"; }; +&pmc8180_2_gpios { + bl_pwr_en: bl-pwr-en-state { + pins = "gpio1"; + function = "normal"; + }; +}; + &pmc8180_pwrkey { status = "okay"; };
@@ -781,6 +822,12 @@ ts_int_default: ts-int-default-state { drive-strength = <2>; }; + lcm_3v3_en: lcm-3v3-en-state { + pins = "gpio130"; + function = "gpio"; + bias-disable; + }; + usbprim_sbu_default: usbprim-sbu-state { oe-n-pins { pins = "gpio152";
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 448/1376 perf data convert json: Fix trace_seq memory leak in process_sample_event()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tanushree Shah <[email protected]>
[ Upstream commit dcb87c88952046ef43cb5ba3a5b95eb29c362a16 ]
Unlike the in-kernel trace_seq which uses a statically allocated buffer, the userspace traceevent library's trace_seq uses a dynamically allocated one. Therefore, every trace_seq_init() call must be paired with a trace_seq_destroy(), otherwise it produces a memory leak.
In process_sample_event(), a trace_seq is initialized for each field when formatting tracepoint raw_data, but the matching trace_seq_destroy() is never called, leaking memory for every field of every sample processed.
Add the missing trace_seq_destroy() after using the trace_seq buffer to properly free the allocated memory.
Detected with Valgrind on a perf.data file with 2,729 tracepoint samples:
Before: definitely lost: 55,537,664 bytes in 13,559 blocks
After: definitely lost: 0 bytes in 0 blocks
--- tools/perf/util/data-convert-json.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/util/data-convert-json.c +1 -0
@@ -242,6 +242,7 @@ static int process_sample_event(const struct perf_tool *tool,trace_seq_init (&s);tep_print_field (&s, sample->raw_data, fields[i]);output_json_key_string (out, true,3 , fields[i]->name, s.buffer); +trace_seq_destroy (&s); i++; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 449/1376 thermal/drivers/rcar: Fix error checking in probe()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit dd04ad1cdabcad51e34b74b4e91b9aeb7180d05d ]
This code accidentally calls thermal_zone_device_enable() before checking whether thermal_zone_device_register_with_trips() failed. Move the call until later to avoid an error pointer dereference of "priv->zone".
The driver works differently depending on if we are using OF thermal or not. We use thermal_add_hwmon_sysfs() if we are using OF thermal and call thermal_zone_device_enable() if not. We can share same error check for if either of these fail.
Moving the thermal_zone_device_enable() call is a bit cleaner as well. The original code used a three step process to cleanup:
1. Call thermal_zone_device_unregister() to cleanup.
2. Set priv->zone to an error pointer to preserve the error code.
3. Set priv->zone to NULL to avoid a second call to thermal_zone_device_unregister() in the rcar_thermal_remove() function.
Now we can just do a direct goto error_unregister and rcar_thermal_remove() handles the cleanup properly.
--- drivers/thermal/renesas/rcar_thermal.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-)
drivers/thermal/renesas/rcar_thermal.c +5 -10
@@ -492,12 +492,6 @@ static int rcar_thermal_probe(struct platform_device *pdev)"rcar_thermal" , trips,ARRAY_SIZE (trips), priv, &rcar_thermal_zone_ops,NULL ,0 , idle); - - ret =thermal_zone_device_enable (priv->zone); -if (ret) { -thermal_zone_device_unregister (priv->zone); - priv->zone =ERR_PTR (ret); - } }if (IS_ERR (priv->zone)) {dev_err (dev,"can't register thermal zone\n" );
@@ -506,11 +500,12 @@ static int rcar_thermal_probe(struct platform_device *pdev) goto error_unregister; } -if (chip->use_of_thermal) { +if (chip->use_of_thermal) ret =thermal_add_hwmon_sysfs (priv->zone); -if (ret) - goto error_unregister; - } +else + ret =thermal_zone_device_enable (priv->zone); +if (ret) + goto error_unregister;rcar_thermal_irq_enable (priv);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 450/1376 usb: typec: ucsi: unregister debugfs entries on teardown
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bjorn Andersson <[email protected]>
[ Upstream commit eed73a65ab609b79d53de88cccc34b36dfe753c4 ]
ucsi_register() creates per-instance debugfs entries, but ucsi_unregister() keeps them around until ucsi_destroy().
Drivers like ucsi_glink that unregister/register the same UCSI instance across remoteproc restart then try to create an already existing debugfs directory and log:
debugfs: 'pmic_glink.ucsi.0' already exists in 'ucsi'
Unregister debugfs entries as part of ucsi_unregister(), and clear ucsi->debugfs after freeing it so repeated unregister paths remain safe.
--- drivers/usb/typec/ucsi/debugfs.c | 1 + drivers/usb/typec/ucsi/ucsi.c | 2 ++ 2 files changed, 3 insertions(+)
drivers/usb/typec/ucsi/debugfs.c +1 -0
@@ -89,6 +89,7 @@ void ucsi_debugfs_unregister(struct ucsi *ucsi)debugfs_remove_recursive (ucsi->debugfs->dentry);kfree (ucsi->debugfs); + ucsi->debugfs =NULL ; }void ucsi_debugfs_init (void )
drivers/usb/typec/ucsi/ucsi.c +2 -0
@@ -2102,6 +2102,8 @@ void ucsi_unregister(struct ucsi *ucsi)cancel_delayed_work_sync (&ucsi->work);cancel_work_sync (&ucsi->resume_work); +ucsi_debugfs_unregister (ucsi); +/* Disable notifications */ ucsi->ops->async_control (ucsi, cmd);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 451/1376 usb: gadget: r8a66597: avoid double free of ep0_req in probe error path
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hongyan Xu <[email protected]>
[ Upstream commit 41d541e3718db01668a4cd29815ee4b3b55f76d2 ]
If usb_add_gadget_udc() fails, r8a66597_probe() jumps to err_add_udc and frees ep0_req, then falls through to clean_up2 where ep0_req is freed again when it is non-NULL.
Remove the redundant free from err_add_udc and keep the cleanup in clean_up2 so the request is released exactly once.
Issue found using a prototype static analysis tool and confirmed by code review.
--- drivers/usb/gadget/udc/r8a66597-udc.c | 1 - 1 file changed, 1 deletion(-)
drivers/usb/gadget/udc/r8a66597-udc.c +0 -1
@@ -1951,7 +1951,6 @@ static int r8a66597_probe(struct platform_device *pdev)return 0 ; err_add_udc: -r8a66597_free_request (&r8a66597->ep[0 ].ep, r8a66597->ep0_req); clean_up2:if (r8a66597->pdata->on_chip)clk_disable_unprepare (r8a66597->clk);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 452/1376 udf: Mark LVID buffer as uptodate before marking it dirty
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Nogikh <[email protected]>
[ Upstream commit fb0601134c7e51728bd098abc6909315de1e5d86 ]
When an I/O error occurs while writing the Logical Volume Integrity Descriptor (LVID) buffer to the block device, the block layer's completion handler (end_buffer_write_sync()) clears the BH_Uptodate flag on the buffer. However, the buffer still contains valid LVID data in memory. If the filesystem is subsequently remounted read-write or synced, udf_open_lvid() or udf_sync_fs() will modify the LVID buffer and call mark_buffer_dirty(). This triggers a spurious WARN_ON_ONCE(!buffer_uptodate(bh)) warning in mark_buffer_dirty() because the buffer is not marked uptodate, even though its in-memory contents are valid and are about to be overwritten.
To prevent this spurious warning, unconditionally set the BH_Uptodate flag before calling mark_buffer_dirty() in udf_open_lvid() and udf_sync_fs(). This acknowledges that the in-memory buffer is valid and matches the workaround previously applied to udf_close_lvid() in commit 853a0c25baf9 ("udf: Mark LVID buffer as uptodate before marking it dirty"). Extending this workaround ensures consistent behavior across all LVID updates.
Buffer I/O error on dev loop0, logical block 128, lost sync page write
------------[ cut here ]------------ !buffer_uptodate(bh) WARNING: fs/buffer.c:1087 at mark_buffer_dirty+0x299/0x410 fs/buffer.c:1087 ... Call Trace: <TASK> udf_open_lvid+0x369/0x5b0 fs/udf/super.c:2078 udf_reconfigure+0x336/0x540 fs/udf/super.c:679 reconfigure_super+0x232/0x8f0 fs/super.c:1080 vfs_cmd_reconfigure fs/fsopen.c:268 [inline] vfs_fsconfig_locked+0x171/0x320 fs/fsopen.c:297 __do_sys_fsconfig fs/fsopen.c:463 [inline] __se_sys_fsconfig+0x6b9/0x810 fs/fsopen.c:350 do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94 </TASK>
--- fs/udf/super.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-)
fs/udf/super.c +14 -9
@@ -2050,6 +2050,17 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,return 0 ; } +static void udf_mark_buffer_dirty (struct buffer_head *bh) +{ +/* +* We set buffer uptodate unconditionally here to avoid spurious +* warnings from mark_buffer_dirty() when previous EIO has marked +* the buffer as !uptodate +*/ +set_buffer_uptodate (bh); +mark_buffer_dirty (bh); +} +static void udf_finalize_lvid (struct logicalVolIntegrityDesc *lvid) {struct timespec64 ts;
@@ -2085,7 +2096,7 @@ static void udf_open_lvid(struct super_block *sb)UDF_SET_FLAG (sb,UDF_FLAG_INCONSISTENT );udf_finalize_lvid (lvid); -mark_buffer_dirty (bh); +udf_mark_buffer_dirty (bh); sbi->s_lvid_dirty =0 ;mutex_unlock (&sbi->s_alloc_mutex);/* Make opening of filesystem visible on the media immediately */
@@ -2118,14 +2129,8 @@ static void udf_close_lvid(struct super_block *sb)if (!UDF_QUERY_FLAG (sb,UDF_FLAG_INCONSISTENT )) lvid->integrityType =cpu_to_le32 (LVID_INTEGRITY_TYPE_CLOSE ); -/* -* We set buffer uptodate unconditionally here to avoid spurious -* warnings from mark_buffer_dirty() when previous EIO has marked -* the buffer as !uptodate -*/ -set_buffer_uptodate (bh);udf_finalize_lvid (lvid); -mark_buffer_dirty (bh); +udf_mark_buffer_dirty (bh); sbi->s_lvid_dirty =0 ;mutex_unlock (&sbi->s_alloc_mutex);/* Make closing of filesystem visible on the media immediately */
@@ -2407,7 +2412,7 @@ static int udf_sync_fs(struct super_block *sb, int wait)* Blockdevice will be synced later so we don't have to submit * the buffer for IO */ -mark_buffer_dirty (bh); +udf_mark_buffer_dirty (bh); sbi->s_lvid_dirty =0 ; }mutex_unlock (&sbi->s_alloc_mutex);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 453/1376 perf vendor events amd: Reintroduce deprecated Zen 5 core events
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sandipan Das <[email protected]>
[ Upstream commit eda39f98bbc5ce8b7b0be10193d2de38ed59da6c ]
Maintain backward compatibility by reintroducing the events that were previously removed by commit 047979af3bf6 ("perf vendor events amd:
Update Zen 5 core events"). Also set the deprecated flag and update the descriptions to point users to the correct alternative.
--- .../arch/x86/amdzen5/floating-point.json | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+)
tools/perf/pmu-events/arch/x86/amdzen5/floating-point.json +42 -0
@@ -383,6 +383,13 @@ "BriefDescription": "Retired MMX integer VNNI ops.", "UMask": "0x0c" }, + { + "EventName": "sse_avx_ops_retired.mmx_pack", + "EventCode": "0x0b", + "BriefDescription": "This event is deprecated. Refer to new event sse_avx_ops_retired.mmx_vnni", + "Deprecated": "1", + "UMask": "0x0c" + }, { "EventName": "sse_avx_ops_retired.mmx_logical", "EventCode": "0x0b",
@@ -449,6 +456,13 @@ "BriefDescription": "Retired SSE and AVX integer convert or pack ops.", "UMask": "0x80" }, + { + "EventName": "sse_avx_ops_retired.sse_avx_clm", + "EventCode": "0x0b", + "BriefDescription": "This event is deprecated. Refer to new event sse_avx_ops_retired.sse_avx_cvt", + "Deprecated": "1", + "UMask": "0x80" + }, { "EventName": "sse_avx_ops_retired.sse_avx_shift", "EventCode": "0x0b",
@@ -473,6 +487,13 @@ "BriefDescription": "Retired SSE and AVX integer VNNI ops.", "UMask": "0xc0" }, + { + "EventName": "sse_avx_ops_retired.sse_avx_pack", + "EventCode": "0x0b", + "BriefDescription": "This event is deprecated. Refer to new event sse_avx_ops_retired.sse_avx_vnni", + "Deprecated": "1", + "UMask": "0xc0" + }, { "EventName": "sse_avx_ops_retired.sse_avx_logical", "EventCode": "0x0b",
@@ -731,6 +752,13 @@ "BriefDescription": "Retired 128-bit packed integer convert or pack ops.", "UMask": "0x08" }, + { + "EventName": "packed_int_op_type.int128_clm", + "EventCode": "0x0d", + "BriefDescription": "This event is deprecated. Refer to new event packed_int_op_type.int128_cvt", + "Deprecated": "1", + "UMask": "0x08" + }, { "EventName": "packed_int_op_type.int128_shift", "EventCode": "0x0d",
@@ -755,6 +783,13 @@ "BriefDescription": "Retired 128-bit packed integer VNNI ops.", "UMask": "0x0c" }, + { + "EventName": "packed_int_op_type.int128_pack", + "EventCode": "0x0d", + "BriefDescription": "This event is deprecated. Refer to new event packed_int_op_type.int128_vnni", + "Deprecated": "1", + "UMask": "0x0c" + }, { "EventName": "packed_int_op_type.int128_logical", "EventCode": "0x0d",
@@ -845,6 +880,13 @@ "BriefDescription": "Retired 256-bit packed integer VNNI ops.", "UMask": "0xc0" }, + { + "EventName": "packed_int_op_type.int256_pack", + "EventCode": "0x0d", + "BriefDescription": "This event is deprecated. Refer to new event packed_int_op_type.int256_vnni", + "Deprecated": "1", + "UMask": "0xc0" + }, { "EventName": "packed_int_op_type.int256_logical", "EventCode": "0x0d",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 454/1376 perf dso: Fix kallsyms DSO detection with fallback logic
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tanushree Shah <[email protected]>
[ Upstream commit 8c5f60344b07f839267c0c835962e2206143be85 ]
The current kallsyms detection in dso__is_kallsyms() uses the dso_binary_type enum which fixes the issue of kallsyms being cached in the build-id cache for out-of-tree modules.
However, during build-id injection in perf record/inject, dso_binary_type has not been explicitly set yet,so dso__binary_type() returns DSO_BINARY_TYPE__NOT_FOUND instead of DSO_BINARY_TYPE__KALLSYMS for the kernel DSO. The current check then fails to identify it as kallsyms, causing build-id symlinks to not be created in ~/.debug/.build-id/ and perf archive to fail with "Cannot stat" errors.
Steps to reproduce the issue:
1. rm -rf ~/.debug/.build-id
2. perf record sleep 1
3. perf archive
Fix by falling back to matching long_name against the known kallsyms strings explicitly when binary_type is not yet set
(== DSO_BINARY_TYPE__NOT_FOUND). Use strcmp() for exact matching of fixed names and strict validation for guest kallsyms with embedded PID to prevent path traversal attacks.
--- tools/perf/util/dso.h | 57 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-)
tools/perf/util/dso.h +56 -1
@@ -9,6 +9,7 @@#include <stdbool.h> #include <stdio.h> #include <linux/bitops.h> +#include <string.h> #include "build-id.h" #include "mutex.h" #include <internal/rc_check.h>
@@ -19,6 +20,40 @@ struct perf_env;#define DSO__NAME_KALLSYMS "[kernel.kallsyms]"#define DSO__NAME_KCORE "[kernel.kcore]" +#define DSO__NAME_GUEST_KALLSYMS "[guest.kernel.kallsyms]" +#define DSO__NAME_GUEST_KALLSYMS_PID_PREFIX "[guest.kernel.kallsyms." + +/* +* Validate names of the form "[guest.kernel.kallsyms.<pid>]", where +* <pid> is the PID of the guest VM and varies per guest, so it +* cannot be matched with strcmp() against a fixed string. +* +* Every character after the fixed prefix must be a decimal digit, +* with ']' immediately terminating the digit run and nothing +* following it. This rules out '/', "..", or any other character +* being smuggled into the name. +*/ +static inline bool is_guest_kallsyms_pid_name (const char *name) +{ +const size_t prefix_len =sizeof (DSO__NAME_GUEST_KALLSYMS_PID_PREFIX ) -1 ; +size_t digits; + +if (strncmp (name,DSO__NAME_GUEST_KALLSYMS_PID_PREFIX , prefix_len) !=0 ) +return false; + + digits =strspn (name + prefix_len,"0123456789" ); +if (digits ==0 ) +return false; + +/* ']' must terminate the digit run, with nothing trailing it */ +if (name[prefix_len + digits] !=']' ) +return false; + +if (name[prefix_len + digits +1 ] !='\0' ) +return false; + +return true; +}enum dso_binary_type {DSO_BINARY_TYPE__KALLSYMS =0 ,
@@ -809,8 +844,28 @@ static inline bool dso__is_kcore(const struct dso *dso)static inline bool dso__is_kallsyms (const struct dso *dso) {enum dso_binary_type bt =dso__binary_type (dso); +const char *name; + +if (bt ==DSO_BINARY_TYPE__KALLSYMS || bt ==DSO_BINARY_TYPE__GUEST_KALLSYMS ) +return true; + +if (bt !=DSO_BINARY_TYPE__NOT_FOUND ) +return false; + +if (!dso__kernel (dso)) +return false; + + name =dso__long_name (dso); +if (!name) +return false; + +if (!strcmp (name,DSO__NAME_KALLSYMS )) +return true; + +if (!strcmp (name,DSO__NAME_GUEST_KALLSYMS )) +return true; -return bt ==DSO_BINARY_TYPE__KALLSYMS || bt ==DSO_BINARY_TYPE__GUEST_KALLSYMS ; +return is_guest_kallsyms_pid_name (name); }bool dso__is_object_file (const struct dso *dso);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 455/1376 bpf: Fix vmlinux BTF prep race in bpf_get_btf_vmlinux
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 92863e678070f57c17c868e4bfa2441a5c61ad2b ]
bpf_get_btf_vmlinux() lazily parses the vmlinux BTF under the bpf_verifier_lock, but publishes the result through a plain store and re-checks it through a plain lockless load. Nothing orders the stores initializing the struct btf inside btf_parse_vmlinux() against the store publishing the pointer: On a weakly ordered arch, a concurrent first-time caller taking the lockless fast path could in principle observe the pointer before the parsed contents are visible. The mutex_unlock() does not help such a reader given it only synchronizes with a later acquisition of the same lock. Thus, publish the pointer with smp_store_release() and read it on the fast path with smp_load_acquire().
Acquire semantics are needed rather than a dependency-ordered READ_ONCE(): btf_parse_vmlinux() also populates globals outside the returned object (e.g. bpf_ctx_convert.t). An address dependency would only order accesses performed through the pointer and not cover other globals.
--- kernel/bpf/verifier.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-)
kernel/bpf/verifier.c +16 -4
@@ -22781,13 +22781,25 @@ static int check_attach_btf_id(struct bpf_verifier_env *env)struct btf *bpf_get_btf_vmlinux (void ) { -if (!btf_vmlinux &&IS_ENABLED (CONFIG_DEBUG_INFO_BTF )) { +/* Pairs with the smp_store_release() on the parse path below. */ +struct btf *btf =smp_load_acquire (&btf_vmlinux); + +if (!btf &&IS_ENABLED (CONFIG_DEBUG_INFO_BTF )) {mutex_lock (&bpf_verifier_lock); -if (!btf_vmlinux) - btf_vmlinux =btf_parse_vmlinux (); + btf = btf_vmlinux; +if (!btf) { + btf =btf_parse_vmlinux (); +/* +* Order the parsed BTF contents and the globals the +* parse populated (e.g. bpf_ctx_convert.t) before +* the pointer publication. Pairs with the acquire +* on the lockless fast path above. +*/ +smp_store_release (&btf_vmlinux, btf); + }mutex_unlock (&bpf_verifier_lock); } -return btf_vmlinux; +return btf; }int bpf_check (struct bpf_prog **prog,union bpf_attr *attr,bpfptr_t uattr,__u32 uattr_size)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 456/1376 efi: fix stale reference to efi_recover_from_page_fault()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
[ Upstream commit 718ee46ba4d95d28d50d3f6437afbbe2be531175 ]
efi_recover_from_page_fault() was renamed to efi_crash_gracefully_on_page_fault(), but the comment above enum efi_rts_ids was not updated. Use the current name.
--- include/linux/efi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/linux/efi.h +2 -2
@@ -1239,8 +1239,8 @@ efi_call_acpi_prm_handler(efi_status_t (__efiapi *handler_addr)(u64, void *),/* * efi_runtime_service() function identifiers. -* "NONE" is used by efi_recover_from_page_fault() to check if the page -* fault happened while executing an efi runtime service. +* "NONE" is used by efi_crash_gracefully_on_page_fault() to check if the +* page fault happened while executing an efi runtime service. */ enum efi_rts_ids {EFI_NONE ,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 457/1376 bpf: Fix use-after-free on mm_struct in bpf_find_vma()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sanghyun Park <[email protected]>
[ Upstream commit 47b079e2117a2ee52e21f8b72935900c702fc0b5 ]
bpf_find_vma() reads task->mm and calls mmap_read_trylock(mm) without holding a reference on the mm. On a foreign task, a concurrent exit_mm() can free the mm_struct between the lockless read and the trylock, resulting in a use-after-free. mm_struct is not SLAB_TYPESAFE_BY_RCU.
For the current task, task->mm is stable. For a foreign task, pin the mm under task->alloc_lock and release it with mmput_async(), mirroring commit d8e27d2d22b6 ("bpf: fix mm lifecycle in open-coded task_vma iterator"). Use spin_trylock() instead of get_task_mm() so BPF context does not block on alloc_lock. Reject irqs-disabled contexts and !CONFIG_MMU on the foreign-task path because dropping the mm reference is not safe there.
Race:
CPU0 (BPF program) CPU1 (exiting task)
============================ ==========================
bpf_find_vma(foreign_task):
mm = task->mm
exit_mm():
task->mm = NULL
mmput(mm) -> frees mm_struct
mmap_read_trylock(mm)
// UAF on mm--- kernel/bpf/task_iter.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-)
kernel/bpf/task_iter.c +33 -3
@@ -760,6 +760,7 @@ BPF_CALL_5(bpf_find_vma, struct task_struct *, task, u64, start,struct mmap_unlock_irq_work *work =NULL ;struct vm_area_struct *vma;bool irq_work_busy = false; +bool __maybe_unused mmput_needed = false;struct mm_struct *mm;int ret = -ENOENT ;
@@ -769,14 +770,38 @@ BPF_CALL_5(bpf_find_vma, struct task_struct *, task, u64, start,if (!task)return -ENOENT ; - mm = task->mm; +if (task == current) { + mm = task->mm; + }else { +/* +* Foreign task: pin task->mm against a concurrent exit_mm(). +* Use trylock on alloc_lock instead of get_task_mm()'s +* blocking task_lock() to avoid deadlocking the target task. +*/ +if (!IS_ENABLED (CONFIG_MMU )) +return -EOPNOTSUPP ; +if (irqs_disabled ()) +return -EBUSY ; +if (!spin_trylock (&task->alloc_lock)) +return -EBUSY ; + mm = task->mm; +if (mm && !(task->flags &PF_KTHREAD )) { +mmget (mm); + mmput_needed = true; + }else { + mm =NULL ; + } +spin_unlock (&task->alloc_lock); + }if (!mm)return -ENOENT ; irq_work_busy =bpf_mmap_unlock_get_irq_work (&work); -if (irq_work_busy || !mmap_read_trylock (mm)) -return -EBUSY ; +if (irq_work_busy || !mmap_read_trylock (mm)) { + ret = -EBUSY ; + goto out; + } vma =find_vma (mm, start);
@@ -786,6 +811,11 @@ BPF_CALL_5(bpf_find_vma, struct task_struct *, task, u64, start, ret =0 ; }bpf_mmap_unlock_mm (work, mm); +out: +#ifdef CONFIG_MMU +if (mmput_needed) +mmput_async (mm); +#endif return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 458/1376 bus: mhi: ep: Fix device refcount leak in the error path of MHI device creation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 6f12862600bb70e599a614d706a095ea5f8f9858 ]
mhi_ep_create_device() takes one device reference for the UL channel and another for the DL channel after allocating the transfer device. These references are normally released by mhi_ep_destroy_device() before the device itself is removed.
If dev_set_name() or device_add() fails, the error path currently drops only one reference. The remaining channel references keep the device from being released and leave the channels associated with a device that was never registered.
Route both failures through a common unwind path that drops the DL channel reference, the UL channel reference, and the initial reference from device_initialize().
--- drivers/bus/mhi/ep/main.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
drivers/bus/mhi/ep/main.c +10 -5
@@ -1340,14 +1340,19 @@ static int mhi_ep_create_device(struct mhi_ep_cntrl *mhi_cntrl, u32 ch_id) ret =dev_set_name (&mhi_dev->dev,"%s_%s" ,dev_name (&mhi_cntrl->mhi_dev->dev), mhi_dev->name); -if (ret) { -put_device (&mhi_dev->dev); -return ret; - } +if (ret) + goto err_put_channels; ret =device_add (&mhi_dev->dev);if (ret) -put_device (&mhi_dev->dev); + goto err_put_channels; + +return 0 ; + +err_put_channels: +put_device (&mhi_dev->dev);/* DL channel reference */ +put_device (&mhi_dev->dev);/* UL channel reference */ +put_device (&mhi_dev->dev);/* device_initialize() reference */ return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 459/1376 iommu/mediatek-v1: Fix off-by-one in MT2701_LARB_NR_MAX
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Akari Tsuyukusa <[email protected]>
[ Upstream commit aebaa93f3da1572877579c2e15ebf27be2dcc7fb ]
The mt2701_m4u_in_larb[] array contains 4 (for LARB0 to LARB3) elements, meaning mt2701_m4u_to_larb() can legitimately return 3. The current check if (larbid >= MT2701_LARB_NR_MAX) incorrectly rejects valid LARB3 with -EINVAL.
Fix this off-by-one error by updating MT2701_LARB_NR_MAX to 4.
Note that this does not cause immediate issues with the current mt2701.dtsi and mt7623n.dtsi because it only defines 3 LARBs:
mediatek,larbs = <&larb0 &larb1 &larb2>;
Thus, larbid never reaches 3 in the existing upstream device tree.
--- drivers/iommu/mtk_iommu_v1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iommu/mtk_iommu_v1.c +1 -1
@@ -78,7 +78,7 @@/* MTK generation one iommu HW only support 4K size mapping */ #define MT2701_IOMMU_PAGE_SHIFT 12#define MT2701_IOMMU_PAGE_SIZE (1UL << MT2701_IOMMU_PAGE_SHIFT) -#define MT2701_LARB_NR_MAX 3 +#define MT2701_LARB_NR_MAX 4/* * MTK m4u support 4GB iova address space, and only support 4K page
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 460/1376 iommu/msm: Return -ENOMEM on memory allocation failure in probe
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Zapolskiy <[email protected]>
[ Upstream commit b0d50c9016c4c2959dfa61bf9549cf98f9aa19cd ]
If dynamic memory allocation in driver's probe function execution fails, it should be reported to the driver's framework with -ENOMEM error code.
--- drivers/iommu/msm_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iommu/msm_iommu.c +1 -1
@@ -720,7 +720,7 @@ static int msm_iommu_probe(struct platform_device *pdev) iommu =devm_kzalloc (&pdev->dev,sizeof (*iommu),GFP_KERNEL );if (!iommu) -return -ENODEV ; +return -ENOMEM ; iommu->dev = &pdev->dev;INIT_LIST_HEAD (&iommu->ctx_list);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 461/1376 iommu/amd: Prevent SB IOAPIC from overriding IVRS validation errors
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wei Wang <[email protected]>
[ Upstream commit 854056480f9217568e3ab5edd81a9347a173ea79 ]
The check_ioapic_information() function validates IOAPICs against the IVRS table to safely disable Interrupt Remapping (IR) if the BIOS provides a broken topology.
Currently, the validation loop contains a bug: If an unmapped secondary IOAPIC is encountered, 'ret' is set to false. But if the Southbridge (SB) IOAPIC is enumerated after it in the MADT, the loop overwrites 'ret' to true.
This bypasses the validation failure and leaves IR enabled. When devices attached to the unmapped secondary IOAPIC fire interrupts, the IOMMU drops them due to the missing Requestor ID, leading to localized device hangs.
Fix this by initializing 'ret' to true and only toggling it to false upon encountering a validation error, ensuring failures are never erased.
--- drivers/iommu/amd/init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/iommu/amd/init.c +2 -2
@@ -2973,7 +2973,7 @@ static bool __init check_ioapic_information(void)int idx; has_sb_ioapic = false; - ret = false; + ret = true;/* * If we have map overrides on the kernel command line the
@@ -2993,7 +2993,6 @@ static bool __init check_ioapic_information(void) ret = false; }else if (devid ==IOAPIC_SB_DEVID ) { has_sb_ioapic = true; - ret = true; } }
@@ -3007,6 +3006,7 @@ static bool __init check_ioapic_information(void)* device id for the IOAPIC in the system. */ pr_err ("%s: No southbridge IOAPIC found\n" , fw_bug); + ret = false; }if (!ret)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 462/1376 iommu/amd: Add support for Hygon family 18h model 4h IOAPIC
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fu Hao <[email protected]>
[ Upstream commit 5beda8cadb1f072140e58b1edb7604444a42d955 ]
The SB IOAPIC is on the device 0xb from Hygon family 18h model 4h.
Stable-dep-of: 04fee302fac7 ("iommu/amd: Fix false positive in SB IOAPIC IVRS validation")
--- drivers/iommu/amd/init.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/iommu/amd/init.c +9 -1
@@ -2966,6 +2966,9 @@ static void __init free_iommu_resources(void)/* SB IOAPIC is always on this device in AMD systems */ #define IOAPIC_SB_DEVID ((0x00 << 8) | PCI_DEVFN(0x14, 0)) +/* SB IOAPIC for Hygon family 18h model 4h is on the device 0xb */ +#define IOAPIC_SB_DEVID_FAM18H_M4H ((0x00 << 8) | PCI_DEVFN(0xb, 0)) +static bool __init check_ioapic_information (void ) {const char *fw_bug =FW_BUG ;
@@ -2991,7 +2994,12 @@ static bool __init check_ioapic_information(void)pr_err ("%s: IOAPIC[%d] not in IVRS table\n" , fw_bug, id); ret = false; - }else if (devid ==IOAPIC_SB_DEVID ) { + }else if (devid ==IOAPIC_SB_DEVID || + (boot_cpu_data.x86_vendor ==X86_VENDOR_HYGON && + boot_cpu_data.x86 ==0x18 && + boot_cpu_data.x86_model >=0x4 && + boot_cpu_data.x86_model <=0xf && + devid ==IOAPIC_SB_DEVID_FAM18H_M4H )) { has_sb_ioapic = true; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 463/1376 iommu/amd: Fix false positive in SB IOAPIC IVRS validation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wei Wang <[email protected]>
[ Upstream commit 04fee302fac762a242ff1ad6810cff90c2a350ba ]
The check_ioapic_information() function is designed to prevent boot hangs by ensuring the Southbridge (SB) IOAPIC is properly mapped in the IVRS table before enabling Interrupt Remapping.
Currently, this check passes if *any* enumerated IOAPIC matches the expected SB IOAPIC device ID. If a buggy BIOS incorrectly assigns the SB IOAPIC's device ID to a secondary IOAPIC in the IVRS, while scrambling the true SB IOAPIC's mapping, the check hits a false positive and succeeds.
This erroneously enables Interrupt Remapping. Consequently, the IOMMU blocks unmapped interrupts from the actual SB IOAPIC, dropping the system timer and leading to a silent kernel boot hang.
Tighten the validation to verify the device ID specifically against the SB IOAPIC by matching their APIC IDs first. This prevents the validation check from being bypassed via device ID aliasing.
--- drivers/iommu/amd/init.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-)
drivers/iommu/amd/init.c +28 -4
@@ -2969,11 +2969,25 @@ static void __init free_iommu_resources(void)/* SB IOAPIC for Hygon family 18h model 4h is on the device 0xb */ #define IOAPIC_SB_DEVID_FAM18H_M4H ((0x00 << 8) | PCI_DEVFN(0xb, 0)) +/* +* The Southbridge IOAPIC is assigned a GSI Base of 0 (handling interrupts +* 0 through 23). +*/ +static int __init get_sb_ioapic_id (void ) +{ +int idx =mp_find_ioapic (0 ); + +if (idx <0 ) +return -ENODEV ; + +return mpc_ioapic_id (idx); +} +static bool __init check_ioapic_information (void ) {const char *fw_bug =FW_BUG ;bool ret, has_sb_ioapic; -int idx; +int idx, sb_apicid; has_sb_ioapic = false; ret = true;
@@ -2986,6 +3000,16 @@ static bool __init check_ioapic_information(void)if (cmdline_maps) fw_bug ="" ; + sb_apicid =get_sb_ioapic_id (); +if (sb_apicid <0 ) { +/* +* Lack of SB IOAPIC registration is not a firmware bug, +* e.g. kernel booted with noapic or noacpi. +*/ + fw_bug ="" ; + goto out; + } +for (idx =0 ; idx < nr_ioapics; idx++) {int devid, id =mpc_ioapic_id (idx);
@@ -2994,16 +3018,16 @@ static bool __init check_ioapic_information(void)pr_err ("%s: IOAPIC[%d] not in IVRS table\n" , fw_bug, id); ret = false; - }else if (devid ==IOAPIC_SB_DEVID || + }else if (id == sb_apicid && (devid ==IOAPIC_SB_DEVID || (boot_cpu_data.x86_vendor ==X86_VENDOR_HYGON && boot_cpu_data.x86 ==0x18 && boot_cpu_data.x86_model >=0x4 && boot_cpu_data.x86_model <=0xf && - devid ==IOAPIC_SB_DEVID_FAM18H_M4H )) { + devid ==IOAPIC_SB_DEVID_FAM18H_M4H ))) { has_sb_ioapic = true; } } - +out:if (!has_sb_ioapic) {/* * We expect the SB IOAPIC to be listed in the IVRS
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 464/1376 leds: pca9532: Fix inverted GPIO output polarity
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cosmo Chou <[email protected]>
[ Upstream commit 65a38a28a0b04af19a5e1fbf3869051412eeac96 ]
The pca9532_gpio_set_value() function incorrectly mapped the requested value to PCA9532_ON and PCA9532_OFF, inverting the GPIO output polarity. A requested logical high (val=1) incorrectly enabled the LED output driver, which on this open-drain device pulls the pin low, while a requested logical low (val=0) released the pin.
Correct the mapping so that val=1 yields PCA9532_OFF (pin released / high-impedance) and val=0 yields PCA9532_ON (pin driven low).
pca9532_gpio_direction_input() is also updated to pass val=1 to pca9532_gpio_set_value() to align with the corrected polarity mapping, ensuring the pin remains not driven when configured as an input.
--- drivers/leds/leds-pca9532.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/leds/leds-pca9532.c +3 -3
@@ -324,9 +324,9 @@ static void pca9532_gpio_set_value(struct gpio_chip *gc, unsigned offset, int vastruct pca9532_led *led = &data->leds[offset];if (val) - led->state =PCA9532_ON ; -else led->state =PCA9532_OFF ; +else + led->state =PCA9532_ON ;pca9532_setled (led); }
@@ -344,7 +344,7 @@ static int pca9532_gpio_get_value(struct gpio_chip *gc, unsigned offset)static int pca9532_gpio_direction_input (struct gpio_chip *gc,unsigned offset) {/* To use as input ensure pin is not driven */ -pca9532_gpio_set_value (gc, offset,0 ); +pca9532_gpio_set_value (gc, offset,1 );return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 465/1376 printk/panic: Add option to allow non-panic CPUs to write to the ring buffer.
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Donghyeok Choe <[email protected]>
[ Upstream commit c1aa3daa517292303d98ff61f0440c354669f948 ]
Commit 779dbc2e78d7 ("printk: Avoid non-panic CPUs writing to ringbuffer") aimed to isolate panic-related messages. However, when panic() itself malfunctions, messages from non-panic CPUs become crucial for debugging.
While commit bcc954c6caba ("printk/panic: Allow cpu backtraces to be written into ringbuffer during panic") enables non-panic CPU backtraces, it may not provide sufficient diagnostic information.
Introduce the "debug_non_panic_cpus" command-line option, enabling non-panic CPU messages to be stored in the ring buffer during a panic. This also prevents discarding non-finalized messages from non-panic CPUs during console flushing, providing a more comprehensive view of system state during critical failures.
Stable-dep-of: 36630cafbeed ("printk: Fix possible console use-after-free")
--- .../admin-guide/kernel-parameters.txt | 8 ++++++++ kernel/printk/internal.h | 1 + kernel/printk/printk.c | 20 ++++++++++++++++++- kernel/printk/printk_ringbuffer.c | 13 +++++++----- 4 files changed, 36 insertions(+), 6 deletions(-)
Documentation/admin-guide/kernel-parameters.txt +8 -0
@@ -4860,6 +4860,14 @@ Format: <bool> default: 0 (auto_verbose is enabled) + printk.debug_non_panic_cpus= + Allows storing messages from non-panic CPUs into + the printk log buffer during panic(). They are + flushed to consoles by the panic-CPU on + a best-effort basis. + Format: <bool> (1/Y/y=enable, 0/N/n=disable) + Default: disabled + printk.devkmsg={on,off,ratelimit} Control writing to /dev/kmsg. on - unlimited logging to /dev/kmsg from userspace
kernel/printk/internal.h +1 -0
@@ -62,6 +62,7 @@ struct dev_printk_info;extern struct printk_ringbuffer *prb;extern bool printk_kthreads_running; +extern bool debug_non_panic_cpus; __printf(4, 0) int vprintk_store(int facility, int level,
kernel/printk/printk.c +19 -1
@@ -2350,6 +2350,22 @@ void printk_legacy_allow_panic_sync(void) } } +bool __read_mostly debug_non_panic_cpus; + +#ifdef CONFIG_PRINTK_CALLER +static int __init debug_non_panic_cpus_setup (char *str) +{ + debug_non_panic_cpus = true; +pr_info ("allow messages from non-panic CPUs in panic()\n" ); + +return 0 ; +} +early_param ("debug_non_panic_cpus" , debug_non_panic_cpus_setup); +module_param (debug_non_panic_cpus, bool,0644 ); +MODULE_PARM_DESC (debug_non_panic_cpus, +"allow messages from non-panic CPUs in panic()" ); +#endif + asmlinkage int vprintk_emit(int facility, int level,const struct dev_printk_info *dev_info,const char *fmt,va_list args)
@@ -2366,7 +2382,9 @@ asmlinkage int vprintk_emit(int facility, int level,* non-panic CPUs are generating any messages, they will be * silently dropped. */ -if (other_cpu_in_panic () && !panic_triggering_all_cpu_backtrace) +if (other_cpu_in_panic () && + !debug_non_panic_cpus && + !panic_triggering_all_cpu_backtrace)return 0 ;printk_get_console_flush_type (&ft);
kernel/printk/printk_ringbuffer.c +8 -5
@@ -2133,9 +2133,9 @@ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq,* there may be other finalized records beyond that * need to be printed for a panic situation. If this * is the panic CPU, skip this -* non-existent/non-finalized record unless it is -* at or beyond the head, in which case it is not -* possible to continue. +* non-existent/non-finalized record unless non-panic +* CPUs are still running and their debugging is +* explicitly enabled. * * Note that new messages printed on panic CPU are * finalized when we are here. The only exception
@@ -2143,10 +2143,13 @@ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq,* But it would have the sequence number returned * by "prb_next_reserve_seq() - 1". */ -if (this_cpu_in_panic () && ((*seq +1 ) <prb_next_reserve_seq (rb))) +if (this_cpu_in_panic () && + (!debug_non_panic_cpus || legacy_allow_panic_sync) && + ((*seq +1 ) <prb_next_reserve_seq (rb))) { (*seq)++; -else + }else {return false; + } } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 466/1376 panic: introduce helper functions for panic state
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jinchao Wang <[email protected]>
[ Upstream commit d0d9c7235548f1d772f1e48c9d5742c65d81c705 ]
Patch series "panic: introduce panic status function family", v2.
This series introduces a family of helper functions to manage panic state and updates existing code to use them.
Before this series, panic state helpers were scattered and inconsistent. For example, panic_in_progress() was defined in printk/printk.c, not in panic.c or panic.h. As a result, developers had to look in unexpected places to understand or re-use panic state logic. Other checks were open- coded, duplicating logic across panic, crash, and watchdog paths.
The new helpers centralize the functionality in panic.c/panic.h:
- panic_try_start()
- panic_reset()
- panic_in_progress()
- panic_on_this_cpu()
- panic_on_other_cpu()
Patches 1–8 add the helpers and convert panic/crash and printk/nbcon code to use them.
Patch 9 fixes a bug in the watchdog subsystem by skipping checks when a panic is in progress, avoiding interference with the panic CPU.
Together, this makes panic state handling simpler, more discoverable, and more robust.
This patch (of 9):
This patch introduces four new helper functions to abstract the management of the panic_cpu variable. These functions will be used in subsequent patches to refactor existing code.
The direct use of panic_cpu can be error-prone and ambiguous, as it requires manual checks to determine which CPU is handling the panic. The new helpers clarify intent:
panic_try_start():
Atomically sets the current CPU as the panicking CPU.
panic_reset():
Reset panic_cpu to PANIC_CPU_INVALID.
panic_in_progress():
Checks if a panic has been triggered.
panic_on_this_cpu():
Returns true if the current CPU is the panic originator.
panic_on_other_cpu():
Returns true if a panic is on another CPU.
This change lays the groundwork for improved code readability and robustness in the panic handling subsystem.
Stable-dep-of: 36630cafbeed ("printk: Fix possible console use-after-free")
--- include/linux/panic.h | 6 +++++ kernel/panic.c | 53 ++++++++++++++++++++++++++++++++++++++++++ kernel/printk/printk.c | 5 ---- 3 files changed, 59 insertions(+), 5 deletions(-)
include/linux/panic.h +6 -0
@@ -44,6 +44,12 @@ void abort(void);extern atomic_t panic_cpu;#define PANIC_CPU_INVALID -1 +bool panic_try_start (void ); +void panic_reset (void ); +bool panic_in_progress (void ); +bool panic_on_this_cpu (void ); +bool panic_on_other_cpu (void ); +/* * Only to be used by arch init code. If the user over-wrote the default * CONFIG_PANIC_TIMEOUT, honor it.
kernel/panic.c +53 -0
59 lines not on this page · raw message
kernel/printk/printk.c +0 -5
@@ -345,11 +345,6 @@ static void __up_console_sem(unsigned long ip) }#define up_console_sem () __up_console_sem(_RET_IP_) -static bool panic_in_progress (void ) -{ -return unlikely (atomic_read (&panic_cpu) !=PANIC_CPU_INVALID ); -} -/* Return true if a panic is in progress on the current CPU. */ bool this_cpu_in_panic (void ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 467/1376 panic/printk: replace this_cpu_in_panic() with panic_on_this_cpu()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jinchao Wang <[email protected]>
[ Upstream commit c6be36e2997662f423edfa3979a63935873ff648 ]
The helper this_cpu_in_panic() duplicated logic already provided by panic_on_this_cpu().
Remove this_cpu_in_panic() and switch all users to panic_on_this_cpu().
This simplifies the code and avoids having two helpers for the same check.
Stable-dep-of: 36630cafbeed ("printk: Fix possible console use-after-free")
--- include/linux/printk.h | 2 -- kernel/panic.c | 2 +- kernel/printk/nbcon.c | 2 +- kernel/printk/printk.c | 15 ++------------- kernel/printk/printk_ringbuffer.c | 2 +- lib/dump_stack.c | 2 +- 6 files changed, 6 insertions(+), 19 deletions(-)
include/linux/printk.h +0 -2
@@ -312,8 +312,6 @@ static inline bool pr_flush(int timeout_ms, bool reset_on_progress)#endif -bool this_cpu_in_panic (void ); -#ifdef CONFIG_SMP extern int __printk_cpu_sync_try_get (void );extern void __printk_cpu_sync_wait (void );
kernel/panic.c +1 -1
@@ -236,7 +236,7 @@ EXPORT_SYMBOL(panic_on_this_cpu);*/ bool panic_on_other_cpu (void ) { -return (panic_in_progress () && !this_cpu_in_panic ()); +return (panic_in_progress () && !panic_on_this_cpu ()); }EXPORT_SYMBOL (panic_on_other_cpu);
kernel/printk/nbcon.c +1 -1
@@ -1394,7 +1394,7 @@ enum nbcon_prio nbcon_get_default_prio(void) {unsigned int *cpu_emergency_nesting; -if (this_cpu_in_panic ()) +if (panic_on_this_cpu ())return NBCON_PRIO_PANIC ; cpu_emergency_nesting =nbcon_get_cpu_emergency_nesting ();
kernel/printk/printk.c +2 -13
@@ -17,6 +17,7 @@* 01Mar01 Andrew Morton */ +#include "linux/panic.h" #define pr_fmt (fmt) KBUILD_MODNAME ": " fmt#include <linux/kernel.h>
@@ -345,18 +346,6 @@ static void __up_console_sem(unsigned long ip) }#define up_console_sem () __up_console_sem(_RET_IP_) -/* Return true if a panic is in progress on the current CPU. */ -bool this_cpu_in_panic (void ) -{ -/* -* We can use raw_smp_processor_id() here because it is impossible for -* the task to be migrated to the panic_cpu, or away from it. If -* panic_cpu has already been set, and we're not currently executing on -* that CPU, then we never will be. -*/ -return unlikely (atomic_read (&panic_cpu) ==raw_smp_processor_id ()); -} -/* * Return true if a panic is in progress on a remote CPU. *
@@ -365,7 +354,7 @@ bool this_cpu_in_panic(void)*/ bool other_cpu_in_panic (void ) { -return (panic_in_progress () && !this_cpu_in_panic ()); +return (panic_in_progress () && !panic_on_this_cpu ()); }/*
kernel/printk/printk_ringbuffer.c +1 -1
@@ -2143,7 +2143,7 @@ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq,* But it would have the sequence number returned * by "prb_next_reserve_seq() - 1". */ -if (this_cpu_in_panic () && +if (panic_on_this_cpu () && (!debug_non_panic_cpus || legacy_allow_panic_sync) && ((*seq +1 ) <prb_next_reserve_seq (rb))) { (*seq)++;
lib/dump_stack.c +1 -1
@@ -102,7 +102,7 @@ static void __dump_stack(const char *log_lvl)*/ asmlinkage __visible void dump_stack_lvl(const char *log_lvl) { -bool in_panic =this_cpu_in_panic (); +bool in_panic =panic_on_this_cpu ();unsigned long flags;/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 468/1376 panic/printk: replace other_cpu_in_panic() with panic_on_other_cpu()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jinchao Wang <[email protected]>
[ Upstream commit d4a36db5639db032a434aef968f9188a600139ec ]
The helper other_cpu_in_panic() duplicated logic already provided by panic_on_other_cpu().
Remove other_cpu_in_panic() and update all users to call panic_on_other_cpu() instead.
This removes redundant code and makes panic handling consistent.
Stable-dep-of: 36630cafbeed ("printk: Fix possible console use-after-free")
--- kernel/printk/internal.h | 1 - kernel/printk/nbcon.c | 8 ++++---- kernel/printk/printk.c | 19 ++++--------------- 3 files changed, 8 insertions(+), 20 deletions(-)
kernel/printk/internal.h +0 -1
@@ -328,7 +328,6 @@ struct printk_message {unsigned long dropped; }; -bool other_cpu_in_panic (void );bool printk_get_next_message (struct printk_message *pmsg,u64 seq,bool is_extended,bool may_supress);
kernel/printk/nbcon.c +4 -4
@@ -254,7 +254,7 @@ static int nbcon_context_try_acquire_direct(struct nbcon_context *ctxt,* opportunity to perform any necessary cleanup if they were * interrupted by the panic CPU while printing. */ -if (other_cpu_in_panic () && +if (panic_on_other_cpu () && (!is_reacquire || cur->unsafe_takeover)) {return -EPERM ; }
@@ -309,7 +309,7 @@ static bool nbcon_waiter_matches(struct nbcon_state *cur, int expected_prio)* Event #2 implies the new context is PANIC. * Event #3 occurs when panic() has flushed the console. * Event #4 occurs when a non-panic CPU reacquires. -* Event #5 is not possible due to the other_cpu_in_panic() check +* Event #5 is not possible due to the panic_on_other_cpu() check * in nbcon_context_try_acquire_handover(). */
@@ -348,7 +348,7 @@ static int nbcon_context_try_acquire_requested(struct nbcon_context *ctxt,struct nbcon_state new;/* Note that the caller must still remove the request! */ -if (other_cpu_in_panic ()) +if (panic_on_other_cpu ())return -EPERM ;/*
@@ -446,7 +446,7 @@ static int nbcon_context_try_acquire_handover(struct nbcon_context *ctxt,* nbcon_waiter_matches(). In particular, the assumption that * lower priorities are ignored during panic. */ -if (other_cpu_in_panic ()) +if (panic_on_other_cpu ())return -EPERM ;/* Handover is not possible on the same CPU. */
kernel/printk/printk.c +4 -15
@@ -346,17 +346,6 @@ static void __up_console_sem(unsigned long ip) }#define up_console_sem () __up_console_sem(_RET_IP_) -/* -* Return true if a panic is in progress on a remote CPU. -* -* On true, the local CPU should immediately release any printing resources -* that may be needed by the panic CPU. -*/ -bool other_cpu_in_panic (void ) -{ -return (panic_in_progress () && !panic_on_this_cpu ()); -} -/* * This is used for debugging the mess that is the VT code by * keeping track if we have the console semaphore held. It's
@@ -2366,7 +2355,7 @@ asmlinkage int vprintk_emit(int facility, int level,* non-panic CPUs are generating any messages, they will be * silently dropped. */ -if (other_cpu_in_panic () && +if (panic_on_other_cpu () && !debug_non_panic_cpus && !panic_triggering_all_cpu_backtrace)return 0 ;
@@ -2802,7 +2791,7 @@ void console_lock(void)might_sleep ();/* On panic, the console_lock must be left to the panic cpu. */ -while (other_cpu_in_panic ()) +while (panic_on_other_cpu ())msleep (1000 );down_console_sem ();
@@ -2822,7 +2811,7 @@ EXPORT_SYMBOL(console_lock);int console_trylock (void ) {/* On panic, the console_lock must be left to the panic cpu. */ -if (other_cpu_in_panic ()) +if (panic_on_other_cpu ())return 0 ;if (down_trylock_console_sem ())return 0 ;
@@ -3197,7 +3186,7 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove any_progress = true;/* Allow panic_cpu to take over the consoles safely. */ -if (other_cpu_in_panic ()) +if (panic_on_other_cpu ()) goto abandon;if (do_cond_resched)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 469/1376 printk: Introduce console_flush_one_record
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrew Murray <[email protected]>
[ Upstream commit 741ea7aa95dd9ac77f861e7d0961d8d231ac8448 ]
console_flush_all prints all remaining records to all usable consoles whilst its caller holds console_lock. This can result in large waiting times for those waiting for console_lock especially where there is a large volume of records or where the console is slow (e.g. serial).
Let's extract the parts of this function which print a single record into a new function named console_flush_one_record. This can later be used for functions that will release and reacquire console_lock between records.
This commit should not change existing functionality.
Stable-dep-of: 36630cafbeed ("printk: Fix possible console use-after-free")
--- kernel/printk/printk.c | 158 ++++++++++++++++++++++++++--------------- 1 file changed, 99 insertions(+), 59 deletions(-)
kernel/printk/printk.c +99 -59
@@ -3104,6 +3104,99 @@ static inline void printk_kthreads_check_locked(void) { }#endif /* CONFIG_PRINTK */ + +/* +* Print out one record for each console. +* +* @do_cond_resched is set by the caller. It can be true only in schedulable +* context. +* +* @next_seq is set to the sequence number after the last available record. +* The value is valid only when there is at least one usable console and all +* usable consoles were flushed. +* +* @handover will be set to true if a printk waiter has taken over the +* console_lock, in which case the caller is no longer holding the +* console_lock. Otherwise it is set to false. +* +* @any_usable will be set to true if there are any usable consoles. +* +* Returns true when there was at least one usable console and a record was +* flushed. A returned false indicates there were no records to flush for any +* of the consoles. It may also indicate that there were no usable consoles, +* the context has been lost or there is a panic suitation. Regardless the +* reason, the caller should assume it is not useful to immediately try again. +* +* Requires the console_lock. +*/ +static bool console_flush_one_record (bool do_cond_resched,u64 *next_seq,bool *handover, +bool *any_usable) +{ +struct console_flush_type ft; +bool any_progress = false; +struct console *con; +int cookie; + +printk_get_console_flush_type (&ft); + + cookie =console_srcu_read_lock (); +for_each_console_srcu (con) { +short flags =console_srcu_read_flags (con); +u64 printk_seq; +bool progress; + +/* +* console_flush_one_record() is only responsible for +* nbcon consoles when the nbcon consoles cannot print via +* their atomic or threaded flushing. +*/ +if ((flags &CON_NBCON ) && (ft.nbcon_atomic || ft.nbcon_offload)) +continue ; + +if (!console_is_usable (con, flags, !do_cond_resched)) +continue ; + *any_usable = true; + +if (flags &CON_NBCON ) { + progress =nbcon_legacy_emit_next_record (con, handover, cookie, + !do_cond_resched); + printk_seq =nbcon_seq_read (con); + }else { + progress =console_emit_next_record (con, handover, cookie); + printk_seq = con->seq; + } + +/* +* If a handover has occurred, the SRCU read lock +* is already released. +*/ +if (*handover) +return false; + +/* Track the next of the highest seq flushed. */ +if (printk_seq > *next_seq) + *next_seq = printk_seq; + +if (!progress) +continue ; + any_progress = true; + +/* Allow panic_cpu to take over the consoles safely. */ +if (panic_on_other_cpu ()) + goto abandon; + +if (do_cond_resched) +cond_resched (); + } +console_srcu_read_unlock (cookie); + +return any_progress; + +abandon: +console_srcu_read_unlock (cookie); +return false; +} +/* * Print out all remaining records to all consoles. *
@@ -3129,77 +3222,24 @@ static inline void printk_kthreads_check_locked(void) { }*/ static bool console_flush_all (bool do_cond_resched,u64 *next_seq,bool *handover) { -struct console_flush_type ft;bool any_usable = false; -struct console *con;bool any_progress; -int cookie; *next_seq =0 ; *handover = false;do { - any_progress = false; + any_progress =console_flush_one_record (do_cond_resched, next_seq, handover, + &any_usable); -printk_get_console_flush_type (&ft); - - cookie =console_srcu_read_lock (); -for_each_console_srcu (con) { -short flags =console_srcu_read_flags (con); -u64 printk_seq; -bool progress; +if (*handover) +return false; -/* -* console_flush_all() is only responsible for nbcon -* consoles when the nbcon consoles cannot print via -* their atomic or threaded flushing. -*/ -if ((flags &CON_NBCON ) && (ft.nbcon_atomic || ft.nbcon_offload)) -continue ; - -if (!console_is_usable (con, flags, !do_cond_resched)) -continue ; - any_usable = true; - -if (flags &CON_NBCON ) { - progress =nbcon_legacy_emit_next_record (con, handover, cookie, - !do_cond_resched); - printk_seq =nbcon_seq_read (con); - }else { - progress =console_emit_next_record (con, handover, cookie); - printk_seq = con->seq; - } - -/* -* If a handover has occurred, the SRCU read lock -* is already released. -*/ -if (*handover) -return false; - -/* Track the next of the highest seq flushed. */ -if (printk_seq > *next_seq) - *next_seq = printk_seq; - -if (!progress) -continue ; - any_progress = true; - -/* Allow panic_cpu to take over the consoles safely. */ -if (panic_on_other_cpu ()) - goto abandon; - -if (do_cond_resched) -cond_resched (); - } -console_srcu_read_unlock (cookie); +if (panic_on_other_cpu ()) +return false; }while (any_progress);return any_usable; - -abandon: -console_srcu_read_unlock (cookie); -return false; }static void __console_flush_and_unlock (void )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 470/1376 printk: Fix possible console use-after-free
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Ogness <[email protected]>
[ Upstream commit 36630cafbeede0b64c370edb2f7b4094327ee1e0 ]
When emitting a record via legacy printing, it is possible that a handover to another legacy printing context occurs. When a context has performed a handover, the console SRCU read lock is released and the pointer to the console struct might now be invalid. Therefore, after calling nbcon_legacy_emit_next_record() or console_emit_next_record(), it is necessary to check if a handover occurred _before_ further @con usage.
Sashiko pointed out that console_flush_one_record() was not doing this.
In console_flush_one_record(), after emitting a record, move the further usage of @con after the handover check.
--- kernel/printk/printk.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
kernel/printk/printk.c +9 -2
@@ -3160,10 +3160,8 @@ static bool console_flush_one_record(bool do_cond_resched, u64 *next_seq, bool *if (flags &CON_NBCON ) { progress =nbcon_legacy_emit_next_record (con, handover, cookie, !do_cond_resched); - printk_seq =nbcon_seq_read (con); }else { progress =console_emit_next_record (con, handover, cookie); - printk_seq = con->seq; }/*
@@ -3173,6 +3171,15 @@ static bool console_flush_one_record(bool do_cond_resched, u64 *next_seq, bool *if (*handover)return false; +/* +* @con can be used here now that it is certain that this +* context is still holding the SRCU read lock. +*/ +if (flags &CON_NBCON ) + printk_seq =nbcon_seq_read (con); +else + printk_seq = con->seq; +/* Track the next of the highest seq flushed. */ if (printk_seq > *next_seq) *next_seq = printk_seq;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 471/1376 ACPI: RISC-V: Fix riscv_acpi_irq_get_dep() loop termination
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Pieralisi <[email protected]>
[ Upstream commit 64ae310bffa477cd11029c818bec489f4b8a845e ]
In riscv_acpi_add_irq_dep() the main loop condition would currently stop the loop if an interrupt descriptor contains an interrupt for which the respective GSI handle is NULL, which is not correct because subsequent interrupts in the interrupt descriptor might still have a GSI dependency that must not be skipped.
Rework riscv_acpi_add_irq_dep() and the riscv_acpi_irq_get_dep() call chain to fix it - by not forcing the loop to stop in order to guarantee dependency detection for all the interrupt entries in the CRS descriptor.
--- drivers/acpi/riscv/irq.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/acpi/riscv/irq.c +6 -4
@@ -230,6 +230,7 @@ static acpi_status riscv_acpi_irq_get_parent(struct acpi_resource *ares, void *creturn AE_OK ; ctx->handle =riscv_acpi_get_gsi_handle (eirq->interrupts[ctx->index]); + ctx->rc =0 ;return AE_CTRL_TERMINATE ; }
@@ -245,10 +246,8 @@ static int riscv_acpi_irq_get_dep(acpi_handle handle, unsigned int index, acpi_hacpi_walk_resources (handle,METHOD_NAME__CRS , riscv_acpi_irq_get_parent, &ctx); *gsi_handle = ctx.handle; -if (*gsi_handle) -return 1 ; -return 0 ; +return ctx.rc; }static u32 riscv_acpi_add_prt_dep (acpi_handle handle)
@@ -310,8 +309,11 @@ static u32 riscv_acpi_add_irq_dep(acpi_handle handle)int i;for (i =0 ; -riscv_acpi_irq_get_dep (handle, i, &gsi_handle); + !riscv_acpi_irq_get_dep (handle, i, &gsi_handle); i++) { +if (!gsi_handle) +continue ; + dep_devices.count =1 ; dep_devices.handles =kcalloc (1 ,sizeof (*dep_devices.handles),GFP_KERNEL );if (!dep_devices.handles) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 472/1376 ACPI: RISC-V: Check acpi_get_handle() status in riscv_acpi_add_prt_dep()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Pieralisi <[email protected]>
[ Upstream commit 20435bda13f1219891ed0ce41207e320a916ff9c ]
In riscv_acpi_add_prt_dep(), the acpi_get_handle() call can fail which would leave link_handle uninitialized.
Fix it by checking the acpi_get_handle() return status and skip the entry if it fails.
--- drivers/acpi/riscv/irq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/acpi/riscv/irq.c +3 -1
@@ -270,7 +270,9 @@ static u32 riscv_acpi_add_prt_dep(acpi_handle handle) entry = buffer.pointer;while (entry && (entry->length >0 )) {if (entry->source[0 ]) { -acpi_get_handle (handle, entry->source, &link_handle); + status =acpi_get_handle (handle, entry->source, &link_handle); +if (ACPI_FAILURE (status)) +continue ; dep_devices.count =1 ; dep_devices.handles =kcalloc (1 ,sizeof (*dep_devices.handles),GFP_KERNEL );if (!dep_devices.handles) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 473/1376 ACPI: RISC-V: Fix riscv_acpi_add_prt_dep() loop handling
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Pieralisi <[email protected]>
[ Upstream commit 3a56321d0aceee2a0bd80d23366401c131ff8350 ]
The loop in riscv_acpi_add_prt_dep() includes error conditions that are handled in a dubious - if not outright wrong - way, by continuining the loop (which skips and misses the entry pointer update to point to the next entry).
Rewrite the loop as a for loop (that handles the continuation correctly) and wrap the condition and update statements using helper functions to make it cleaner.
--- drivers/acpi/riscv/irq.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)
drivers/acpi/riscv/irq.c +15 -4
@@ -250,6 +250,20 @@ static int riscv_acpi_irq_get_dep(acpi_handle handle, unsigned int index, acpi_hreturn ctx.rc; } +static bool acpi_prt_entry_valid (void *prt_entry) +{ +struct acpi_pci_routing_table *entry = prt_entry; + +return entry && entry->length >0 ; +} + +static void *acpi_prt_next_entry (void *prt_entry) +{ +struct acpi_pci_routing_table *entry = prt_entry; + +return prt_entry + entry->length; +} +static u32 riscv_acpi_add_prt_dep (acpi_handle handle) {struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER ,NULL };
@@ -268,7 +282,7 @@ static u32 riscv_acpi_add_prt_dep(acpi_handle handle) } entry = buffer.pointer; -while (entry && (entry->length >0 )) { +for (;acpi_prt_entry_valid (entry); entry =acpi_prt_next_entry (entry)) {if (entry->source[0 ]) { status =acpi_get_handle (handle, entry->source, &link_handle);if (ACPI_FAILURE (status))
@@ -294,9 +308,6 @@ static u32 riscv_acpi_add_prt_dep(acpi_handle handle) dep_devices.handles[0 ] = gsi_handle; count +=acpi_scan_add_dep (handle, &dep_devices); } - - entry = (struct acpi_pci_routing_table *) - ((unsigned long )entry + entry->length); }kfree (buffer.pointer);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 474/1376 platform/x86: dell-privacy: Fix race condition
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Armin Wolf <[email protected]>
[ Upstream commit ca9338dbc64759b30741b12017c050b33c94dfa2 ]
Accessing priv->features_present needs to happen with the list mutex being held, otherwise priv can be freed at any moment.
--- drivers/platform/x86/dell/dell-wmi-privacy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/platform/x86/dell/dell-wmi-privacy.c +2 -2
@@ -69,11 +69,11 @@ bool dell_privacy_has_mic_mute(void) {struct privacy_wmi_data *priv; -mutex_lock (&list_mutex); +guard (mutex)(&list_mutex); + priv =list_first_entry_or_null (&wmi_list, struct privacy_wmi_data, list); -mutex_unlock (&list_mutex);return priv && (priv->features_present &BIT (DELL_PRIVACY_TYPE_AUDIO )); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 475/1376 platform/x86: dell-wmi-base: Fix resource leak on module load failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Armin Wolf <[email protected]>
[ Upstream commit 072841e02cf9c00a7e8a9c567a14239e02ca47ad ]
We need to properly clean up the SMBIOS request and the privacy driver when the module load fails.
--- drivers/platform/x86/dell/dell-wmi-base.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
drivers/platform/x86/dell/dell-wmi-base.c +15 -2
@@ -839,9 +839,22 @@ static int __init dell_wmi_init(void) err =dell_privacy_register_driver ();if (err) -return err; + goto out_smbios; -return wmi_driver_register (&dell_wmi_driver); + err =wmi_driver_register (&dell_wmi_driver); +if (err) + goto out_privacy; + +return 0 ; + +out_privacy: +dell_privacy_unregister_driver (); + +out_smbios: +if (wmi_requires_smbios_request) +dell_wmi_events_set_enabled (false); + +return err; }late_initcall (dell_wmi_init);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 476/1376 platform/x86: lg-laptop: Drop debug-only ACPI notify handler
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit c12fe0b2c12195e0d1c56e0f670a6bd792b0567e ]
To facilitate subsequent conversion of the driver to using struct platform_driver instead of struct acpi_driver, drop the debug-only notify handler method from the driver.
No intentional functional impact beyond debug.
Stable-dep-of: 3e91964aa74a ("platform/x86: lg-laptop: Fix LED resource handling")
--- drivers/platform/x86/lg-laptop.c | 6 ------ 1 file changed, 6 deletions(-)
drivers/platform/x86/lg-laptop.c +0 -6
@@ -269,11 +269,6 @@ static void wmi_input_setup(void) } } -static void acpi_notify (struct acpi_device *device,u32 event) -{ -acpi_handle_debug (device->handle,"notify: %d\n" , event); -} -static ssize_t fan_mode_store (struct device *dev,struct device_attribute *attr,const char *buffer,size_t count)
@@ -886,7 +881,6 @@ static struct acpi_driver acpi_driver = { .ops = { .add = acpi_add, .remove = acpi_remove, - .notify = acpi_notify, }, };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 477/1376 platform/x86: lg-laptop: Convert ACPI driver to a platform one
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit 2d9cb20610f75ca48c1cac064aede90196787507 ]
In all cases in which a struct acpi_driver is used for binding a driver to an ACPI device object, a corresponding platform device is created by the ACPI core and that device is regarded as a proper representation of underlying hardware. Accordingly, a struct platform_driver should be used by driver code to bind to that device. There are multiple reasons why drivers should not bind directly to ACPI device objects [1].
Overall, it is better to bind drivers to platform devices than to their ACPI companions, so convert the LG Gram ACPI features and hotkeys driver from an ACPI driver to a platform one.
While this is not expected to alter functionality, it changes sysfs layout and so it will be visible to user space.
Stable-dep-of: 3e91964aa74a ("platform/x86: lg-laptop: Fix LED resource handling")
--- drivers/platform/x86/lg-laptop.c | 45 +++++++++----------------------- 1 file changed, 13 insertions(+), 32 deletions(-)
drivers/platform/x86/lg-laptop.c +13 -32
@@ -748,8 +748,9 @@ static void lg_laptop_remove_address_space_handler(void *data) &lg_laptop_address_space_handler); } -static int acpi_add (struct acpi_device *device) +static int acpi_probe (struct platform_device *pdev) { +struct acpi_device *device =ACPI_COMPANION (&pdev->dev);struct platform_device_info pdev_info = { .fwnode =acpi_fwnode_handle (device), .name =PLATFORM_NAME ,
@@ -765,11 +766,11 @@ static int acpi_add(struct acpi_device *device) status =acpi_install_address_space_handler (device->handle,LG_ADDRESS_SPACE_ID , &lg_laptop_address_space_handler, -NULL , &device->dev); +NULL , &pdev->dev);if (ACPI_FAILURE (status))return -ENODEV ; - ret =devm_add_action_or_reset (&device->dev, lg_laptop_remove_address_space_handler, + ret =devm_add_action_or_reset (&pdev->dev, lg_laptop_remove_address_space_handler, device);if (ret <0 )return ret;
@@ -854,7 +855,7 @@ static int acpi_add(struct acpi_device *device)return ret; } -static void acpi_remove (struct acpi_device *device) +static void acpi_remove (struct platform_device *pdev) {sysfs_remove_group (&pf_device->dev.kobj, &dev_attribute_group);
@@ -874,33 +875,13 @@ static const struct acpi_device_id device_ids[] = { };MODULE_DEVICE_TABLE (acpi, device_ids); -static struct acpi_driver acpi_driver = { - .name ="LG Gram Laptop Support" , - .class ="lg-laptop" , - .ids = device_ids, - .ops = { - .add = acpi_add, - .remove = acpi_remove, - }, +static struct platform_driver acpi_driver = { + .probe = acpi_probe, + .remove = acpi_remove, + .driver = { + .name ="LG Gram Laptop Support" , + .acpi_match_table = device_ids, + }, }; -static int __init acpi_init (void ) -{ -int result; - - result =acpi_bus_register_driver (&acpi_driver); -if (result <0 ) { -pr_debug ("Error registering driver\n" ); -return -ENODEV ; - } - -return 0 ; -} - -static void __exit acpi_exit(void) -{ -acpi_bus_unregister_driver (&acpi_driver); -} - -module_init (acpi_init); -module_exit (acpi_exit); +module_platform_driver (acpi_driver);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 478/1376 platform/x86: lg-laptop: Fix LED resource handling
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Armin Wolf <[email protected]>
[ Upstream commit 3e91964aa74ab261aa15d9d96318eded2fd9d22a ]
The event notification callback might access kbd_backlight even when it was not successfully registered with the LED subsystem. The same happens inside acpi_remove(), where the LED devices are unregistered unconditionally.
Fix this by tracking the availability of the kbd_backlight LED device and use devm_led_classdev_register() to let devres take care of unregistering the LED devices during removal. For this the parent device of the LED devices is changed to the native platform device.
--- drivers/platform/x86/lg-laptop.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)
drivers/platform/x86/lg-laptop.c +14 -7
@@ -98,6 +98,7 @@ static u32 inited;#define INIT_SPARSE_KEYMAP 0x80static int battery_limit_use_wmbb; +static bool kbd_backlight_available;static struct led_classdev kbd_backlight;static enum led_brightness get_kbd_backlight_level (struct device *dev);
@@ -212,6 +213,7 @@ static union acpi_object *lg_wmbb(struct device *dev, u32 method_id, u32 arg1, ustatic void wmi_notify (union acpi_object *obj,void *context) {long data = (long )context; +unsigned int brightness;pr_debug ("event guid %li\n" , data);if (!obj)
@@ -222,8 +224,11 @@ static void wmi_notify(union acpi_object *obj, void *context)struct key_entry *key;if (eventcode ==0x10000000 ) { -led_classdev_notify_brightness_hw_changed ( - &kbd_backlight,get_kbd_backlight_level (kbd_backlight.dev->parent)); +if (kbd_backlight_available) { + brightness =get_kbd_backlight_level (kbd_backlight.dev->parent); +led_classdev_notify_brightness_hw_changed (&kbd_backlight, + brightness); + } }else { key =sparse_keymap_entry_from_scancode ( wmi_input_dev, eventcode);
@@ -840,8 +845,13 @@ static int acpi_probe(struct platform_device *pdev) goto out_platform_device;/* LEDs are optional */ -led_classdev_register (&pf_device->dev, &kbd_backlight); -led_classdev_register (&pf_device->dev, &tpad_led); + ret =devm_led_classdev_register (&pdev->dev, &kbd_backlight); +if (ret <0 ) + kbd_backlight_available = false; +else + kbd_backlight_available = true; + +devm_led_classdev_register (&pdev->dev, &tpad_led);wmi_input_setup ();battery_hook_register (&battery_hook);
@@ -859,9 +869,6 @@ static void acpi_remove(struct platform_device *pdev) {sysfs_remove_group (&pf_device->dev.kobj, &dev_attribute_group); -led_classdev_unregister (&tpad_led); -led_classdev_unregister (&kbd_backlight); -battery_hook_unregister (&battery_hook);wmi_input_destroy ();platform_device_unregister (pf_device);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 479/1376 remoteproc: qcom_q6v5_adsp: Fix reference leak for device node
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Gu <[email protected]>
[ Upstream commit 8c952807c2cebd5e9e9b37146c9383229794c129 ]
When calling of_parse_phandle_with_args(), the caller is responsible to call of_node_put() to release the reference of device node. In adsp_map_carveout, it does not release the reference.
--- drivers/remoteproc/qcom_q6v5_adsp.c | 1 + 1 file changed, 1 insertion(+)
drivers/remoteproc/qcom_q6v5_adsp.c +1 -0
@@ -355,6 +355,7 @@ static int adsp_map_carveout(struct rproc *rproc)return ret; sid = args.args[0 ] &SID_MASK_DEFAULT ; +of_node_put (args.np);/* Add SID configuration for ADSP Firmware to SMMU */ iova = adsp->mem_phys | (sid <<32 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 480/1376 hwspinlock: propagate errno when registering single lock
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wolfram Sang <[email protected]>
[ Upstream commit e088ffa9a00eaaaf90da74763e774ca160969c26 ]
hwspin_lock_register_single() always returns 0 despite checking the result from radix_tree_insert(). Propagate the errno to make sanity checks in callers of this function actually meaningful.
--- drivers/hwspinlock/hwspinlock_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hwspinlock/hwspinlock_core.c +1 -1
@@ -472,7 +472,7 @@ static int hwspin_lock_register_single(struct hwspinlock *hwlock, int id) out:mutex_unlock (&hwspinlock_tree_lock); -return 0 ; +return ret; }static struct hwspinlock *hwspin_lock_unregister_single (unsigned int id)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 481/1376 selftests/sched_ext: Fix bpf_link leak on early return in prog_run
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liang Luo <[email protected]>
[ Upstream commit e655c1f1bd14804f398df7da029c4a7e3f9ccd7f ]
In prog_run's run(), the bpf_link is attached early but only destroyed on the success path. The three SCX_EQ assertions between attach and destroy expand to a direct 'return SCX_TEST_FAIL', so if any of them triggers, bpf_link__destroy() is never reached and the BPF scheduler stays loaded. All subsequent tests then fail to attach because SCX is not in the DISABLED state.
Convert those assertions to explicit checks that jump to a unified 'out' label which always runs the cleanup, matching the pattern used in cyclic_kick_wait.c.
--- tools/testing/selftests/sched_ext/prog_run.c | 34 +++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-)
tools/testing/selftests/sched_ext/prog_run.c +26 -8
@@ -28,7 +28,8 @@ static enum scx_test_status setup(void **ctx)static enum scx_test_status run (void *ctx) {struct prog_run *skel = ctx; -struct bpf_link *link; +struct bpf_link *link =NULL ; +enum scx_test_status status =SCX_TEST_PASS ;int prog_fd, err =0 ; prog_fd =bpf_program__fd (skel->progs.prog_run_syscall);
@@ -42,23 +43,40 @@ static enum scx_test_status run(void *ctx) link =bpf_map__attach_struct_ops (skel->maps.prog_run_ops);if (!link) {SCX_ERR ("Failed to attach scheduler" ); -close (prog_fd); -return SCX_TEST_FAIL ; + status =SCX_TEST_FAIL ; + goto out; } err =bpf_prog_test_run_opts (prog_fd, &topts); -SCX_EQ (err,0 ); +if (err) { +SCX_ERR ("BPF_PROG_RUN failed (%d)" , err); + status =SCX_TEST_FAIL ; + goto out; + }/* Assumes uei.kind is written last */ while (skel->data->uei.kind ==EXIT_KIND (SCX_EXIT_NONE ))sched_yield (); -SCX_EQ (skel->data->uei.kind,EXIT_KIND (SCX_EXIT_UNREG_BPF )); -SCX_EQ (skel->data->uei.exit_code,0xdeadbeef ); +if (skel->data->uei.kind !=EXIT_KIND (SCX_EXIT_UNREG_BPF )) { +SCX_ERR ("Unexpected exit kind: %llu" , + (unsigned long long )skel->data->uei.kind); + status =SCX_TEST_FAIL ; + goto out; + } +if (skel->data->uei.exit_code !=0xdeadbeef ) { +SCX_ERR ("Unexpected exit code: %lld" , + (long long )skel->data->uei.exit_code); + status =SCX_TEST_FAIL ; + goto out; + } + +out:close (prog_fd); -bpf_link__destroy (link); +if (link) +bpf_link__destroy (link); -return SCX_TEST_PASS ; +return status; }static void cleanup (void *ctx)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 482/1376 serial: ma35d1: Fix OF node reference leaks in console init
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 8dfea56f350b3dc826f35711802ad6ae8fae0748 ]
ma35d1serial_console_init_port() stores matching UART device nodes in ma35d1serial_uart_nodes[] with an extra of_node_get() so that console setup can later read the "reg" property. However, the stored references are never released after console setup has finished using them.
Drop the stored node reference after ma35d1serial_console_setup() reads the "reg" property, and clear the array slot to avoid leaving a stale pointer behind. Also release the iterator reference before breaking out of for_each_matching_node(), since the normal iterator advance will not run in that path.
--- drivers/tty/serial/ma35d1_serial.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/tty/serial/ma35d1_serial.c +10 -2
@@ -608,8 +608,14 @@ static int __init ma35d1serial_console_setup(struct console *co, char *options)if (!np || !p)return -ENODEV ; -if (of_property_read_u32_array (np,"reg" , val32,ARRAY_SIZE (val32)) !=0 ) +if (of_property_read_u32_array (np,"reg" , val32,ARRAY_SIZE (val32)) !=0 ) { +of_node_put (np); + ma35d1serial_uart_nodes[co->index] =NULL ;return -EINVAL ; + } + +of_node_put (np); + ma35d1serial_uart_nodes[co->index] =NULL ; p->port.iobase = val32[1 ]; p->port.membase =ioremap (p->port.iobase,MA35_UART_REG_SIZE );
@@ -648,8 +654,10 @@ static void ma35d1serial_console_init_port(void)of_node_get (np); ma35d1serial_uart_nodes[i] = np; i++; -if (i ==MA35_UART_NR ) +if (i ==MA35_UART_NR ) { +of_node_put (np);break ; + } } } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 483/1376 serial: qcom-geni: do not advance stale DMA completions
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit 7ea38c49e7178960926657863299face6dc0e1b0 ]
The qcom GENI serial DMA TX completion path advances the transmit fifo by the number of bytes recorded in port->tx_remaining.
If uart_flush_buffer() runs after the hardware has completed a DMA transfer but before the DMA completion interrupt has been handled, the serial core resets the transmit fifo while port->tx_remaining still describes the old DMA transfer.
A previous fix avoided advancing an empty fifo by checking that the fifo length is at least tx_remaining. That still does not distinguish the old DMA payload from new bytes written after the flush. If userspace writes new data before the stale DMA completion interrupt is handled, the fifo can again contain at least tx_remaining bytes and the stale completion can advance and discard those new bytes.
Mark an in-flight DMA transfer stale when the transmit fifo is flushed. The later completion still unprepares the original DMA mapping using the saved length, but it no longer advances the transmit fifo.
--- drivers/tty/serial/qcom_geni_serial.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/tty/serial/qcom_geni_serial.c +9 -1
@@ -132,6 +132,7 @@ struct qcom_geni_serial_port {unsigned int tx_remaining;unsigned int tx_queued; +bool tx_dma_stale;int wakeup_irq;bool rx_tx_swap;bool cts_rts_swap;
@@ -659,6 +660,7 @@ static void qcom_geni_serial_start_tx_dma(struct uart_port *uport) } port->tx_remaining = xmit_size; + port->tx_dma_stale = false; }static void qcom_geni_serial_start_tx_fifo (struct uart_port *uport)
@@ -991,6 +993,7 @@ static void qcom_geni_serial_handle_tx_dma(struct uart_port *uport)struct qcom_geni_serial_port *port =to_dev_port (uport);struct tty_port *tport = &uport->state->port;unsigned int fifo_len =kfifo_len (&tport->xmit_fifo); +bool tx_dma_stale = port->tx_dma_stale;/* * Only advance the kfifo if it still contains the bytes that were
@@ -1001,12 +1004,13 @@ static void qcom_geni_serial_handle_tx_dma(struct uart_port *uport)* kfifo->in, making kfifo_len() wrap to UART_XMIT_SIZE - tx_remaining * and triggering a spurious large DMA transfer of stale data. */ -if (fifo_len >= port->tx_remaining) +if (!tx_dma_stale && fifo_len >= port->tx_remaining)uart_xmit_advance (uport, port->tx_remaining);geni_se_tx_dma_unprep (&port->se, port->tx_dma_addr, port->tx_remaining); port->tx_dma_addr =0 ; port->tx_remaining =0 ; + port->tx_dma_stale = false;if (!kfifo_is_empty (&tport->xmit_fifo))qcom_geni_serial_start_tx_dma (uport);
@@ -1142,6 +1146,10 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport)static void qcom_geni_serial_flush_buffer_fifo (struct uart_port *uport) { +struct qcom_geni_serial_port *port =to_dev_port (uport); + +if (port->tx_dma_addr) + port->tx_dma_stale = true;qcom_geni_serial_cancel_tx_cmd (uport); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 484/1376 usb: gadget: f_fs: Fix fence cleanup in ffs_dmabuf_transfer() error paths
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nuno Sá <[email protected]>
[ Upstream commit 621707dc67c9846fd876d7579ec951d92aa033f1 ]
The error paths for endpoint-disabled (ESHUTDOWN) and request-allocation failure (ENOMEM) in ffs_dmabuf_transfer() jump to err_fence_put which calls dma_fence_put() on the fence. However, at that point the fence has only been kmalloc'd — dma_fence_init() has not been called yet, so the refcount and the fence ops are uninitialized. Calling dma_fence_put() on such an object leads to undefined behavior.
Use kfree() instead, since the fence is just a plain allocation at this stage, and rename the label to err_fence_free to reflect the actual cleanup action.
--- drivers/usb/gadget/function/f_fs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/usb/gadget/function/f_fs.c +4 -4
@@ -1678,13 +1678,13 @@ static int ffs_dmabuf_transfer(struct file *file,/* In the meantime, endpoint got disabled or changed. */ if (epfile->ep != ep) { ret = -ESHUTDOWN ; - goto err_fence_put; + goto err_fence_free; } usb_req =usb_ep_alloc_request (ep->ep,GFP_ATOMIC );if (!usb_req) { ret = -ENOMEM ; - goto err_fence_put; + goto err_fence_free; }/*
@@ -1733,9 +1733,9 @@ static int ffs_dmabuf_transfer(struct file *file,return ret; -err_fence_put: +err_fence_free:spin_unlock_irq (&epfile->ffs->eps_lock); -dma_fence_put (&fence->base); +kfree (fence); err_resv_unlock:dma_resv_unlock (dmabuf->resv); err_attachment_put:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 485/1376 usb: gadget: configfs: fix out-of-bounds read of qw_sign
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
[ Upstream commit f63edb54d8f738f9c21e2068c777ae1c097df6b7 ]
os_desc_qw_sign_show() passes OS_STRING_QW_SIGN_LEN as the input length to utf16s_to_utf8s(), but that argument counts UTF-16 code units while OS_STRING_QW_SIGN_LEN (14) is the byte size of qw_sign[]. The array holds only OS_STRING_QW_SIGN_LEN / 2 (7) code units, so the conversion reads up to 7 units (14 bytes) past the end of qw_sign[] into the following members of struct gadget_info when the stored signature fills the array without a NUL terminator, exposing those bytes through the configfs attribute.
The store path halves the count for its input bound but passes the full byte count as the utf8s_to_utf16s() output limit; use the destination code-unit count in both directions.
--- drivers/usb/gadget/configfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/gadget/configfs.c +2 -2
@@ -1177,7 +1177,7 @@ static ssize_t os_desc_qw_sign_show(struct config_item *item, char *page)struct gadget_info *gi =os_desc_item_to_gadget_info (item);int res; - res =utf16s_to_utf8s ((wchar_t *) gi->qw_sign,OS_STRING_QW_SIGN_LEN , + res =utf16s_to_utf8s ((wchar_t *) gi->qw_sign,OS_STRING_QW_SIGN_LEN /2 ,UTF16_LITTLE_ENDIAN , page,PAGE_SIZE -1 ); page[res++] ='\n' ;
@@ -1199,7 +1199,7 @@ static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page,mutex_lock (&gi->lock); res =utf8s_to_utf16s (page, l,UTF16_LITTLE_ENDIAN , (wchar_t *) gi->qw_sign, -OS_STRING_QW_SIGN_LEN ); +OS_STRING_QW_SIGN_LEN /2 );if (res >0 ) res = len;mutex_unlock (&gi->lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 486/1376 usb: ljca: bound bank_num in ljca_enumerate_gpio()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <[email protected]>
[ Upstream commit dd9483726d0f16c1a56879c3edb65128259a4e2b ]
ljca_enumerate_gpio() reads desc->bank_num from the device and loops valid_pin[i] = get_unaligned_le32(...) for i < bank_num. valid_pin[] holds only LJCA_MAX_GPIO_NUM / 32 = 2 entries.
Two checks run before the loop. The reply length must match struct_size(desc, bank_desc, bank_num). The product pins_per_bank * bank_num must not exceed LJCA_MAX_GPIO_NUM. Neither one bounds bank_num against the size of valid_pin[]. The reply is capped at LJCA_MAX_PAYLOAD_SIZE (60) bytes, so the struct_size check limits bank_num to 9. A device that reports bank_num 9 with pins_per_bank 7 still passes both checks. gpio_num is 63 and the reply is 56 bytes. The loop then writes nine u32 into the two entry array and overruns valid_pin[] on the stack.
A broken or malicious LJCA device can therefore overflow the stack. Reject a bank_num that does not fit valid_pin[].
--- drivers/usb/misc/usb-ljca.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/usb/misc/usb-ljca.c +3 -0
@@ -585,6 +585,9 @@ static int ljca_enumerate_gpio(struct ljca_adapter *adap)if (gpio_num >LJCA_MAX_GPIO_NUM )return -EINVAL ; +if (desc->bank_num >ARRAY_SIZE (valid_pin)) +return -EINVAL ; +/* construct platform data */ gpio_info =kzalloc (sizeof *gpio_info,GFP_KERNEL );if (!gpio_info)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 487/1376 usb: gadget: aspeed_udc: check endpoint DMA allocation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit 97cee53a94be3bd4fd8fbed6071bd2f32dad1ab1 ]
ast_udc_probe() allocates a coherent DMA buffer used as the backing store for endpoint buffers. ast_udc_init_ep() derives per-endpoint buffer pointers from udc->ep0_buf, so a failed allocation is dereferenced during probe.
Check the allocation before endpoint setup. The existing probe error path called ast_udc_remove(), which unregisters the gadget unconditionally and is not safe before usb_add_gadget_udc() succeeds. Add a local cleanup helper for probe failures so pre-registration failures only unwind the resources that were actually initialized.
This was found by a local static analysis checker for unchecked allocator returns while scanning Linux 6.16. The change was checked by applying it to current mainline and by running checkpatch. I do not have access to Aspeed UDC hardware, so no runtime testing was performed.
--- drivers/usb/gadget/udc/aspeed_udc.c | 50 ++++++++++++++++++----------- 1 file changed, 32 insertions(+), 18 deletions(-)
drivers/usb/gadget/udc/aspeed_udc.c +32 -18
@@ -1434,25 +1434,12 @@ static void ast_udc_init_hw(struct ast_udc_dev *udc)ast_udc_write (udc,0 ,AST_UDC_EP0_CTRL ); } -static void ast_udc_remove (struct platform_device *pdev) +static void ast_udc_cleanup (struct platform_device *pdev) {struct ast_udc_dev *udc =platform_get_drvdata (pdev);unsigned long flags;u32 ctrl; -usb_del_gadget_udc (&udc->gadget); -if (udc->driver) { -/* -* This is broken as only some cleanup is skipped, *udev is -* freed and the register mapping goes away. Any further usage -* probably crashes. Also the device is unbound, so the skipped -* cleanup is never catched up later. -*/ -dev_alert (&pdev->dev, -"Driver is busy and still going away. Fasten your seat belts!\n" ); -return ; - } -spin_lock_irqsave (&udc->lock, flags);/* Disable upstream port connection */
@@ -1472,6 +1459,26 @@ static void ast_udc_remove(struct platform_device *pdev) udc->ep0_buf =NULL ; } +static void ast_udc_remove (struct platform_device *pdev) +{ +struct ast_udc_dev *udc =platform_get_drvdata (pdev); + +usb_del_gadget_udc (&udc->gadget); +if (udc->driver) { +/* +* This is broken as only some cleanup is skipped, *udev is +* freed and the register mapping goes away. Any further usage +* probably crashes. Also the device is unbound, so the skipped +* cleanup is never catched up later. +*/ +dev_alert (&pdev->dev, +"Driver is busy and still going away. Fasten your seat belts!\n" ); +return ; + } + +ast_udc_cleanup (pdev); +} +static int ast_udc_probe (struct platform_device *pdev) {enum usb_device_speed max_speed;
@@ -1524,6 +1531,12 @@ static int ast_udc_probe(struct platform_device *pdev)AST_UDC_NUM_ENDPOINTS , &udc->ep0_buf_dma, GFP_KERNEL); +if (!udc->ep0_buf) { +clk_disable_unprepare (udc->clk); + rc = -ENOMEM ; + goto err; + } + udc->gadget.speed =USB_SPEED_UNKNOWN ; udc->gadget.max_speed =USB_SPEED_HIGH ; udc->creq = udc->reg +AST_UDC_SETUP0 ;
@@ -1553,20 +1566,20 @@ static int ast_udc_probe(struct platform_device *pdev) udc->irq =platform_get_irq (pdev,0 );if (udc->irq <0 ) { rc = udc->irq; - goto err; + goto err_cleanup; } rc =devm_request_irq (&pdev->dev, udc->irq, ast_udc_isr,0 ,KBUILD_MODNAME , udc);if (rc) {dev_err (&pdev->dev,"Failed to request interrupt\n" ); - goto err; + goto err_cleanup; } rc =usb_add_gadget_udc (&pdev->dev, &udc->gadget);if (rc) {dev_err (&pdev->dev,"Failed to add gadget udc\n" ); - goto err; + goto err_cleanup; } dev_info(&pdev->dev, "Initialized udc in USB%s mode\n",
@@ -1574,9 +1587,10 @@ static int ast_udc_probe(struct platform_device *pdev)return 0 ; +err_cleanup: +ast_udc_cleanup (pdev); err:dev_err (&pdev->dev,"Failed to udc probe, rc:0x%x\n" , rc); -ast_udc_remove (pdev);return rc; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 488/1376 USB: make single lock for all usb dynamic id lists
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
[ Upstream commit 0b3144da31f855fce652303f588416a60991bdef ]
There are a number of places where we accidentally pass in a constant structure to later cast it off to a dynamic one, and then attempt to grab a lock on it, which is not a good idea. To help resolve this, move the dynamic id lock out of the dynamic id structure for the driver and into one single lock for all USB dynamic ids. As this lock should never have any real contention (it's only every accessed when a device is added or removed, which is always serialized) there should not be any difference except for some memory savings.
Note, this just converts the existing use of the dynamic id lock to the new static lock, there is one place that is accessing the dynamic id list without grabbing the lock, that will be fixed up in a follow-on change.
Stable-dep-of: ef8154d8b52d ("usb: fix UAF when probe runs concurrent to dyn ID removal")
--- drivers/usb/common/common.c | 3 +++ drivers/usb/core/driver.c | 15 +++++---------- drivers/usb/serial/bus.c | 4 +--- drivers/usb/serial/usb-serial.c | 4 +--- include/linux/usb.h | 2 +- 5 files changed, 11 insertions(+), 17 deletions(-)
drivers/usb/common/common.c +3 -0
@@ -415,6 +415,9 @@ EXPORT_SYMBOL_GPL(usb_of_get_companion_dev);struct dentry *usb_debug_root;EXPORT_SYMBOL_GPL (usb_debug_root); +DEFINE_MUTEX (usb_dynids_lock); +EXPORT_SYMBOL_GPL (usb_dynids_lock); +static int __init usb_common_init (void ) { usb_debug_root =debugfs_create_dir ("usb" ,NULL );
drivers/usb/core/driver.c +5 -10
@@ -95,9 +95,9 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, } } -spin_lock (&dynids->lock); +mutex_lock (&usb_dynids_lock);list_add_tail (&dynid->node, &dynids->list); -spin_unlock (&dynids->lock); +mutex_unlock (&usb_dynids_lock); retval =driver_attach (driver);
@@ -160,7 +160,7 @@ static ssize_t remove_id_store(struct device_driver *driver, const char *buf,if (fields <2 )return -EINVAL ; -spin_lock (&usb_driver->dynids.lock); +guard (mutex)(&usb_dynids_lock);list_for_each_entry_safe (dynid, n, &usb_driver->dynids.list, node) {struct usb_device_id *id = &dynid->id;
@@ -171,7 +171,6 @@ static ssize_t remove_id_store(struct device_driver *driver, const char *buf,break ; } } -spin_unlock (&usb_driver->dynids.lock);return count; }
@@ -220,12 +219,11 @@ static void usb_free_dynids(struct usb_driver *usb_drv) {struct usb_dynid *dynid, *n; -spin_lock (&usb_drv->dynids.lock); +guard (mutex)(&usb_dynids_lock);list_for_each_entry_safe (dynid, n, &usb_drv->dynids.list, node) {list_del (&dynid->node);kfree (dynid); } -spin_unlock (&usb_drv->dynids.lock); } static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,
@@ -233,14 +231,12 @@ static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *in {struct usb_dynid *dynid; -spin_lock (&drv->dynids.lock); +guard (mutex)(&usb_dynids_lock);list_for_each_entry (dynid, &drv->dynids.list, node) {if (usb_match_one_id (intf, &dynid->id)) { -spin_unlock (&drv->dynids.lock);return &dynid->id; } } -spin_unlock (&drv->dynids.lock);return NULL ; }
@@ -1076,7 +1072,6 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner, new_driver->driver.owner = owner; new_driver->driver.mod_name = mod_name; new_driver->driver.dev_groups = new_driver->dev_groups; -spin_lock_init (&new_driver->dynids.lock);INIT_LIST_HEAD (&new_driver->dynids.list); retval =driver_register (&new_driver->driver);
drivers/usb/serial/bus.c +1 -3
@@ -136,12 +136,11 @@ static void free_dynids(struct usb_serial_driver *drv) {struct usb_dynid *dynid, *n; -spin_lock (&drv->dynids.lock); +guard (mutex)(&usb_dynids_lock);list_for_each_entry_safe (dynid, n, &drv->dynids.list, node) {list_del (&dynid->node);kfree (dynid); } -spin_unlock (&drv->dynids.lock); }const struct bus_type usb_serial_bus_type = {
@@ -157,7 +156,6 @@ int usb_serial_bus_register(struct usb_serial_driver *driver)int retval; driver->driver.bus = &usb_serial_bus_type; -spin_lock_init (&driver->dynids.lock);INIT_LIST_HEAD (&driver->dynids.list); retval =driver_register (&driver->driver);
drivers/usb/serial/usb-serial.c +1 -3
@@ -706,14 +706,12 @@ static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf, {struct usb_dynid *dynid; -spin_lock (&drv->dynids.lock); +guard (mutex)(&usb_dynids_lock);list_for_each_entry (dynid, &drv->dynids.list, node) {if (usb_match_one_id (intf, &dynid->id)) { -spin_unlock (&drv->dynids.lock);return &dynid->id; } } -spin_unlock (&drv->dynids.lock);return NULL ; }
include/linux/usb.h +1 -1
@@ -1132,8 +1132,8 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)/* ----------------------------------------------------------------------- */ /* Stuff for dynamic usb ids */ +extern struct mutex usb_dynids_lock;struct usb_dynids { -spinlock_t lock;struct list_head list; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 489/1376 USB: make to_usb_driver() use container_of_const()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
[ Upstream commit 2f3aab7aecb827ba93c6222646eb0faa8228d590 ]
Turns out that we have some const pointers being passed to to_usb_driver() but were not catching this. Change the macro to properly propagate the const-ness of the pointer so that we will notice when we try to write to memory that we shouldn't be writing to.
This requires fixing up the usb_match_dynamic_id() function as well, because it can handle a const * to struct usb_driver.
Stable-dep-of: ef8154d8b52d ("usb: fix UAF when probe runs concurrent to dyn ID removal")
--- drivers/usb/core/driver.c | 4 ++-- include/linux/usb.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/usb/core/driver.c +2 -2
@@ -227,7 +227,7 @@ static void usb_free_dynids(struct usb_driver *usb_drv) }static const struct usb_device_id *usb_match_dynamic_id (struct usb_interface *intf, -struct usb_driver *drv) +const struct usb_driver *drv) {struct usb_dynid *dynid;
@@ -889,7 +889,7 @@ static int usb_device_match(struct device *dev, const struct device_driver *drv) }else if (is_usb_interface (dev)) {struct usb_interface *intf; -struct usb_driver *usb_drv; +const struct usb_driver *usb_drv;const struct usb_device_id *id;/* device drivers never match interfaces */
include/linux/usb.h +1 -1
@@ -1246,7 +1246,7 @@ struct usb_driver { unsigned int disable_hub_initiated_lpm:1; unsigned int soft_unbind:1; }; -#define to_usb_driver (d) container_of(d, struct usb_driver, driver) +#define to_usb_driver (d) container_of_const(d, struct usb_driver, driver)/** * struct usb_device_driver - identifies USB device driver to usbcore
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 490/1376 usb: fix UAF when probe runs concurrent to dyn ID removal
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gary Guo <[email protected]>
[ Upstream commit ef8154d8b52d60338c1fd8d793cd8e891c604c14 ]
Dynamic IDs are only guaranteed to be valid when usb_dynids_lock is held, as remove_id_store can free the node. Thus, make a copy in usb_probe_interface. Clarify the documentation that the id parameter is only valid during the probe.
USB serial has the same pattern, but it does not need fixing as the IDs cannot be removed via sysfs.
--- drivers/usb/core/driver.c | 12 ++++++++---- include/linux/usb.h | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-)
drivers/usb/core/driver.c +8 -4
@@ -227,14 +227,16 @@ static void usb_free_dynids(struct usb_driver *usb_drv) }static const struct usb_device_id *usb_match_dynamic_id (struct usb_interface *intf, -const struct usb_driver *drv) +const struct usb_driver *drv, +struct usb_device_id *id_copy) {struct usb_dynid *dynid;guard (mutex)(&usb_dynids_lock);list_for_each_entry (dynid, &drv->dynids.list, node) {if (usb_match_one_id (intf, &dynid->id)) { -return &dynid->id; + *id_copy = dynid->id; +return id_copy; } }return NULL ;
@@ -320,6 +322,7 @@ static int usb_probe_interface(struct device *dev)struct usb_interface *intf =to_usb_interface (dev);struct usb_device *udev =interface_to_usbdev (intf);const struct usb_device_id *id; +struct usb_device_id id_copy;int error = -ENODEV ;int lpm_disable_error = -ENODEV ;
@@ -339,7 +342,7 @@ static int usb_probe_interface(struct device *dev)return error; } - id =usb_match_dynamic_id (intf, driver); + id =usb_match_dynamic_id (intf, driver, &id_copy);if (!id) id =usb_match_id (intf, driver->id_table);if (!id)
@@ -891,6 +894,7 @@ static int usb_device_match(struct device *dev, const struct device_driver *drv)struct usb_interface *intf;const struct usb_driver *usb_drv;const struct usb_device_id *id; +struct usb_device_id id_copy;/* device drivers never match interfaces */ if (is_usb_device_driver (drv))
@@ -903,7 +907,7 @@ static int usb_device_match(struct device *dev, const struct device_driver *drv)if (id)return 1 ; - id =usb_match_dynamic_id (intf, usb_drv); + id =usb_match_dynamic_id (intf, usb_drv, &id_copy);if (id)return 1 ; }
include/linux/usb.h +2 -1
@@ -1159,7 +1159,8 @@ extern ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf);* interface. It may also use usb_set_interface() to specify the * appropriate altsetting. If unwilling to manage the interface, * return -ENODEV, if genuine IO errors occurred, an appropriate -* negative errno value. +* negative errno value. The usb_device_id parameter is only valid during +* probe. * @disconnect: Called when the interface is no longer accessible, usually * because its device has been (or is being) disconnected or the * driver module is being unloaded.
Signature · 1 line
2.53.0
Re: [PATCH 6.12 0490/1376] usb: fix UAF when probe runs concurrent to dyn ID removal
Hi Greg/Sasha,
Quoted 38 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gary Guo <[email protected]>
[ Upstream commit
ef8154d8b52d60338c1fd8d793cd8e891c604c14]Dynamic IDs are only guaranteed to be valid when
usb_dynids_lockis held, asremove_id_storecan free the node. Thus, make a copy inusb_probe_interface. Clarify the documentation that the id parameter is only valid during the probe.USB serial has the same pattern, but it does not need fixing as the IDs cannot be removed via sysfs.
Fixes 0c7a2b72746a ("USB: add remove_id sysfs attr for usb drivers")Signed-off-by Gary Guo <[email protected]>Reviewed-by Danilo Krummrich <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- drivers/usb/core/driver.c | 12 ++++++++---- include/linux/usb.h | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-)drivers/usb/core/driver.c +2
-1@@ -227,14 +227,16 @@ static void usb_free_dynids(struct usb_driver *usb_drv) }static const struct usb_device_id *usb_match_dynamic_id (struct usb_interface *intf, -const struct usb_driver *drv) +const struct usb_driver *drv, +struct usb_device_id *id_copy)
drivers/usb/core/driver.c static void usb_free_dynids(struct usb_driver *usb_drv) · line 240
Quoted 10 lines
drivers/usb/core/driver.c +2
-1{struct usb_dynid *dynid;guard (mutex)(&usb_dynids_lock);list_for_each_entry (dynid, &drv->dynids.list, node) {if (usb_match_one_id (intf, &dynid->id)) { -return &dynid->id; + *id_copy = dynid->id; +return id_copy; }
I ran an AI-assisted backport review, and I have verified the report. It looks valid to me.
The core UAF fix is present, but it deliberately passes a local copy of a dynamic USB ID to probe. The 6.12 xusbatm driver still computes id - xusbatm_usb_ids and uses that as an array index. A copied dynamic ID is not an element of that static array, so this driver violates the new contract.
Upstream prerequisite code:
int drv_ix = id->driver_info;
.no_dynamic_id = 1,Downstream 6.12.y code:
int drv_ix = id - xusbatm_usb_ids;
xusbatm_drivers + (id - xusbatm_usb_ids)
Upstream first applied eb6cd6d3d8ab, "usb: xusbatm: don't rely on id table pointer arithmetic".
Maybe we should queue that prerequisite as well. Thoughts?
thanks,
Harshit> }
Quoted 49 lines
drivers/usb/core/driver.c +4
-2return NULL ;@@ -320,6 +322,7 @@ static int usb_probe_interface(struct device *dev)struct usb_interface *intf =to_usb_interface (dev);struct usb_device *udev =interface_to_usbdev (intf);const struct usb_device_id *id; +struct usb_device_id id_copy;int error = -ENODEV ;int lpm_disable_error = -ENODEV ;@@ -339,7 +342,7 @@ static int usb_probe_interface(struct device *dev)return error; } - id =usb_match_dynamic_id (intf, driver); + id =usb_match_dynamic_id (intf, driver, &id_copy);if (!id) id =usb_match_id (intf, driver->id_table);if (!id)@@ -891,6 +894,7 @@ static int usb_device_match(struct device *dev, const struct device_driver *drv)struct usb_interface *intf;const struct usb_driver *usb_drv;const struct usb_device_id *id; +struct usb_device_id id_copy;/* device drivers never match interfaces */ if (is_usb_device_driver (drv))@@ -903,7 +907,7 @@ static int usb_device_match(struct device *dev, const struct device_driver *drv)if (id)return 1 ; - id =usb_match_dynamic_id (intf, usb_drv); + id =usb_match_dynamic_id (intf, usb_drv, &id_copy);if (id)return 1 ; }include/linux/usb.h +2
-1@@ -1159,7 +1159,8 @@ extern ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf);* interface. It may also use usb_set_interface() to specify the * appropriate altsetting. If unwilling to manage the interface, * return -ENODEV, if genuine IO errors occurred, an appropriate -* negative errno value. +* negative errno value. The usb_device_id parameter is only valid during +* probe. * @disconnect: Called when the interface is no longer accessible, usually * because its device has been (or is being) disconnected or the * driver module is being unloaded.
Re: [PATCH 6.12 0490/1376] usb: fix UAF when probe runs concurrent to dyn ID removal
Quoted 56 lines · Harshit Mogalapalli
Hi Greg/Sasha,
Quoted 38 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gary Guo <[email protected]>
[ Upstream commit
ef8154d8b52d60338c1fd8d793cd8e891c604c14]Dynamic IDs are only guaranteed to be valid when
usb_dynids_lockis held, asremove_id_storecan free the node. Thus, make a copy inusb_probe_interface. Clarify the documentation that the id parameter is only valid during the probe.USB serial has the same pattern, but it does not need fixing as the IDs cannot be removed via sysfs.
Fixes 0c7a2b72746a ("USB: add remove_id sysfs attr for usb drivers")Signed-off-by Gary Guo <[email protected]>Reviewed-by Danilo Krummrich <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- drivers/usb/core/driver.c | 12 ++++++++---- include/linux/usb.h | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-)drivers/usb/core/driver.c +2
-1@@ -227,14 +227,16 @@ static void usb_free_dynids(struct usb_driver *usb_drv) }static const struct usb_device_id *usb_match_dynamic_id (struct usb_interface *intf, -const struct usb_driver *drv) +const struct usb_driver *drv, +struct usb_device_id *id_copy)drivers/usb/core/driver.c static void usb_free_dynids(struct usb_driver *usb_drv) · line 240
Quoted 10 lines
drivers/usb/core/driver.c +2
-1{struct usb_dynid *dynid;guard (mutex)(&usb_dynids_lock);list_for_each_entry (dynid, &drv->dynids.list, node) {if (usb_match_one_id (intf, &dynid->id)) { -return &dynid->id; + *id_copy = dynid->id; +return id_copy; }I ran an AI-assisted backport review, and I have verified the report. It looks valid to me.
Quoted 5 lines
The core UAF fix is present, but it deliberately passes a local copy of a dynamic USB ID to probe. The 6.12 xusbatm driver still computes id -
xusbatm_usb_idsand uses that as an array index. A copied dynamic ID is not an element of that static array, so this driver violates the new contract.
I fixed all the drivers first before the core fix, but they're no real dependency between them.
Those code that do arithmetic or otherwise use the ID pointer assuming they're static are already broken when the ID pointer is actually from dynamic ID. The stack copy doesn't change it. Correct code stays correct, broken code stays broken.
I think it'd be good if the other patches in that series are backported too -- but that shouldn't be dependency of the core fix.
Best,
Gary
Quoted 67 lines
Upstream prerequisite code:
int drv_ix = id->driver_info; .no_dynamic_id = 1,Downstream 6.12.y code:
int
drv_ix= id -xusbatm_usb_ids;
xusbatm_drivers+ (id -xusbatm_usb_ids)Upstream first applied
eb6cd6d3d8ab, "usb: xusbatm: don't rely on id table pointer arithmetic".Maybe we should queue that prerequisite as well. Thoughts?
thanks,
Harshit> }Quoted 49 lines
drivers/usb/core/driver.c +4
-2return NULL ;@@ -320,6 +322,7 @@ static int usb_probe_interface(struct device *dev)struct usb_interface *intf =to_usb_interface (dev);struct usb_device *udev =interface_to_usbdev (intf);const struct usb_device_id *id; +struct usb_device_id id_copy;int error = -ENODEV ;int lpm_disable_error = -ENODEV ;@@ -339,7 +342,7 @@ static int usb_probe_interface(struct device *dev)return error; } - id =usb_match_dynamic_id (intf, driver); + id =usb_match_dynamic_id (intf, driver, &id_copy);if (!id) id =usb_match_id (intf, driver->id_table);if (!id)@@ -891,6 +894,7 @@ static int usb_device_match(struct device *dev, const struct device_driver *drv)struct usb_interface *intf;const struct usb_driver *usb_drv;const struct usb_device_id *id; +struct usb_device_id id_copy;/* device drivers never match interfaces */ if (is_usb_device_driver (drv))@@ -903,7 +907,7 @@ static int usb_device_match(struct device *dev, const struct device_driver *drv)if (id)return 1 ; - id =usb_match_dynamic_id (intf, usb_drv); + id =usb_match_dynamic_id (intf, usb_drv, &id_copy);if (id)return 1 ; }include/linux/usb.h +2
-1@@ -1159,7 +1159,8 @@ extern ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf);* interface. It may also use usb_set_interface() to specify the * appropriate altsetting. If unwilling to manage the interface, * return -ENODEV, if genuine IO errors occurred, an appropriate -* negative errno value. +* negative errno value. The usb_device_id parameter is only valid during +* probe. * @disconnect: Called when the interface is no longer accessible, usually * because its device has been (or is being) disconnected or the * driver module is being unloaded.
Re: [PATCH 6.12 0490/1376] usb: fix UAF when probe runs concurrent to dyn ID removal
Quoted 2 lines
I think it'd be good if the other patches in that series are backported too -- but that shouldn't be dependency of the core fix.
Queued for 7.2, 6.18, 6.12, 6.6 and 6.1, thanks.
One exception: 934e1322f18c ("usb: serial: spcp8x5: don't store usb_device_id") is skipped on 6.1, where usb-serial never exposes remove_id and re-derives the id itself, so the stored pointer cannot dangle there.
Signature · 2 lines
Thanks, Sasha
Greg Kroah-Hartman
maintainerPATCH 491/1376 platform/mellanox: mlxbf-pmc: Check ACPI_COMPANION() against NULL
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linmao Li <[email protected]>
[ Upstream commit c38cce70adef874c2a7b5132c14d6c221401deff ]
Every platform driver can be forced to match a device that doesn't match its list of device IDs because of device_match_driver_override(), so platform drivers that rely on the existence of a device's ACPI companion object need to verify its presence.
mlxbf_pmc_probe() passes the result of ACPI_COMPANION() to acpi_device_hid(), which dereferences it, so force-binding the driver to a device without an ACPI companion leads to a NULL pointer dereference.
Accordingly, add a requisite ACPI_COMPANION() check against NULL to the mlxbf-pmc driver and return -ENODEV when the companion is missing.
--- drivers/platform/mellanox/mlxbf-pmc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/platform/mellanox/mlxbf-pmc.c +8 -2
@@ -2021,13 +2021,19 @@ static int mlxbf_pmc_map_counters(struct device *dev)static int mlxbf_pmc_probe (struct platform_device *pdev) { -struct acpi_device *acpi_dev =ACPI_COMPANION (&pdev->dev); -const char *hid =acpi_device_hid (acpi_dev);struct device *dev = &pdev->dev; +struct acpi_device *acpi_dev;struct arm_smccc_res res; +const char *hid;guid_t guid;int ret; + acpi_dev =ACPI_COMPANION (&pdev->dev); +if (!acpi_dev) +return -ENODEV ; + + hid =acpi_device_hid (acpi_dev); +/* Ensure we have the UUID we expect for this service. */ arm_smccc_smc (MLXBF_PMC_SIP_SVC_UID ,0 ,0 ,0 ,0 ,0 ,0 ,0 , &res);guid_parse (mlxbf_pmc_svc_uuid_str, &guid);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 492/1376 platform/surface: acpi-notify: Check ACPI companion before use
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linmao Li <[email protected]>
[ Upstream commit 2b3a5dabe89e330413af403246b648c1890f368f ]
Since every platform driver can be forced to match a device that doesn't match its list of device IDs because of device_match_driver_override(), platform drivers that rely on the existence of a device's ACPI companion object should verify its presence.
san_probe() dereferences the result of ACPI_COMPANION() when installing the GSBUS address space handler, so force-binding the driver to a device without an ACPI companion leads to a NULL pointer dereference. The dereference was introduced when the probe function was switched from ACPI_HANDLE() to ACPI_COMPANION().
Check the ACPI companion against NULL and return -ENODEV when it is missing, like commit e4865a56d013 ("ACPI: driver: Check ACPI_COMPANION() against NULL during probe") does for the core ACPI platform drivers.
--- drivers/platform/surface/surface_acpi_notify.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/platform/surface/surface_acpi_notify.c +5 -1
@@ -777,12 +777,16 @@ static int san_consumer_links_setup(struct platform_device *pdev)static int san_probe (struct platform_device *pdev) { -struct acpi_device *san =ACPI_COMPANION (&pdev->dev);struct ssam_controller *ctrl; +struct acpi_device *san;struct san_data *data;acpi_status astatus;int status; + san =ACPI_COMPANION (&pdev->dev); +if (!san) +return -ENODEV ; + ctrl =ssam_client_bind (&pdev->dev);if (IS_ERR (ctrl))return PTR_ERR (ctrl) == -ENODEV ? -EPROBE_DEFER :PTR_ERR (ctrl);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 493/1376 usb: mtu3: allow system suspend during active gadget connection
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fei Shao <[email protected]>
[ Upstream commit e69027c25361b6044c7928715667586cc5469063 ]
When operating in gadget mode connected to a USB host, system suspend fails with -EBUSY because active peripheral connections block suspend entry.
Fix this by restricting the -EBUSY check to runtime autosuspend (PMSG_IS_AUTO). For system suspend (!PMSG_IS_AUTO), perform soft disconnect to disconnect from the bus and allow MAC sleep.
--- drivers/usb/mtu3/mtu3_core.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/usb/mtu3/mtu3_core.c +10 -1
@@ -1037,9 +1037,14 @@ int ssusb_gadget_suspend(struct ssusb_mtk *ssusb, pm_message_t msg)if (!mtu->gadget_driver)return 0 ; -if (mtu->connected) +/* Prevent runtime suspend when active connection exists */ +if (mtu->connected &&PMSG_IS_AUTO (msg))return -EBUSY ; +/* Perform soft disconnect for system suspend */ +if (mtu->softconnect && !PMSG_IS_AUTO (msg)) +mtu3_dev_on_off (mtu,0 ); +mtu3_dev_suspend (mtu);synchronize_irq (mtu->irq);
@@ -1055,5 +1060,9 @@ int ssusb_gadget_resume(struct ssusb_mtk *ssusb, pm_message_t msg)mtu3_dev_resume (mtu); +/* Restore soft connect for system resume */ +if (mtu->softconnect && !PMSG_IS_AUTO (msg)) +mtu3_dev_on_off (mtu,1 ); +return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 494/1376 usb: renesas_usbhs: Fix power-off ordering on unbind
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Biju Das <[email protected]>
[ Upstream commit 589b9e6f96be6bd8dd0d45fda8e948c31dc2fe94 ]
Move the usbhsc_power_ctrl() call to before hardware_exit() and reset_control_assert() in usbhs_remove(), so the PHY is powered off while priv->phy is still valid, rather than after hardware_exit() has already cleared it.
--- drivers/usb/renesas_usbhs/common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/usb/renesas_usbhs/common.c +3 -3
@@ -809,9 +809,6 @@ static void usbhs_remove(struct platform_device *pdev)flush_delayed_work (&priv->notify_hotplug_work); -usbhs_platform_call (priv, hardware_exit, pdev); -reset_control_assert (priv->rsts); -/* * Explicitly free the IRQ to ensure the interrupt handler is * disabled and synchronized before freeing resources.
@@ -828,6 +825,9 @@ static void usbhs_remove(struct platform_device *pdev)if (!usbhs_get_dparam (priv, runtime_pwctrl))usbhsc_power_ctrl (priv,0 ); +usbhs_platform_call (priv, hardware_exit, pdev); +reset_control_assert (priv->rsts); +usbhsc_clk_put (priv);pm_runtime_disable (&pdev->dev); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 495/1376 drm/panel: samsung-s6d16d0: Power off on prepare failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Laxman Acharya Padhya <[email protected]>
[ Upstream commit a9f950adfe2147318d75e7a6eab5e814851802ac ]
If enabling tearing mode or exiting sleep mode fails after the regulator is enabled, s6d16d0_prepare() returns without asserting reset or disabling the supply. Since the DRM panel core leaves the panel unprepared, a later unprepare call skips the driver callback and the supply remains enabled.
Assert reset and disable the supply before returning the DSI command error.
--- drivers/gpu/drm/panel/panel-samsung-s6d16d0.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/gpu/drm/panel/panel-samsung-s6d16d0.c +8 -2
@@ -89,16 +89,22 @@ static int s6d16d0_prepare(struct drm_panel *panel) MIPI_DSI_DCS_TEAR_MODE_VBLANK);if (ret) {dev_err (s6->dev,"failed to enable vblank TE (%d)\n" , ret); -return ret; + goto err_power_off; }/* Exit sleep mode and power on */ ret =mipi_dsi_dcs_exit_sleep_mode (dsi);if (ret) {dev_err (s6->dev,"failed to exit sleep mode (%d)\n" , ret); -return ret; + goto err_power_off; }return 0 ; + +err_power_off: +gpiod_set_value_cansleep (s6->reset_gpio,1 ); +regulator_disable (s6->supply); + +return ret; }static int s6d16d0_enable (struct drm_panel *panel)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 496/1376 perf metricgroup: Fix metric expression copy leaks
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yu Peng <[email protected]>
[ Upstream commit ef3af1df4f3372bd8ad47619452a283048b3bc8d ]
metricgroup__copy_metric_events() allocates a new metric expression and duplicates metric_name before linking the expression into the destination metric event.
Free new_expr when strdup() fails, and free the duplicated metric_name on the later error paths.
--- tools/perf/util/metricgroup.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
tools/perf/util/metricgroup.c +6 -1
@@ -1814,8 +1814,10 @@ int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp, new_expr->metric_expr = old_expr->metric_expr; new_expr->metric_threshold = old_expr->metric_threshold; new_expr->metric_name =strdup (old_expr->metric_name); -if (!new_expr->metric_name) +if (!new_expr->metric_name) { +free (new_expr);return -ENOMEM ; + } new_expr->metric_unit = old_expr->metric_unit; new_expr->runtime = old_expr->runtime;
@@ -1827,6 +1829,7 @@ int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp, alloc_size =sizeof (*new_expr->metric_refs); new_expr->metric_refs =calloc (nr +1 , alloc_size);if (!new_expr->metric_refs) { +zfree (&new_expr->metric_name);free (new_expr);return -ENOMEM ; }
@@ -1843,6 +1846,7 @@ int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp, alloc_size =sizeof (*new_expr->metric_events); new_expr->metric_events =calloc (nr +1 , alloc_size);if (!new_expr->metric_events) { +zfree (&new_expr->metric_name);zfree (&new_expr->metric_refs);free (new_expr);return -ENOMEM ;
@@ -1853,6 +1857,7 @@ int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp, evsel = old_expr->metric_events[idx]; evsel =evlist__find_evsel (evlist, evsel->core.idx);if (evsel ==NULL ) { +zfree (&new_expr->metric_name);zfree (&new_expr->metric_events);zfree (&new_expr->metric_refs);free (new_expr);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 497/1376 soc: qcom: rpmh-rsc: manage PM notifiers with devres
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit 75e918aa876440d8ad559a11d6ab87bddb1ed79a ]
rpmh_rsc_probe() registers CPU PM or genpd notifiers before populating child devices. If child population fails, the CPU PM notifier path is not unwound and the genpd path needs open-coded cleanup.
Use devm_pm_runtime_enable() for the genpd path and devm_add_action_or_reset() for both notifier registrations. This makes probe failure and driver detach use the same cleanup model while keeping devm_of_platform_populate() responsible for child devices.
--- drivers/soc/qcom/rpmh-rsc.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-)
drivers/soc/qcom/rpmh-rsc.c +26 -11
@@ -944,17 +944,30 @@ static int rpmh_rsc_pd_callback(struct notifier_block *nfb,return NOTIFY_OK ; } +static void rpmh_rsc_pd_detach (void *data) +{ +dev_pm_genpd_remove_notifier (data); +} +static int rpmh_rsc_pd_attach (struct rsc_drv *drv,struct device *dev) {int ret; -pm_runtime_enable (dev); + ret =devm_pm_runtime_enable (dev); +if (ret) +return ret; + drv->genpd_nb.notifier_call = rpmh_rsc_pd_callback; ret =dev_pm_genpd_add_notifier (dev, &drv->genpd_nb);if (ret) -pm_runtime_disable (dev); +return ret; -return ret; +return devm_add_action_or_reset (dev, rpmh_rsc_pd_detach, dev); +} + +static void rpmh_rsc_cpu_pm_unregister (void *data) +{ +cpu_pm_unregister_notifier (data); }static int rpmh_probe_tcs_config (struct platform_device *pdev,struct rsc_drv *drv)
@@ -1110,7 +1123,15 @@ static int rpmh_rsc_probe(struct platform_device *pdev)return ret; }else { drv->rsc_pm.notifier_call = rpmh_rsc_cpu_pm_callback; -cpu_pm_register_notifier (&drv->rsc_pm); + ret =cpu_pm_register_notifier (&drv->rsc_pm); +if (ret) +return ret; + + ret =devm_add_action_or_reset (&pdev->dev, + rpmh_rsc_cpu_pm_unregister, + &drv->rsc_pm); +if (ret) +return ret; } }
@@ -1125,13 +1146,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev)dev_set_drvdata (&pdev->dev, drv); drv->dev = &pdev->dev; - ret =devm_of_platform_populate (&pdev->dev); -if (ret && pdev->dev.pm_domain) { -dev_pm_genpd_remove_notifier (&pdev->dev); -pm_runtime_disable (&pdev->dev); - } - -return ret; +return devm_of_platform_populate (&pdev->dev); }static const struct of_device_id rpmh_drv_match[] = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 498/1376 bus: qcom-ebi2: use managed resources for clocks and children
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit d19a46f7ed8eb54fea61e0eaf7db53ff7babb03c ]
qcom_ebi2_probe() enables the EBI2 clocks manually and populates child devices manually. Several later failure paths can then return without disabling the clocks or without relying on the driver core to undo child population.
Use devm_clk_get_enabled() for both clocks and devm_of_platform_populate() for children. This lets the driver core unwind the resources automatically and removes the hand-written error labels.
--- drivers/bus/qcom-ebi2.c | 50 +++++++++-------------------------------- 1 file changed, 11 insertions(+), 39 deletions(-)
drivers/bus/qcom-ebi2.c +11 -39
@@ -302,41 +302,23 @@ static int qcom_ebi2_probe(struct platform_device *pdev)u32 val;int ret; - ebi2xclk =devm_clk_get (dev,"ebi2x" ); + ebi2xclk =devm_clk_get_enabled (dev,"ebi2x" );if (IS_ERR (ebi2xclk))return PTR_ERR (ebi2xclk); - ret =clk_prepare_enable (ebi2xclk); -if (ret) { -dev_err (dev,"could not enable EBI2X clk (%d)\n" , ret); -return ret; - } - - ebi2clk =devm_clk_get (dev,"ebi2" ); -if (IS_ERR (ebi2clk)) { - ret =PTR_ERR (ebi2clk); - goto err_disable_2x_clk; - } - - ret =clk_prepare_enable (ebi2clk); -if (ret) { -dev_err (dev,"could not enable EBI2 clk\n" ); - goto err_disable_2x_clk; - } + ebi2clk =devm_clk_get_enabled (dev,"ebi2" ); +if (IS_ERR (ebi2clk)) +return PTR_ERR (ebi2clk); res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); ebi2_base =devm_ioremap_resource (dev, res); -if (IS_ERR (ebi2_base)) { - ret =PTR_ERR (ebi2_base); - goto err_disable_clk; - } +if (IS_ERR (ebi2_base)) +return PTR_ERR (ebi2_base); res =platform_get_resource (pdev,IORESOURCE_MEM ,1 ); ebi2_xmem =devm_ioremap_resource (dev, res); -if (IS_ERR (ebi2_xmem)) { - ret =PTR_ERR (ebi2_xmem); - goto err_disable_clk; - } +if (IS_ERR (ebi2_xmem)) +return PTR_ERR (ebi2_xmem);/* Allegedly this turns the power save mode off */ writel (0UL , ebi2_xmem +EBI2_XMEM_CFG );
@@ -353,7 +335,7 @@ static int qcom_ebi2_probe(struct platform_device *pdev)/* Figure out the chipselect */ ret =of_property_read_u32 (child,"reg" , &csindex);if (ret) - goto err_disable_clk; +return ret;if (csindex >5 ) { dev_err(dev,
@@ -372,20 +354,10 @@ static int qcom_ebi2_probe(struct platform_device *pdev) have_children = true; } -if (have_children) { - ret =of_platform_default_populate (np,NULL , dev); -if (ret) - goto err_disable_clk; - } +if (have_children) +return devm_of_platform_populate (dev);return 0 ; - -err_disable_clk: -clk_disable_unprepare (ebi2clk); -err_disable_2x_clk: -clk_disable_unprepare (ebi2xclk); - -return ret; }static const struct of_device_id qcom_ebi2_of_match[] = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 499/1376 clk: qcom: camcc-sc8280xp: unregister CAMCC_GDSC_CLK
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Brian Masney <[email protected]>
[ Upstream commit 499b4cb6710f9a351d8b57a2132f9b4389d8464a ]
With the introduction of sync_state support in the clk and pmdomain subsystems, the following warning happens when the unused clocks are shutdown in camcc-sc8280xp:
[ 15.408367] titan_top_gdsc status stuck at 'on'
[ 15.408429] WARNING: drivers/clk/qcom/gdsc.c:178 at gdsc_toggle_logic+0x14c/0x160, CPU#2: kworker/u32:1/14
[ 15.408462] Modules linked in: bnep vfat fat ath11k_pci(+) ath11k mac80211 cfg80211 mhi libarc4 snd_soc_wcd938x snd_soc_wcd938x_sdw snd_soc_wcd_classh hci_uart snd_soc_wcd_common
snd_soc_sc8280xp soundwire_qcom snd_soc_wcd_mbhc snd_soc_qcom_sdw slimbus snd_soc_qcom_common regmap_sdw btqca btrtl qcom_camss soundwire_bus btbcm btintel snd_soc_sdca snd_soc_lpass_wsa_macro
bluetooth snd_soc_lpass_tx_macro snd_soc_lpass_va_macro snd_soc_lpass_rx_macro snd_soc_hdmi_codec snd_soc_lpass_macro_common videobuf2_dma_sg ov5675 v4l2_fwnode videobuf2_memops
qcom_spmi_adc5 snd_soc_core qcom_spmi_adc_tm5 videobuf2_v4l2 snd_seq snd_seq_device videobuf2_common v4l2_async qcom_vadc_common qcom_spmi_temp_alarm pm8941_pwrkey industrialio videodev
snd_compress rfkill ac97_bus snd_pcm_dmaengine qcom_tsens mc qcom_edac snd_pcm pci_pwrctrl_pwrseq qcom_cpufreq_hw snd_timer snd qcomtee soundcore tee leds_gpio joydev binfmt_misc zram
lz4hc_compress governor_simpleondemand panel_edp msm xhci_plat_hcd nvme nvme_core dwc3 qcom_pm8008_regulator
[ 15.408688] ucsi_glink nvme_keyring nvme_auth pmic_glink_altmode udc_core typec_ucsi aux_hpd_bridge qcom_battmgr ulpi ubwc_config socinfo ocmem drm_gpuvm qcom_q6v5_pas drm_exec
qcom_pil_info leds_qcom_lpg gpu_sched led_class_multicolor rtc_pm8xxx qcom_pbs qcom_common drm_display_helper qcom_pon qcom_glink_smem qcom_glink ghash_ce pwrseq_qcom_wcn gpio_sbu_mux
qcom_stats phy_qcom_qmp_combo qcom_q6v5 gf128mul cec dispcc_sc8280xp phy_qcom_edp camcc_sc8280xp i2c_qcom_cci qcom_sysmon drm_dp_aux_bus mdt_loader aux_bridge qcom_pm8008 i2c_hid_of_elan
dwc3_qcom_legacy llcc_qcom icc_bwmon gpi typec qcom_refgen_regulator phy_qcom_qmp_usb nvmem_qfprom qcom_ipcc phy_qcom_snps_femto_v2 gpucc_sc8280xp pinctrl_sc8280xp_lpass_lpi qcom_hwspinlock
pinctrl_lpass_lpi lpasscc_sc8280xp qrtr qcom_aoss pmic_glink pdr_interface phy_qcom_qmp_pcie qcom_smd qcom_pdr_msg icc_osm_l3 qcom_wdt qmi_helpers qcom_rng smp2p rpmsg_core gpio_keys pwm_bl
smem hid_multitouch fuse i2c_dev
[ 15.408928] CPU: 2 UID: 0 PID: 14 Comm: kworker/u32:1 Not tainted 7.1.0+ #2 PREEMPT(lazy)
[ 15.408937] Hardware name: LENOVO 21BX0016US/21BX0016US, BIOS N3HET88W (1.60 ) 03/14/2024
[ 15.408942] Workqueue: pm pm_runtime_work
[ 15.408959] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 15.408967] pc : gdsc_toggle_logic+0x14c/0x160
[ 15.408978] lr : gdsc_toggle_logic+0x14c/0x160
[ 15.408987] sp : ffff8000800f3b40
[ 15.408991] x29: ffff8000800f3b40 x28: 0000000000000000 x27: 0000000000000000
[ 15.409003] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000
[ 15.409014] x23: 0000000000000000 x22: 0000000000000001 x21: ffffa33f298fca88
[ 15.409024] x20: 0000000000000000 x19: ffffa33f298fc5b0 x18: 00cd15db75dacefd
[ 15.409035] x17: 000000040044ffff x16: ffffa33f3b1a3d88 x15: 726f776b80000002
[ 15.409045] x14: ffffffffffffffff x13: 0000000000000028 x12: 0101010101010101
[ 15.409056] x11: 7f7f7f7f7f7f7f7f x10: fefeff3039313274 x9 : ffffa33f3a5edafc
[ 15.409067] x8 : ffff8000800f3780 x7 : 0000000000000001 x6 : 0000000000000001
[ 15.409078] x5 : ffff000bf3ca1288 x4 : 0000000000000000 x3 : ffff5cccb6a3f000
[ 15.409088] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff000080ae0000
[ 15.409098] Call trace:
[ 15.409103] gdsc_toggle_logic+0x14c/0x160 (P)
[ 15.409115] gdsc_disable+0x4c/0x190
[ 15.409126] _genpd_power_off+0xa0/0x1a8
[ 15.409137] genpd_power_off.part.0+0x180/0x2a0
[ 15.409149] genpd_runtime_suspend+0x218/0x310
[ 15.409155] __rpm_callback+0x50/0x1f8
[ 15.409166] rpm_callback+0x7c/0x90
[ 15.409175] rpm_suspend+0xe8/0x690
[ 15.409185] pm_runtime_work+0xd0/0xe0
[ 15.409195] process_one_work+0x18c/0x518
[ 15.409208] worker_thread+0x190/0x320
[ 15.409218] kthread+0x110/0x130
[ 15.409227] ret_from_fork+0x10/0x20This clock is force enabled to be on in the probe, and registered with the Common Clk Framework, resulting in them being toggled off after unused clocks are shutdown. This clock is required for the GDSC transitions.
Similar to the fix in commit b60521eff227 ("clk: qcom: gcc-x1e80100:
Unregister GCC_GPU_CFG_AHB_CLK/GCC_DISP_XO_CLK"), let's just unregister this clock.
--- drivers/clk/qcom/camcc-sc8280xp.c | 19 ------------------- 1 file changed, 19 deletions(-)
drivers/clk/qcom/camcc-sc8280xp.c +0 -19
@@ -1754,24 +1754,6 @@ static struct clk_branch camcc_csiphy3_clk = { }, }; -static struct clk_branch camcc_gdsc_clk = { - .halt_reg =0xc1e4 , - .halt_check =BRANCH_HALT , - .clkr = { - .enable_reg =0xc1e4 , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="camcc_gdsc_clk" , - .parent_hws = (const struct clk_hw *[]){ - &camcc_xo_clk_src.clkr.hw, - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; -static struct clk_branch camcc_icp_ahb_clk = { .halt_reg =0xc0d8 , .halt_check =BRANCH_HALT ,
@@ -2840,7 +2822,6 @@ static struct clk_regmap *camcc_sc8280xp_clocks[] = { [CAMCC_CSIPHY2_CLK] = &camcc_csiphy2_clk.clkr, [CAMCC_CSIPHY3_CLK] = &camcc_csiphy3_clk.clkr, [CAMCC_FAST_AHB_CLK_SRC] = &camcc_fast_ahb_clk_src.clkr, - [CAMCC_GDSC_CLK] = &camcc_gdsc_clk.clkr, [CAMCC_ICP_AHB_CLK] = &camcc_icp_ahb_clk.clkr, [CAMCC_ICP_CLK] = &camcc_icp_clk.clkr, [CAMCC_ICP_CLK_SRC] = &camcc_icp_clk_src.clkr,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 500/1376 iio: accel: dmard09: Implement IIO_CHAN_INFO_SCALE
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mert Seftali <[email protected]>
[ Upstream commit aa58ecc73466d0cb8c418de98e2225490bf600e3 ]
Reading the in_accel_scale attribute on the DMARD09 has always returned -EINVAL: the channels advertise scale via info_mask_shared_by_type so the IIO core exposes the attribute, but dmard09_read_raw() only handles IIO_CHAN_INFO_RAW, so a SCALE read falls through to 'default: return -EINVAL':
$ cat .../iio:deviceX/in_accel_scale
cat: in_accel_scale: Invalid argumentleaving userspace with raw counts it cannot convert to m/s^2.
The driver was written from a vendor source [1] without a datasheet, and the scale was declared but never implemented. The vendor source carries the sensitivity: its conversion is
acc = raw * GRAVITY_EARTH_1000 / sensitivity (then / 1000 -> m/s^2)
with sensitivity = 32 and GRAVITY_EARTH_1000 = 9807 ("about (9.80665)*1000"), i.e. 32 counts correspond to 1 g.
That sensitivity applies to the value this driver already reports as raw:
the vendor reduces each 16-bit sample to a signed 9-bit value, and the preparation in dmard09_read_raw() yields the same value. It is
self-consistent: 256 counts / 32 = 8 g full scale, matching the +/-8g range.
Implement the scale derived from that sensitivity using standard gravity:
scale = 9.80665 / 32 = 0.3064578125 m/s^2 per LSB
--- drivers/iio/accel/dmard09.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/iio/accel/dmard09.c +7 -0
@@ -8,6 +8,7 @@#include <linux/unaligned.h> #include <linux/module.h> #include <linux/i2c.h> +#include <linux/units.h> #include <linux/iio/iio.h> #define DMARD09_DRV_NAME "dmard09"
@@ -79,6 +80,12 @@ static int dmard09_read_raw(struct iio_dev *indio_dev, *val = accel;return IIO_VAL_INT ; +case IIO_CHAN_INFO_SCALE : + *val =0 ; +/* 1 g / 32 LSB, in m/s^2 */ + *val2 =IIO_G_TO_M_S_2 (NANO /32 ); + +return IIO_VAL_INT_PLUS_NANO ;default :return -EINVAL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 501/1376 RDMA/core: Wait for RCU callbacks before unloading ib_core
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 7d75592114d1664623c8cf191a12b38052c04483 ]
put_gid_ndev() is queued with call_rcu() and implemented in ib_core. Stopping the workqueues does not drain callbacks already queued, so RCU could invoke it after the module code has been unloaded.
synchronize_rcu() does not wait for callbacks. Wait for them after all producers have stopped.
--- drivers/infiniband/core/device.c | 1 + 1 file changed, 1 insertion(+)
drivers/infiniband/core/device.c +1 -0
@@ -3017,6 +3017,7 @@ static void __exit ib_core_cleanup(void)/* Make sure that any pending umem accounting work is done. */ destroy_workqueue (ib_wq);destroy_workqueue (ib_unreg_wq); +rcu_barrier ();WARN_ON (!xa_empty (&clients));WARN_ON (!xa_empty (&devices)); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 502/1376 RDMA/mlx5: Drain RCU callbacks during module teardown
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit e37cdd75f8d61c1123d324ae5667ac3da562290e ]
devx_free_subscription() can remain queued after the last DevX event file drops its module reference or an auxiliary driver detaches its devices. mlx5_ib can then unload before the callback runs.
Registration error unwind has the same risk because driver registration can attach existing devices before failing. Wait after all drivers have stopped.
--- drivers/infiniband/hw/mlx5/main.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/infiniband/hw/mlx5/main.c +2 -0
@@ -5101,6 +5101,7 @@ static int __init mlx5_ib_init(void) dd_err:mlx5r_rep_cleanup (); rep_err: +rcu_barrier ();mlx5_ib_qp_event_cleanup (); qp_event_err:destroy_workqueue (mlx5_ib_event_wq);
@@ -5114,6 +5115,7 @@ static void __exit mlx5_ib_cleanup(void)auxiliary_driver_unregister (&mlx5r_driver);auxiliary_driver_unregister (&mlx5r_mp_driver);mlx5r_rep_cleanup (); +rcu_barrier ();mlx5_ib_qp_event_cleanup ();destroy_workqueue (mlx5_ib_event_wq);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 503/1376 RDMA/ipoib: Drain RCU callbacks during module teardown
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 31b7c700670830a0e8a4cdcd451c88a13cc5dc48 ]
IPoIB reclamation completions can be signaled from inside an RCU callback. Teardown can wake before the callback returns and unload ib_ipoib while its code is still executing.
Client registration failure can also remove already-added devices and queue callbacks. Wait after client and workqueue teardown.
--- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/infiniband/ulp/ipoib/ipoib_main.c +2 -0
@@ -2703,6 +2703,7 @@ static int __init ipoib_init_module(void) err_sa:ib_sa_unregister_client (&ipoib_sa_client);destroy_workqueue (ipoib_workqueue); +rcu_barrier (); err_fs:ipoib_unregister_debugfs ();
@@ -2720,6 +2721,7 @@ static void __exit ipoib_cleanup_module(void)ib_sa_unregister_client (&ipoib_sa_client);ipoib_unregister_debugfs ();destroy_workqueue (ipoib_workqueue); +rcu_barrier (); }module_init (ipoib_init_module);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 504/1376 RDMA/rxe: Avoid reprocessing the current packet after the QP enters the error state
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Allison Henderson <[email protected]>
[ Upstream commit 15ae32c4a3551c4c9da457370bdfdd65d171e512 ]
When do_complete() finds the QP in the error state it returns RESPST_CHK_RESOURCE. Before commit 49dc9c1f0c7e ("RDMA/rxe: Cleanup reset state handling in rxe_resp.c") this was the flush loop:check_resource() had an error-state branch that fetched each remaining recv WQE and completed it with IB_WC_WR_FLUSH_ERR, without touching the current packet. That commit removed the error-state branch from check_resource() (draining is now done at rxe_receiver() entry) but kept the do_complete() error-state return.
As a result, when a QP moves to the error state while a packet is being completed - e.g. an rdma_cm disconnect racing with receive processing - the responder state machine loops back into the request processing chain with the already-completed packet still in hand:check_resource() fetches a fresh recv WQE, execute()/send_data_in() copies the same packet payload again, do_complete() posts another IB_WC_SUCCESS CQE (qp->resp.status is still 0), and control returns to the error-state check. The loop re-executes the same packet once per posted recv WQE (observed: ~1000 duplicate IB_WC_SUCCESS completions of one SEND, one per ~8us, matching the RQ occupancy) until the RQ is exhausted, after which qp->resp.wqe is NULL and send_data_in() dereferences it:
BUG: kernel NULL pointer dereference, address: 0000000000000014 Workqueue: rxe_wq do_work RIP: copy_data+0x29/0x1f0 Call Trace: send_data_in+0x25/0x50 rxe_receiver+0xf36/0x1dd0
The duplicate completions are indistinguishable from real receives to the ULP. During an rds stress test, the message was accepted as new and delivered the same datagram to user space hundreds of times, corrupting the stream; any ULP that relies on RC exactly-once delivery is affected.
A live packet reaching the error-state check in do_complete() has been executed and completed exactly once and must be consumed, not re-processed. Return RESPST_CLEANUP for it (dequeue and free); keep returning RESPST_CHK_RESOURCE for the pkt == NULL case.
--- drivers/infiniband/sw/rxe/rxe_resp.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/infiniband/sw/rxe/rxe_resp.c +8 -1
@@ -1188,7 +1188,14 @@ static enum resp_states do_complete(struct rxe_qp *qp,spin_lock_irqsave (&qp->state_lock, flags);if (unlikely (qp_state (qp) ==IB_QPS_ERR )) {spin_unlock_irqrestore (&qp->state_lock, flags); -return RESPST_CHK_RESOURCE ; +/* The packet was executed and completed before the QP +* moved to ERROR; it must be consumed exactly once. +* Re-entering the request chain with the stale packet +* would copy it into every remaining recv WQE as a new +* completion. Remaining WQEs are flushed by the drain +* path at rxe_receiver() entry. +*/ +return pkt ?RESPST_CLEANUP :RESPST_CHK_RESOURCE ; }spin_unlock_irqrestore (&qp->state_lock, flags);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 505/1376 crypto: ccp - Fix memory leak in SEV INIT_EX path
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Atish Patra <[email protected]>
[ Upstream commit c8e53ada20d352b0f1bdc3e58405a9edab897a2e ]
allocated pages in _init_ext_path are never freed and sev_init_ex_buffer is left pointing at the leaked memory in case of any failures during the function..
Fix by adding an error path that frees the pages and clears sev_init_ex_buffer. Make sure we only free the memory if the failure happens before the conversion. Otherwise, we may end up trying to free up converted pages in case of reclaim failure. rmp_mark_pages_firmware failures should be rare enough to avoid more code complexity to track down which pages were reclaimed/leaked vs which are not.
--- drivers/crypto/ccp/sev-dev.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
drivers/crypto/ccp/sev-dev.c +14 -3
@@ -1244,7 +1244,7 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)if (sev_init_ex_buffer)return 0 ; - page =alloc_pages (GFP_KERNEL ,get_order (NV_LENGTH )); + page =alloc_pages (GFP_KERNEL | __GFP_ZERO,get_order (NV_LENGTH ));if (!page) {dev_err (sev->dev,"SEV: INIT_EX NV memory allocation failed\n" );return -ENOMEM ;
@@ -1254,7 +1254,7 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev) rc =sev_read_init_ex_file ();if (rc) -return rc; + goto err_free;/* If SEV-SNP is initialized, transition to firmware page. */ if (sev->snp_initialized) {
@@ -1263,11 +1263,22 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev) npages =1UL <<get_order (NV_LENGTH );if (rmp_mark_pages_firmware (__pa (sev_init_ex_buffer), npages, false)) {dev_err (sev->dev,"SEV: INIT_EX NV memory page state change failed.\n" ); -return -ENOMEM ; + rc = -ENOMEM ; +/* +* Pages can be in an inconsistent state, don't release them back to the +* system. +*/ + goto err_reset; } }return 0 ; + +err_free: +__free_pages (page,get_order (NV_LENGTH )); +err_reset: + sev_init_ex_buffer =NULL ; +return rc; }static int __sev_platform_init_locked (int *error)
Signature · 1 line
2.53.0
Re: [PATCH 6.12 0505/1376] crypto: ccp - Fix memory leak in SEV INIT_EX path
Hi Greg/Sasha,
Quoted 54 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Atish Patra <[email protected]>
[ Upstream commit
c8e53ada20d352b0f1bdc3e58405a9edab897a2e]allocated pages in
_init_ext_pathare never freed andsev_init_ex_bufferis left pointing at the leaked memory in case of any failures during the function..Fix by adding an error path that frees the pages and clears
sev_init_ex_buffer. Make sure we only free the memory if the failure happens before the conversion. Otherwise, we may end up trying to free up converted pages in case of reclaim failure.rmp_mark_pages_firmwarefailures should be rare enough to avoid more code complexity to track down which pages were reclaimed/leaked vs which are not.Fixes 7364a6fbca45 ("crypto: ccp: Handle non-volatile INIT_EX data when SNP is enabled")Reported-by Sashiko <[email protected]>Reviewed-by Tom Lendacky <[email protected]>Signed-off-by Atish Patra <[email protected]>Acked-by Herbert Xu <[email protected]>Signed-off-by Herbert Xu <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- drivers/crypto/ccp/sev-dev.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)drivers/crypto/ccp/sev-dev.c +2
-2@@ -1244,7 +1244,7 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)if (sev_init_ex_buffer)return 0 ; - page =alloc_pages (GFP_KERNEL ,get_order (NV_LENGTH )); + page =alloc_pages (GFP_KERNEL | __GFP_ZERO,get_order (NV_LENGTH ));if (!page) {dev_err (sev->dev,"SEV: INIT_EX NV memory allocation failed\n" );return -ENOMEM ;@@ -1254,7 +1254,7 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev) rc =sev_read_init_ex_file ();if (rc) -return rc; + goto err_free;/* If SEV-SNP is initialized, transition to firmware page. */ if (sev->snp_initialized) {
drivers/crypto/ccp/sev-dev.c static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev) · line 1269
Quoted 8 lines
drivers/crypto/ccp/sev-dev.c +4
-1@@ -1263,11 +1263,22 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev) npages =1UL <<get_order (NV_LENGTH );if (rmp_mark_pages_firmware (__pa (sev_init_ex_buffer), npages, false)) {dev_err (sev->dev,"SEV: INIT_EX NV memory page state change failed.\n" ); -return -ENOMEM ; + rc = -ENOMEM ; +/* +* Pages can be in an inconsistent state, don't release them back to the +* system.
I ran an AI-assisted backport review and manually verified the finding.
Upstream c8e53ada20d3 follows b0e7ec0dab242c5e480121ba12400d0513e37ca2, "crypto: ccp - Fix possible deadlock in SEV init failure path", but 6.12 has only the former. The backport retains locked=false in rmp_mark_pages_firmware() while sev_cmd_mutex is already held.
Upstream code after b0e7ec0dab24:
rmp_mark_pages_firmware(__pa(sev_init_ex_buffer),
npages, true)
Downstream 6.12.y code:
rmp_mark_pages_firmware(__pa(sev_init_ex_buffer),
npages, false)
The downstream false argument can reacquire sev_cmd_mutex in rollback.
If a later page conversion fails, rollback enters snp_reclaim_pages(). The false argument selects sev_do_cmd(), which tries to take the same mutex again, so the cleanup added by this patch cannot finish.
Maybe we should beapplying b0e7ec0dab242c5e480121ba12400d0513e37ca2 to the queue now that this backport is merged.
Thanks,
Harshit> + */
Quoted 14 lines
drivers/crypto/ccp/sev-dev.c +7
-0+ goto err_reset; } }return 0 ; + +err_free: +__free_pages (page,get_order (NV_LENGTH )); +err_reset: + sev_init_ex_buffer =NULL ; +return rc; }static int __sev_platform_init_locked (int *error)
Re: [PATCH 6.12 0505/1376] crypto: ccp - Fix memory leak in SEV INIT_EX path
Quoted 4 lines
Upstream
c8e53ada20d3followsb0e7ec0dab242c5e480121ba12400d0513e37ca2, "crypto: ccp - Fix possible deadlock in SEV init failure path", but 6.12 has only the former. The backport retains locked=false inrmp_mark_pages_firmware()whilesev_cmd_mutexis already held.
Queued for 6.18 and 6.12, thanks. 6.18 had the same gap.
Signature · 2 lines
Thanks, Sasha
Re: [PATCH 6.12 0505/1376] crypto: ccp - Fix memory leak in SEV INIT_EX path
Quoted 1 line · Sasha Levin
Queued for 6.18 and 6.12, thanks. 6.18 had the same gap.
thanks!
Regards,
Harshit
Greg Kroah-Hartman
maintainerPATCH 506/1376 hwrng: ks-sa - Fix runtime PM cleanup on registration failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 1c17b601fafb09c9ec074fd097737d20eafe7d63 ]
ks_sa_rng_probe() enables runtime PM and resumes the device before registering the hwrng. If devm_hwrng_register() fails, probe returns without dropping the runtime PM usage count or disabling runtime PM.
Unwind the runtime PM state on the registration failure path, matching the cleanup done by remove().
--- drivers/char/hw_random/ks-sa-rng.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/char/hw_random/ks-sa-rng.c +8 -1
@@ -242,7 +242,14 @@ static int ks_sa_rng_probe(struct platform_device *pdev)return dev_err_probe (dev, ret,"Failed to enable SA power-domain\n" ); } -return devm_hwrng_register (&pdev->dev, &ks_sa_rng->rng); + ret =devm_hwrng_register (dev, &ks_sa_rng->rng); +if (ret) { +pm_runtime_put_sync (dev); +pm_runtime_disable (dev); +return ret; + } + +return 0 ; }static void ks_sa_rng_remove (struct platform_device *pdev)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 507/1376 xfrm6: fix out-of-bounds write in xfrm6_input_addr() when secpath is full
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit 5d9e3bf34fec9a5d237e4b7cef4a707bc2e091bc ]
The depth check in xfrm6_input_addr() is off by one:
if (1 + sp->len == XFRM_MAX_DEPTH)
goto drop;
...
sp->xvec[sp->len++] = x;xfrm_input() can leave sp->len == XFRM_MAX_DEPTH, and the transport-mode receive path re-enters IPv6 input via xfrm_trans_reinject() with that secpath preserved. If the inner packet carries a destination-options HAO option or a type-2 routing header, xfrm6_input_addr() is called with sp->len == XFRM_MAX_DEPTH; the check (1 + 6 == 6) is false, so sp->xvec[sp->len++] writes one slot past the 6-element xvec[]. The write stays within the sec_path allocation (invisible to KASAN); UBSAN_BOUNDS flags it and panics under panic_on_warn.
Use "sp->len >= XFRM_MAX_DEPTH", matching xfrm_input(). This also restores one chain level the old check rejected at sp->len == 5.
UBSAN: array-index-out-of-bounds in net/ipv6/xfrm6_input.c:309:10 index 6 is out of range for type 'xfrm_state *[6]'
--- net/ipv6/xfrm6_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/xfrm6_input.c +1 -1
@@ -249,7 +249,7 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, goto drop; } -if (1 + sp->len ==XFRM_MAX_DEPTH ) { +if (sp->len >=XFRM_MAX_DEPTH ) {XFRM_INC_STATS (net,LINUX_MIB_XFRMINBUFFERERROR ); goto drop; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 508/1376 ALSA: hpi: Check transport errors during HPI6000 adapter initialization
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Evgenii Burenchev <[email protected]>
[ Upstream commit cc15c329663e3ef1aeed0b68e49a5d5ce4ae0d5c ]
create_adapter_obj() retrieves adapter information by calling hpi6000_message_response_sequence(). This function reports transport-level errors through its return value and DSP-reported errors via hr0.error.
The current code only checks hr0.error, causing transport-level errors to be ignored. As a result, adapter initialization may continue with an invalid response.
Check the return value of hpi6000_message_response_sequence() before examining hr0.error.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- sound/pci/asihpi/hpi6000.c | 5 +++++ 1 file changed, 5 insertions(+)
sound/pci/asihpi/hpi6000.c +5 -0
@@ -537,6 +537,11 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao, hr1.size =sizeof (hr1); error =hpi6000_message_response_sequence (pao,0 , &hm, &hr0); +if (error) { +HPI_DEBUG_LOG (ERROR ,"message transport error %d\n" , + error); +return error; + }if (hr0.error) {HPI_DEBUG_LOG (DEBUG ,"message error %d\n" , hr0.error);return hr0.error;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 509/1376 pmdomain: bcm: bcm2835: handle genpd provider registration errors
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit a1d9d3b958d69a13783613304f524f489fecdd1f ]
bcm2835_power_probe() initializes all power domains and then registers the onecell genpd provider, but ignores of_genpd_add_provider_onecell() failures. Probe can therefore return success even though no provider was published.
Check the provider registration return value and jump to the existing cleanup path on failure.
--- drivers/pmdomain/bcm/bcm2835-power.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/pmdomain/bcm/bcm2835-power.c +6 -1
@@ -682,7 +682,12 @@ static int bcm2835_power_probe(struct platform_device *pdev)if (ret) goto fail; -of_genpd_add_provider_onecell (dev->parent->of_node, &power->pd_xlate); + ret =of_genpd_add_provider_onecell (dev->parent->of_node, + &power->pd_xlate); +if (ret) { +dev_err_probe (dev, ret,"failed to add genpd provider\n" ); + goto fail; + }dev_info (dev,"Broadcom BCM2835 power domains driver" );return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 510/1376 misc: rtsx_usb: avoid USB I/O in runtime autosuspend
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Rhodes <[email protected]>
[ Upstream commit 483c948324a3823871c004560a92545759d3253c ]
The runtime autosuspend callback currently queries card status and clears OCP by issuing USB register accesses. This can run from the USB runtime-PM path itself, which is the wrong place to start more device I/O.
Keep a cached copy of the card-status bits from normal status reads instead. During runtime autosuspend, use that cached value only to preserve the existing Memory Stick autosuspend deferral.
Do not treat raw SD_CD as an autosuspend blocker, because tray-based SD readers can assert SD_CD with an empty tray. A real SD card is protected by the SD/MMC child runtime-PM usage once powered.
Also stop clearing OCP from the runtime autosuspend callback, so the callback does not issue USB commands.
--- drivers/misc/cardreader/rtsx_usb.c | 23 ++++++++++++++++++++--- include/linux/rtsx_usb.h | 3 +++ 2 files changed, 23 insertions(+), 3 deletions(-)
drivers/misc/cardreader/rtsx_usb.c +20 -3
@@ -312,6 +312,9 @@ int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status)if (ret <0 )return ret; + ucr->card_status_cache = *status; + ucr->card_status_valid = true; +return 0 ; }EXPORT_SYMBOL_GPL (rtsx_usb_get_card_status);
@@ -619,6 +622,7 @@ static int rtsx_usb_probe(struct usb_interface *intf, {struct usb_device *usb_dev =interface_to_usbdev (intf);struct rtsx_ucr *ucr; +u16 status;int ret; dev_dbg(&intf->dev,
@@ -655,6 +659,9 @@ static int rtsx_usb_probe(struct usb_interface *intf,if (ret) goto out_init_fail; +/* Prime cached status for runtime autosuspend decisions. */ +rtsx_usb_get_card_status (ucr, &status); +/* initialize USB SG transfer timer */ timer_setup (&ucr->sg_timer, rtsx_usb_sg_timed_out,0 );
@@ -709,17 +716,27 @@ static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata (intf);u16 val =0 ; +bool valid = false;dev_dbg (&intf->dev,"%s called with pm message 0x%04x\n" , __func__, message.event);if (PMSG_IS_AUTO (message)) {if (mutex_trylock (&ucr->dev_mutex)) { -rtsx_usb_get_card_status (ucr, &val); + valid = ucr->card_status_valid; +if (valid) + val = ucr->card_status_cache;mutex_unlock (&ucr->dev_mutex); -/* Defer the autosuspend if card exists */ -if (val & (SD_CD |MS_CD )) { +/* +* Do not issue USB commands from runtime autosuspend. +* Raw SD_CD is not authoritative on tray-based readers, +* while a real SD card is protected by the SD/MMC child +* runtime-PM reference once the card is powered. Keep +* the historical Memory Stick autosuspend deferral when +* the cached status says MS media is present. +*/ +if (valid && (val &MS_CD )) {device_for_each_child (&intf->dev,NULL , rtsx_usb_resume_child);return -EAGAIN ; }
include/linux/rtsx_usb.h +3 -0
@@ -57,6 +57,9 @@ struct rtsx_ucr {struct timer_list sg_timer;struct mutex dev_mutex; + +u16 card_status_cache; +bool card_status_valid; };/* buffer size */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 511/1376 RDMA/hfi1: Preserve unit 0 on allocation failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 2e3809ad8911f5d5581b3f046bd628417bface76 ]
hfi1_free_devdata() assumes that the device was inserted into the unit table and unconditionally erases dd->unit. If xa_alloc_irq() fails, the zero-initialized unit remains zero, so full cleanup can remove an unrelated device from index 0.
Release only the rdmavt allocation and return immediately while the unit table has not acquired the device.
--- drivers/infiniband/hw/hfi1/init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/infiniband/hw/hfi1/init.c +3 -2
@@ -1227,8 +1227,9 @@ static struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, GFP_KERNEL);if (ret <0 ) {dev_err (&pdev->dev, -"Could not allocate unit ID: error %d\n" , -ret); - goto bail; +"Could not allocate unit ID: error %pe\n" ,ERR_PTR (ret)); +rvt_dealloc_device (&dd->verbs_dev.rdi); +return ERR_PTR (ret); }rvt_set_ibdev_name (&dd->verbs_dev.rdi,"%s_%d" ,class_name (), dd->unit);/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 512/1376 RDMA/hfi1: Free RX data on late probe failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 8e17e101e04a3dc062e2719da57ff78c1c060632 ]
hfi1_init_dd() allocates the shared AIP/VNIC RX support before returning. If hfi1_init() or hfi1_register_ib_device() later fails, init_one() tears down the device data without calling hfi1_free_rx(). This leaks netdev_rx and its dummy netdev.
Free the RX support after IB unregistration and before postinit_cleanup(), as done on normal device removal.
--- drivers/infiniband/hw/hfi1/init.c | 1 + 1 file changed, 1 insertion(+)
drivers/infiniband/hw/hfi1/init.c +1 -0
@@ -1678,6 +1678,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)hfi1_device_remove (dd);if (!ret)hfi1_unregister_ib_device (dd); +hfi1_free_rx (dd);postinit_cleanup (dd);if (initfail) ret = initfail;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 513/1376 RDMA/hfi1: Remove redundant PCI device ID validation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit af9117d02f50514c998714b23820de71d0aa5d24 ]
The PCI core calls init_one() only after pci_match_device() has selected an ID. For normal probing, hfi1_pci_tbl already restricts matches to the two supported Intel device IDs. Dynamic IDs and driver_override are explicit requests to attempt binding, so the probe should not second-guess the PCI core's decision.
Remove the redundant check.
Stable-dep-of: 9f674ba674a0 ("RDMA/hfi1: Allocate device data after PCI initialization")
--- drivers/infiniband/hw/hfi1/init.c | 9 --------- 1 file changed, 9 deletions(-)
drivers/infiniband/hw/hfi1/init.c +0 -9
@@ -1563,15 +1563,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)/* First, lock the non-writable module parameters */ HFI1_CAP_LOCK (); -/* Validate dev ids */ -if (!(ent->device ==PCI_DEVICE_ID_INTEL0 || - ent->device ==PCI_DEVICE_ID_INTEL1 )) { -dev_err (&pdev->dev,"Failing on unknown Intel deviceid 0x%x\n" , - ent->device); - ret = -ENODEV ; - goto bail; - } -/* Allocate the dd so we can get to work */ dd =hfi1_alloc_devdata (pdev,NUM_IB_PORTS *sizeof (struct hfi1_pportdata ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 514/1376 RDMA/hfi1: Create workqueues before device initialization
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 0d5618c1b2fc9dd4fc086f0226acd8a077ab6c1b ]
create_workqueues() only needs fields set up by hfi1_alloc_devdata(). Call it before hfi1_init_dd() so a workqueue allocation failure happens before chip resources are initialized.
To keep the reordered error paths safe, make init_one() own hfi1_devdata. hfi1_init_dd() unwinds its partial setup but leaves the allocation for the caller to free. If device initialization fails, destroy the workqueues before freeing the device data.
Stable-dep-of: 9f674ba674a0 ("RDMA/hfi1: Allocate device data after PCI initialization")
--- drivers/infiniband/hw/hfi1/chip.c | 4 +--- drivers/infiniband/hw/hfi1/hfi.h | 2 -- drivers/infiniband/hw/hfi1/init.c | 19 ++++++++++--------- 3 files changed, 11 insertions(+), 14 deletions(-)
drivers/infiniband/hw/hfi1/chip.c +1 -3
@@ -15065,7 +15065,7 @@ int hfi1_init_dd(struct hfi1_devdata *dd)*/ ret =hfi1_pcie_ddinit (dd, pdev);if (ret <0 ) - goto bail_free; + goto bail;/* Save PCI space registers to rewrite after device reset */ ret =save_pci_variables (dd);
@@ -15320,8 +15320,6 @@ int hfi1_init_dd(struct hfi1_devdata *dd) bail_cleanup:hfi1_free_rx (dd);hfi1_pcie_ddcleanup (dd); -bail_free: -hfi1_free_devdata (dd); bail:return ret; }
drivers/infiniband/hw/hfi1/hfi.h +0 -2
@@ -2044,9 +2044,7 @@ struct cc_state *get_cc_state_protected(struct hfi1_pportdata *ppd)/* waiting for an urgent packet to arrive */ #define HFI1_CTXT_WAITING_URG 4 -/* free up any allocated data at closes */ int hfi1_init_dd (struct hfi1_devdata *dd); -void hfi1_free_devdata (struct hfi1_devdata *dd);/* LED beaconing functions */ void hfi1_start_led_override(struct hfi1_pportdata *ppd, unsigned int timeon,
drivers/infiniband/hw/hfi1/init.c +10 -9
@@ -630,8 +630,6 @@ void hfi1_init_pportdata(struct pci_dev *pdev, struct hfi1_pportdata *ppd, ppd->sm_trap_qp =0x0 ; ppd->sa_qp =0x1 ; - ppd->hfi1_wq =NULL ; -spin_lock_init (&ppd->cca_timer_lock);for (i =0 ; i <OPA_MAX_SLS ; i++) {
@@ -1164,7 +1162,7 @@ static void finalize_asic_data(struct hfi1_devdata *dd,* It cleans up and frees all data structures set up by * by hfi1_alloc_devdata(). */ -void hfi1_free_devdata (struct hfi1_devdata *dd) +static void hfi1_free_devdata (struct hfi1_devdata *dd) {struct hfi1_asic_data *ad;unsigned long flags;
@@ -1616,17 +1614,17 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)if (ret) goto bail; + ret =create_workqueues (dd); +if (ret) + goto free_devdata; +/* * Do device-specific initialization, function table setup, dd * allocation, etc. */ ret =hfi1_init_dd (dd);if (ret) - goto clean_bail;/* error already printed */ - - ret =create_workqueues (dd); -if (ret) - goto clean_bail; + goto destroy_workqueues;/* error already printed */ /* do the generic initialization */ initfail =hfi1_init (dd,0 );
@@ -1680,7 +1678,10 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)return 0 ; -clean_bail: +destroy_workqueues: +destroy_workqueues (dd); +free_devdata: +hfi1_free_devdata (dd);hfi1_pcie_cleanup (pdev); bail:return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 515/1376 RDMA/hfi1: Stop flushing the global IB workqueue
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit d43b1c17f9e1b9d34a0d742f569c00d84147ebc0 ]
hfi1 does not queue work on ib_wq. QSFP and link work run on the per-port link_wq, while the remaining device work uses hfi1_wq or dedicated queues. The probe failure path destroys both per-port workqueues, and normal device removal flushes them in shutdown_device() before destroying them.
Remove the flushes of the core-owned global workqueue. Waiting for unrelated core or other device work is not part of hfi1 teardown.
--- drivers/infiniband/hw/hfi1/init.c | 4 ---- 1 file changed, 4 deletions(-)
drivers/infiniband/hw/hfi1/init.c +0 -4
@@ -1650,7 +1650,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)if (initfail || ret) {msix_clean_up_interrupts (dd);stop_timers (dd); -flush_workqueue (ib_wq);for (pidx =0 ; pidx < dd->num_pports; ++pidx) {hfi1_quiet_serdes (dd->pport + pidx); ppd = dd->pport + pidx;
@@ -1727,9 +1726,6 @@ static void remove_one(struct pci_dev *pdev)stop_timers (dd); -/* wait until all of our (qsfp) queue_work() calls complete */ -flush_workqueue (ib_wq); -postinit_cleanup (dd); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 516/1376 RDMA/hfi1: Initialize debugfs after probe completes
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit bb18740b302f6f222ce3d5a7e5c45a52a90df805 ]
Commit ed6f653fe430 ("staging/rdma/hfi1: Fix debugfs access race") moved debugfs creation after device initialization and IB registration so users cannot access the files before the driver is ready. However, init_one() still creates them before character device creation and SDMA startup finish.
Move hfi1_dbg_ibdev_init() to the end of the successful probe path, matching hfi1_dbg_ibdev_exit() as the first action in remove_one().
--- drivers/infiniband/hw/hfi1/init.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/infiniband/hw/hfi1/init.c +2 -4
@@ -1637,11 +1637,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)* we still create devices, so diags, etc. can be used * to determine cause of problem. */ -if (!initfail && !ret) { +if (!initfail && !ret) dd->flags |=HFI1_INITTED ; -/* create debufs files after init and ib register */ -hfi1_dbg_ibdev_init (&dd->verbs_dev); - } j =hfi1_device_create (dd);if (j)
@@ -1674,6 +1671,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) }sdma_start (dd); +hfi1_dbg_ibdev_init (&dd->verbs_dev);return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 517/1376 ASoC: apple: mca: increase SERDES reset delay
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Calligeros <[email protected]>
[ Upstream commit cccd721e5aab03e92234faee72b363c9ba60611c ]
The SERDES clusters in this peripheral take a long time to warm up. We tried polling the reset bit until cleared, however this is not a reliable signal of readiness to be configured. Only waiting ~25 us to give the cluster a chance to settle makes it work reliably.
Increase the 2 us delay to 25 us and hope we never have to do this again.
--- sound/soc/apple/mca.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
sound/soc/apple/mca.c +3 -3
@@ -210,10 +210,10 @@ static void mca_fe_early_trigger(struct snd_pcm_substream *substream, int cmd,SERDES_STATUS_EN |SERDES_STATUS_RST , SERDES_STATUS_RST);/* -* Experiments suggest that it takes at most ~1 us -* for the bit to clear, so wait 2 us for good measure. +* The SERDES cluster needs a bit of time to reset itself +* and settle before we start poking it. This is... slow... */ -udelay (2 ); +udelay (25 );WARN_ON (readl_relaxed (cl->base + serdes_unit +REG_SERDES_STATUS ) &SERDES_STATUS_RST ); mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 518/1376 isofs: fix out-of-bounds page array access on empty zisofs block
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit 68d4d3e78150c7ed7d1195af63ad1e6ace30c661 ]
zisofs_uncompress_block()'s empty-block fast path returns pcount << PAGE_SHIFT, ignoring the incoming poffset, unlike the decompression path which returns bytes produced relative to poffset. zisofs_fill_pages() uses that return to advance its page cursor, so when the zisofs block size is below PAGE_SIZE and a sub-page block leaves poffset partway into a page, a following empty block over-counts and advances pages[] one element past its end, after which
"if (poffset && *pages)" reads pages[1] out of bounds. rock.c only rejects a block-size shift > 17, so a crafted "ZF" Rock Ridge record can set it below PAGE_SHIFT; the bug is reached by an ordinary read() of a compressed file on such a mounted ISO9660 image.
Return the byte count relative to poffset and zero only [poffset, PAGE_SIZE) of the first page, matching the decompression path. The page-aligned case (poffset == 0) is unaffected.
BUG: KASAN: slab-out-of-bounds in zisofs_read_folio (fs/isofs/compress.c:290) Read of size 8 at addr ffff88800f5eac48 by task exploit/142 zisofs_read_folio (fs/isofs/compress.c:290) read_pages (mm/readahead.c:184) ... filemap_read (mm/filemap.c:2814) vfs_read (fs/read_write.c:574) __x64_sys_pread64 (fs/read_write.c:769) do_syscall_64 (arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) The buggy address is located 0 bytes to the right of the allocated 8-byte region in the kmalloc-8 cache
--- fs/isofs/compress.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
fs/isofs/compress.c +4 -2
@@ -65,12 +65,14 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,/* Empty block? */ if (block_size ==0 ) {for ( i =0 ; i < pcount ; i++ ) { +unsigned int off = i ?0 : poffset; +if (!pages[i])continue ; -memzero_page (pages[i],0 ,PAGE_SIZE ); +memzero_page (pages[i], off,PAGE_SIZE - off);SetPageUptodate (pages[i]); } -return ((loff_t )pcount) <<PAGE_SHIFT ; +return (((loff_t )pcount) <<PAGE_SHIFT ) - poffset; }/* Because zlib is not thread-safe, do all the I/O at the top. */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 519/1376 iommufd/selftest: Avoid selftest dirty bitmap size wrap
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samuel Moelius <[email protected]>
[ Upstream commit 4132ba2ae2cf14c289e3fabc1c95ac244d643356 ]
IOMMU_TEST_OP_DIRTY sizes its temporary dirty bitmap from length / page_size. Very large selftest ranges can make the DIV_ROUND_UP() additions wrap before allocation, producing a zero-length allocation while the later test_bit() loop still walks the original number of bits.
The selftest helper does not need to support unbounded dirty bitmap sizes. Reject requests that would allocate more than SZ_16M for the temporary buffer.
--- drivers/iommu/iommufd/selftest.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/iommu/iommufd/selftest.c +4 -1
@@ -10,6 +10,7 @@#include <linux/iommu.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/sizes.h> #include <linux/xarray.h> #include <uapi/linux/iommufd.h>
@@ -1359,6 +1360,9 @@ static int iommufd_test_dirty(struct iommufd_ucmd *ucmd, unsigned int mockpt_id,if (!page_size || !length || iova % page_size || length % page_size || !uptr)return -EINVAL ; + max = length / page_size; +if (max >SZ_16M *BITS_PER_BYTE ) +return -EOVERFLOW ; hwpt =get_md_pagetable (ucmd, mockpt_id, &mock);if (IS_ERR (hwpt))
@@ -1369,7 +1373,6 @@ static int iommufd_test_dirty(struct iommufd_ucmd *ucmd, unsigned int mockpt_id, goto out_put; } - max = length / page_size; tmp =kvzalloc (DIV_ROUND_UP (max,BITS_PER_LONG ) *sizeof (unsigned long ),GFP_KERNEL_ACCOUNT );if (!tmp) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 520/1376 media: v4l2-async: Unregister sub-device if asc_list is empty
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil <[email protected]>
[ Upstream commit 4e72f13d58c4245c177a9d5f54579345554f354d ]
When my em28xx USB device that uses the i2c tvp5150 driver is disconnected, it crashes.
The cause is that the tvp5150 i2c module uses v4l2_async, but the em28xx driver does not since it predates v4l2_async.
In that corner case sd->asc_list is empty, so v4l2_async_unregister_subdev() never calls v4l2_device_unregister_subdev().
Modify the code so that, if sd->asc_list is empty, v4l2_device_unregister_subdev() is still called.
--- drivers/media/v4l2-core/v4l2-async.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/media/v4l2-core/v4l2-async.c +12 -3
@@ -897,9 +897,18 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) sd->subdev_notifier =NULL ;if (sd->asc_list.next) { -list_for_each_entry_safe (asc, asc_tmp, &sd->asc_list, - asc_subdev_entry) { -v4l2_async_unbind_subdev_one (asc->notifier, asc); +if (list_empty (&sd->asc_list)) { +/* +* If the sub-device was registered through other means +* than v4l2-async, there are no async connections but +* the sub-device may still well be registered. +* Unregister it now. +*/ +v4l2_device_unregister_subdev (sd); + }else { +list_for_each_entry_safe (asc, asc_tmp, &sd->asc_list, + asc_subdev_entry) +v4l2_async_unbind_subdev_one (asc->notifier, asc); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 521/1376 rpmsg: glink: remove duplicate code for rpmsg device remove
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivas Kandagatla <[email protected]>
[ Upstream commit 112766cdf2e5ea0a0f72b0304d57a6f74c066670 ]
rpmsg device remove code is duplicated in at-least 2-3 places, add a helper function to remove this duplicated code.
Stable-dep-of: 5a5a48e788e0 ("rpmsg: glink: fix deadlock in endpoint destroy during driver detach")
--- drivers/rpmsg/qcom_glink_native.c | 43 ++++++++++++------------------- 1 file changed, 16 insertions(+), 27 deletions(-)
drivers/rpmsg/qcom_glink_native.c +16 -27
@@ -1395,11 +1395,23 @@ static int qcom_glink_announce_create(struct rpmsg_device *rpdev)return 0 ; } +static void qcom_glink_remove_rpmsg_device (struct qcom_glink *glink,struct glink_channel *channel) +{ +struct rpmsg_channel_info chinfo; + +if (channel->rpdev) { +strscpy_pad (chinfo.name, channel->name,sizeof (chinfo.name)); + chinfo.src =RPMSG_ADDR_ANY ; + chinfo.dst =RPMSG_ADDR_ANY ; +rpmsg_unregister_device (glink->dev, &chinfo); + } + channel->rpdev =NULL ; +} +static void qcom_glink_destroy_ept (struct rpmsg_endpoint *ept) {struct glink_channel *channel =to_glink_channel (ept);struct qcom_glink *glink = channel->glink; -struct rpmsg_channel_info chinfo;unsigned long flags;spin_lock_irqsave (&channel->recv_lock, flags);
@@ -1407,14 +1419,7 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept)spin_unlock_irqrestore (&channel->recv_lock, flags);/* Decouple the potential rpdev from the channel */ -if (channel->rpdev) { -strscpy_pad (chinfo.name, channel->name,sizeof (chinfo.name)); - chinfo.src =RPMSG_ADDR_ANY ; - chinfo.dst =RPMSG_ADDR_ANY ; - -rpmsg_unregister_device (glink->dev, &chinfo); - } - channel->rpdev =NULL ; +qcom_glink_remove_rpmsg_device (glink, channel);qcom_glink_send_close_req (glink, channel); }
@@ -1704,7 +1709,6 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid,static void qcom_glink_rx_close (struct qcom_glink *glink,unsigned int rcid) { -struct rpmsg_channel_info chinfo;struct glink_channel *channel;unsigned long flags;
@@ -1720,14 +1724,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid)/* cancel pending rx_done work */ cancel_work_sync (&channel->intent_work); -if (channel->rpdev) { -strscpy_pad (chinfo.name, channel->name,sizeof (chinfo.name)); - chinfo.src =RPMSG_ADDR_ANY ; - chinfo.dst =RPMSG_ADDR_ANY ; - -rpmsg_unregister_device (glink->dev, &chinfo); - } - channel->rpdev =NULL ; +qcom_glink_remove_rpmsg_device (glink, channel);qcom_glink_send_close_ack (glink, channel);
@@ -1741,7 +1738,6 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid)static void qcom_glink_rx_close_ack (struct qcom_glink *glink,unsigned int lcid) { -struct rpmsg_channel_info chinfo;struct glink_channel *channel;unsigned long flags;
@@ -1763,14 +1759,7 @@ static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid)spin_unlock_irqrestore (&glink->idr_lock, flags);/* Decouple the potential rpdev from the channel */ -if (channel->rpdev) { -strscpy (chinfo.name, channel->name,sizeof (chinfo.name)); - chinfo.src =RPMSG_ADDR_ANY ; - chinfo.dst =RPMSG_ADDR_ANY ; - -rpmsg_unregister_device (glink->dev, &chinfo); - } - channel->rpdev =NULL ; +qcom_glink_remove_rpmsg_device (glink, channel);kref_put (&channel->refcount, qcom_glink_channel_release); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 522/1376 rpmsg: glink: fix deadlock in endpoint destroy during driver detach
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vishnu Santhosh <[email protected]>
[ Upstream commit 5a5a48e788e02fd8a8eb7188ce440572d6c12418 ]
During driver detach, the device core holds the device mutex throughout the driver's remove callback chain. When the rpmsg endpoint is destroyed as part of that teardown, the GLINK endpoint destroy implementation attempts to unregister the underlying rpmsg device. That unregistration calls device_del(), which tries to re-acquire the same device mutex already held higher up the stack, causing rmmod to hang indefinitely.
The deadlock manifests with the following call chain:
[<0>] device_del+0x44/0x414 <- tries to acquire same mutex [<0>] device_unregister+0x18/0x34 [<0>] rpmsg_unregister_device+0x28/0x4c [<0>] qcom_glink_remove_rpmsg_device+0x70/0xc0 [<0>] qcom_glink_destroy_ept+0x58/0xbc [<0>] rpmsg_dev_remove+0x50/0x60 [<0>] device_remove+0x4c/0x80 [<0>] device_release_driver_internal+0x1cc/0x228 <- acquires device mutex [<0>] driver_detach+0x4c/0x98 [<0>] bus_remove_driver+0x6c/0xbc [<0>] driver_unregister+0x30/0x60 [<0>] unregister_rpmsg_driver+0x10/0x1c [<0>] fastrpc_exit+0x28/0x38 [fastrpc] [<0>] __arm64_sys_delete_module+0x1b8/0x294 [<0>] invoke_syscall+0x48/0x10c [<0>] el0_svc_common.constprop.0+0xc0/0xe0 [<0>] do_el0_svc+0x1c/0x28 [<0>] el0_svc+0x34/0x108 [<0>] el0t_64_sync_handler+0xa0/0xe4 [<0>] el0t_64_sync+0x198/0x19c
The rpmsg device unregistration inside endpoint destroy is redundant. In both contexts where endpoint destruction is triggered:
- Driver detach path: the driver core already tears down the rpmsg device.
- Channel close path: the rpmsg device is already unregistered before endpoint destruction is reached.
Remove the redundant unregistration to fix the deadlock.
--- drivers/rpmsg/qcom_glink_native.c | 3 --- 1 file changed, 3 deletions(-)
drivers/rpmsg/qcom_glink_native.c +0 -3
@@ -1418,9 +1418,6 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept) channel->ept.cb =NULL ;spin_unlock_irqrestore (&channel->recv_lock, flags); -/* Decouple the potential rpdev from the channel */ -qcom_glink_remove_rpmsg_device (glink, channel); -qcom_glink_send_close_req (glink, channel); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 523/1376 cxl/memdev: Fix firmware upload exact-fit handling
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guzebing <[email protected]>
[ Upstream commit af5035e1b3e400067bb003975936e5407377e7a3 ]
cxl_fw_prepare() classifies a firmware image as a one-shot transfer only when its Transfer FW input payload is smaller than the mailbox payload size. An image that exactly fills the payload is therefore treated as a multi-part transfer.
The firmware loader invokes cxl_fw_write() only once for that image. Since both offset == 0 and remaining == 0, the multi-part action selection sends INITIATE, never sends END, and then attempts to activate the target slot.
Include equality in the one-shot classification so exact-fit images use the FULL action.
--- drivers/cxl/core/memdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/cxl/core/memdev.c +1 -1
@@ -845,7 +845,7 @@ static enum fw_upload_err cxl_fw_prepare(struct fw_upload *fwl, const u8 *data,if (!size)return FW_UPLOAD_ERR_INVALID_SIZE ; - mds->fw.oneshot =struct_size (transfer, data, size) < + mds->fw.oneshot =struct_size (transfer, data, size) <= cxl_mbox->payload_size;if (cxl_mem_get_fw_info (mds))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 524/1376 cxl/mbox: Break poison list loop on an empty payload
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Jiang <[email protected]>
[ Upstream commit 8b301c4afbce4bc3f94528441d8d5ce1366504ad ]
A device that returns count == 0 with CXL_POISON_FLAG_MORE set on every iteration never advances nr_records, so the max_errors guard never trips and the do/while loops forever while holding poison.mutex. That hangs the sysfs-triggered scan thread and blocks all subsequent poison operations on the device. The existing "Protect against an uncleared _FLAG_MORE" guard was intended to bound a misbehaving device but does not cover the count == 0 case.
Stop the loop on an empty payload so a malfunctioning or malicious device cannot wedge the poison scan.
--- drivers/cxl/core/mbox.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/cxl/core/mbox.c +5 -0
@@ -1358,6 +1358,11 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,if (rc)break ; +if (!le16_to_cpu (po->count)) { +dev_dbg (&cxlmd->dev,"Poison empty payload!\n" ); +break ; + } +for (int i =0 ; i <le16_to_cpu (po->count); i++) trace_cxl_poison(cxlmd, cxlr, &po->record[i], po->flags, po->overflow_ts,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 525/1376 cxl/pci: Honor -EPROBE_DEFER from component register setup
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Jiang <[email protected]>
[ Upstream commit 430c502c80e542e77bcf97db13ec0e8cdf9addb0 ]
cxl_pci_setup_regs() for CXL_REGLOC_RBI_COMPONENT can return -EPROBE_DEFER on a Restricted CXL Host (RCD) when the upstream port has not yet been enumerated and the Component Registers must be extracted from the RCRB. cxl_pci_probe() treats every non-zero return from that call as the benign "component registers not found" case, logs a warning, and continues. The rc is then immediately overwritten by the subsequent cxl_pci_type3_init_mailbox() call, so the deferral is silently swallowed.
Return -EPROBE_DEFER instead of continuing so the probe is retried once the upstream port is available.
--- drivers/cxl/pci.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/cxl/pci.c +5 -2
@@ -851,10 +851,13 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)*/ rc =cxl_pci_setup_regs (pdev,CXL_REGLOC_RBI_COMPONENT , &cxlds->reg_map); -if (rc) +if (rc) { +if (rc == -EPROBE_DEFER ) +return rc;dev_warn (&pdev->dev,"No component registers (%d)\n" , rc); -else if (!cxlds->reg_map.component_map.ras.valid) + }else if (!cxlds->reg_map.component_map.ras.valid) {dev_dbg (&pdev->dev,"RAS registers not found\n" ); + } rc =cxl_map_component_regs (&cxlds->reg_map, &cxlds->regs.component,BIT (CXL_CM_CAP_CAP_ID_RAS ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 526/1376 fs/ntfs3: Add more checks in mi_enum_attr (part 2)
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konstantin Komarov <[email protected]>
[ Upstream commit a8f659ce14f8f734894227ba2c5ca78c8451501e ]
Add offset check before access to attr->non_res field as mentioned in [1].
[1] https://lore.kernel.org/ntfs3/[email protected]/
Stable-dep-of: 7c4841e2a627 ("fs/ntfs3: fix slab-out-of-bounds write in ni_create_attr_list()")
--- fs/ntfs3/record.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
fs/ntfs3/record.c +13 -3
@@ -212,7 +212,7 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)return NULL ;if (off >= used || off <MFTRECORD_FIXUP_OFFSET_1 || - !IS_ALIGNED (off,4 )) { + !IS_ALIGNED (off,8 )) {return NULL ; }
@@ -236,8 +236,11 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr) off += asize; } -/* Can we use the first field (attr->type). */ -/* NOTE: this code also checks attr->size availability. */ +/* +* Can we use the first fields: +* attr->type, +* attr->size +*/ if (off +8 > used) {static_assert (ALIGN (sizeof (enum ATTR_TYPE ),8 ) ==8 );return NULL ;
@@ -259,10 +262,17 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr) asize =le32_to_cpu (attr->size); +if (!IS_ALIGNED (asize,8 )) +return NULL ; +/* Check overflow and boundary. */ if (off + asize < off || off + asize > used)return NULL ; +/* Can we use the field attr->non_res. */ +if (off +9 > used) +return NULL ; +/* Check size of attribute. */ if (!attr->non_res) {/* Check resident fields. */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 527/1376 fs/ntfs3: Mark inode as bad as soon as error detected in mi_enum_attr()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konstantin Komarov <[email protected]>
[ Upstream commit 2afd4d267e6dbaec8d3ccd4f5396cb84bc67aa2e ]
Extended the mi_enum_attr() function interface with an additional parameter, struct ntfs_inode *ni, to allow marking the inode as bad as soon as an error is detected.
Stable-dep-of: 7c4841e2a627 ("fs/ntfs3: fix slab-out-of-bounds write in ni_create_attr_list()")
--- fs/ntfs3/attrib.c | 11 ++++--- fs/ntfs3/frecord.c | 59 ++++++++++++++++++---------------- fs/ntfs3/ntfs_fs.h | 21 ++++++------ fs/ntfs3/record.c | 79 ++++++++++++++++++++++++---------------------- 4 files changed, 90 insertions(+), 80 deletions(-)
fs/ntfs3/attrib.c +6 -5
@@ -789,7 +789,8 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type,if (err) goto out; - attr =mi_find_attr (mi,NULL , type, name, name_len, &le->id); + attr =mi_find_attr (ni, mi,NULL , type, name, name_len, + &le->id);if (!attr) { err = -EINVAL ; goto bad_inode;
@@ -1197,7 +1198,7 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn, goto out; } - attr =mi_find_attr (mi,NULL ,ATTR_DATA ,NULL ,0 , &le->id); + attr =mi_find_attr (ni, mi,NULL ,ATTR_DATA ,NULL ,0 , &le->id);if (!attr) { err = -EINVAL ; goto out;
@@ -1821,7 +1822,7 @@ int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size, goto out; } - attr =mi_find_attr (mi,NULL ,ATTR_DATA ,NULL ,0 , + attr =mi_find_attr (ni, mi,NULL ,ATTR_DATA ,NULL ,0 , &le->id);if (!attr) { err = -EINVAL ;
@@ -2066,8 +2067,8 @@ int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) }/* Look for required attribute. */ - attr =mi_find_attr (mi,NULL ,ATTR_DATA ,NULL , -0 , &le->id); + attr =mi_find_attr (ni, mi,NULL ,ATTR_DATA , +NULL ,0 , &le->id);if (!attr) { err = -EINVAL ; goto out;
fs/ntfs3/frecord.c +31 -28
226 lines not on this page · raw message
fs/ntfs3/ntfs_fs.h +11 -10
@@ -746,23 +746,24 @@ int mi_get(struct ntfs_sb_info *sbi, CLST rno, struct mft_inode **mi);void mi_put (struct mft_inode *mi);int mi_init (struct mft_inode *mi,struct ntfs_sb_info *sbi,CLST rno);int mi_read (struct mft_inode *mi,bool is_mft); -struct ATTRIB *mi_enum_attr (struct mft_inode *mi,struct ATTRIB *attr); -// TODO: id? -struct ATTRIB *mi_find_attr (struct mft_inode *mi,struct ATTRIB *attr, -enum ATTR_TYPE type,const __le16 *name, -u8 name_len,const __le16 *id); -static inline struct ATTRIB *rec_find_attr_le (struct mft_inode *rec, +struct ATTRIB *mi_enum_attr (struct ntfs_inode *ni,struct mft_inode *mi, +struct ATTRIB *attr); +struct ATTRIB *mi_find_attr (struct ntfs_inode *ni,struct mft_inode *mi, +struct ATTRIB *attr,enum ATTR_TYPE type, +const __le16 *name,u8 name_len,const __le16 *id); +static inline struct ATTRIB *rec_find_attr_le (struct ntfs_inode *ni, +struct mft_inode *rec,struct ATTR_LIST_ENTRY *le) { -return mi_find_attr (rec,NULL , le->type,le_name (le), le->name_len, +return mi_find_attr (ni, rec,NULL , le->type,le_name (le), le->name_len, &le->id); }int mi_write (struct mft_inode *mi,int wait);int mi_format_new (struct mft_inode *mi,struct ntfs_sb_info *sbi,CLST rno,__le16 flags,bool is_mft); -struct ATTRIB *mi_insert_attr (struct mft_inode *mi,enum ATTR_TYPE type, -const __le16 *name,u8 name_len,u32 asize, -u16 name_off); +struct ATTRIB *mi_insert_attr (struct ntfs_inode *ni,struct mft_inode *mi, +enum ATTR_TYPE type,const __le16 *name, +u8 name_len,u32 asize,u16 name_off);bool mi_remove_attr (struct ntfs_inode *ni,struct mft_inode *mi,struct ATTRIB *attr);
fs/ntfs3/record.c +42 -37
216 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 528/1376 fs/ntfs3: fix KMSAN uninit-value in ni_create_attr_list
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nirbhay Sharma <[email protected]>
[ Upstream commit 5f33da04e6ceee849e76e6592cc283c72fef7af9 ]
The call to kmalloc() to allocate the attribute list buffer is given a size of al_aligned(rs). This size can be larger than the data subsequently copied into the buffer, leaving trailing bytes uninitialized.
This can trigger a KMSAN "uninit-value" warning if that memory is later accessed.
Fix this by using kzalloc() instead, which ensures the entire allocated buffer is zero-initialized, preventing the warning.
Stable-dep-of: 7c4841e2a627 ("fs/ntfs3: fix slab-out-of-bounds write in ni_create_attr_list()")
--- fs/ntfs3/frecord.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ntfs3/frecord.c +1 -1
@@ -826,7 +826,7 @@ int ni_create_attr_list(struct ntfs_inode *ni)* Skip estimating exact memory requirement. * Looks like one record_size is always enough. */ - le =kmalloc (al_aligned (rs),GFP_NOFS ); + le =kzalloc (al_aligned (rs),GFP_NOFS );if (!le)return -ENOMEM ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 529/1376 fs/ntfs3: fix slab-out-of-bounds write in ni_create_attr_list()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: HE WEI(ギカク) <[email protected]>
[ Upstream commit 7c4841e2a62794a3bab7c1ff0540580f387e377f ]
ni_create_attr_list() allocates a fixed buffer of al_aligned(record_size) (== record_size) bytes and then walks every attribute of the primary MFT record, writing one ATTR_LIST_ENTRY per attribute and advancing the cursor by le_size(name_len), with no check against the end of the buffer; the total size is only computed after the loop.
A minimum-size resident attribute occupies SIZEOF_RESIDENT (0x18 = 24) bytes on disk, but an unnamed attribute expands to le_size(0) (0x20 = 32) bytes in the list. Because the number of attributes in a record is not bounded (mi_enum_attr() accepts arbitrarily many equal-type, nameless minimum-size attributes), a crafted record packed with such attributes produces a list larger than record_size and overflows the heap buffer.
This is reachable from a crafted, loop-mounted NTFS image: opening the file and adding an attribute (e.g. via setxattr) drives ntfs_set_ea() -> ni_insert_resident() -> ni_insert_attr() -> ni_ins_attr_ext() -> ni_create_attr_list().
BUG: KASAN: slab-out-of-bounds in ni_create_attr_list+0xc48/0x1058 Write of size 4 at addr ffff000008984c00 by task setfattr/345 ni_create_attr_list+0xc48/0x1058 ni_ins_attr_ext+0x510/0x7c0 ni_insert_attr+0x3f8/0x70c ni_insert_resident+0xc8/0x3b0 ntfs_set_ea+0x66c/0xd28 ntfs_setxattr+0x4d8/0x5b0 __arm64_sys_setxattr+0xa4/0x124 Allocated by task 345: ni_create_attr_list+0x188/0x1058 The buggy address belongs to the cache kmalloc-1k of size 1024 (the write lands at object+1024).
Size the buffer from the actual attributes instead of assuming a single record_size is always enough.
--- fs/ntfs3/frecord.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-)
fs/ntfs3/frecord.c +16 -4
@@ -823,10 +823,23 @@ int ni_create_attr_list(struct ntfs_inode *ni) rs = sbi->record_size;/* -* Skip estimating exact memory requirement. -* Looks like one record_size is always enough. +* Compute the exact size of the attribute list. Each attribute in the +* record yields one ATTR_LIST_ENTRY of le_size(name_len) bytes. The +* minimum on-disk attribute is SIZEOF_RESIDENT (0x18) bytes, but an +* unnamed one expands to le_size(0) (0x20) here, so a record crafted +* with many such attributes needs more than a single record_size; the +* previous fixed kzalloc(record_size) could therefore be overflowed by +* an attacker-controlled record. */ - le =kzalloc (al_aligned (rs),GFP_NOFS ); + lsize =0 ; + attr =NULL ; +while ((attr =mi_enum_attr (ni, &ni->mi, attr))) + lsize +=le_size (attr->name_len); + +if (!lsize) +return -EINVAL ; + + le =kzalloc (al_aligned (lsize),GFP_NOFS );if (!le)return -ENOMEM ;
@@ -836,7 +849,6 @@ int ni_create_attr_list(struct ntfs_inode *ni) attr =NULL ; nb =0 ; free_b =0 ; - attr =NULL ;for (; (attr =mi_enum_attr (ni, &ni->mi, attr)); le =Add2Ptr (le, sz)) { sz =le_size (attr->name_len);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 530/1376 hfsplus: validate thread record before delete key rebuild
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyle Zeng <[email protected]>
[ Upstream commit e2ea5cac61acfc11dad22f1d2d4bc71d56c52a20 ]
hfsplus_delete_cat() is called with str == NULL when the last open reference to an unlinked HFS+ hardlink backing inode is closed. In that case, the function finds the catalog thread by CNID and rebuilds the catalog key from thread.nodeName.
That reconstruction path reads thread.nodeName.length directly from the catalog B-tree into fd.search_key and then copies length * 2 bytes into fd.search_key->cat.name.unicode. It does not first check that the found record is a thread record or that its size matches the thread name.
A corrupted image can therefore provide an oversized thread name length and make hfs_bnode_read() write past the catalog search-key allocation.
Read the CNID record through hfsplus_brec_read_cat(), which bounds the record read to sizeof(hfsplus_cat_entry) and verifies that a thread record's size exactly matches nodeName.length. Together, these checks ensure an accepted thread name fits HFSPLUS_MAX_STRLEN. Reject non-thread records before building the delete key from the validated thread name.
Share the thread-record-type helper between hfsplus_find_cat() and hfsplus_delete_cat().
--- fs/hfsplus/catalog.c | 25 ++++++++++++------------- fs/hfsplus/hfsplus_fs.h | 6 ++++++ 2 files changed, 18 insertions(+), 13 deletions(-)
fs/hfsplus/catalog.c +12 -13
@@ -204,7 +204,7 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,return err; type =be16_to_cpu (tmp.type); -if (type !=HFSPLUS_FOLDER_THREAD && type !=HFSPLUS_FILE_THREAD ) { +if (!is_hfs_thread_record_type (type)) {pr_err ("found bad thread record in catalog\n" );return -EIO ; }
@@ -350,23 +350,22 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, const struct qstr *str) goto out;if (!str) { -int len; +hfsplus_cat_entry entry = {0 };hfsplus_cat_build_key_with_cnid (sb, fd.search_key, cnid); - err =hfs_brec_find (&fd, hfs_find_rec_by_key); + err =hfsplus_brec_read_cat (&fd, &entry);if (err) goto out; - off = fd.entryoffset + - offsetof(struct hfsplus_cat_thread , nodeName); - fd.search_key->cat.parent =cpu_to_be32 (dir->i_ino); -hfs_bnode_read (fd.bnode, - &fd.search_key->cat.name.length, off,2 ); - len =be16_to_cpu (fd.search_key->cat.name.length) *2 ; -hfs_bnode_read (fd.bnode, - &fd.search_key->cat.name.unicode, - off +2 , len); - fd.search_key->key_len =cpu_to_be16 (6 + len); + type =be16_to_cpu (entry.type); +if (!is_hfs_thread_record_type (type)) { +pr_err ("found bad thread record in catalog\n" ); + err = -EIO ; + goto out; + } + +hfsplus_cat_build_key_uni (fd.search_key, dir->i_ino, + &entry.thread.nodeName); }else { err =hfsplus_cat_build_key (sb, fd.search_key, dir->i_ino, str);if (unlikely (err))
fs/hfsplus/hfsplus_fs.h +6 -0
@@ -543,6 +543,12 @@ static inline u32 hfsplus_cat_thread_size(const struct hfsplus_cat_thread *threabe16_to_cpu (thread->nodeName.length) *sizeof (hfsplus_unichr); } +static inline +bool is_hfs_thread_record_type (u16 type) +{ +return type ==HFSPLUS_FOLDER_THREAD || type ==HFSPLUS_FILE_THREAD ; +} +int hfsplus_brec_read_cat (struct hfs_find_data *fd,hfsplus_cat_entry *entry);/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 531/1376 wifi: ath11k: cap out-of-range rx MCS instead of leaving bogus rate
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baochen Qiang <[email protected]>
[ Upstream commit 12b09e478aa7459b7893a695ef77682202f2da83 ]
ath11k can receive HT/VHT/HE frames whose reported MCS is above the maximum that can be expressed in the corresponding mac80211 rate space (e.g. an HE frame reported with MCS 12, while HE tops out at MCS 11).
The frame itself is valid and decodes correctly, but for such a frame ath11k_dp_rx_h_rate() leaves rx_status->rate_idx set to the out-of-range value and never assigns rx_status->encoding, so it stays RX_ENC_LEGACY from the ath11k_dp_rx_h_ppdu() initialization. Once that frame reaches mac80211 it trips the rate sanity check and the frame is dropped with a splat:
ath11k_pci 0000:03:00.0: Received with invalid mcs in HE mode 12
WARNING: CPU: 0 PID: 0 at net/mac80211/rx.c:5433 ieee80211_rx_list+0xb0a/0xe90 [mac80211]
Dropping the frame would discard otherwise valid data, so instead cap the reported MCS to the maximum the rate space can express and deliver the frame. Set rx_status->encoding before the range check and assign rate_idx from the capped value, so a frame with an out-of-range MCS no longer leaves partial or bogus rate metadata behind. Also downgrade the logging level since they are not treated as invalid frames now. The only loss is that such a frame is reported as the capped MCS in the rx rate statistics.
Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41
--- drivers/net/wireless/ath/ath11k/dp_rx.c | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-)
drivers/net/wireless/ath/ath11k/dp_rx.c +15 -15
@@ -2332,10 +2332,10 @@ static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc,case RX_MSDU_START_PKT_TYPE_11N : rx_status->encoding =RX_ENC_HT ;if (rate_mcs >ATH11K_HT_MCS_MAX ) { -ath11k_warn (ar->ab, -"Received with invalid mcs in HT mode %d\n" , - rate_mcs); -break ; +ath11k_dbg (ar->ab,ATH11K_DBG_DP_RX , +"Received HT frame with out-of-range mcs %d, capping to %d\n" , + rate_mcs,ATH11K_HT_MCS_MAX ); + rate_mcs =ATH11K_HT_MCS_MAX ; } rx_status->rate_idx = rate_mcs + (8 * (nss -1 ));if (sgi)
@@ -2344,13 +2344,13 @@ static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc,break ;case RX_MSDU_START_PKT_TYPE_11AC : rx_status->encoding =RX_ENC_VHT ; - rx_status->rate_idx = rate_mcs;if (rate_mcs >ATH11K_VHT_MCS_MAX ) { -ath11k_warn (ar->ab, -"Received with invalid mcs in VHT mode %d\n" , - rate_mcs); -break ; +ath11k_dbg (ar->ab,ATH11K_DBG_DP_RX , +"Received VHT frame with out-of-range mcs %d, capping to %d\n" , + rate_mcs,ATH11K_VHT_MCS_MAX ); + rate_mcs =ATH11K_VHT_MCS_MAX ; } + rx_status->rate_idx = rate_mcs; rx_status->nss = nss;if (sgi) rx_status->enc_flags |=RX_ENC_FLAG_SHORT_GI ;
@@ -2360,14 +2360,14 @@ static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc, rx_status->enc_flags |=RX_ENC_FLAG_LDPC ;break ;case RX_MSDU_START_PKT_TYPE_11AX : - rx_status->rate_idx = rate_mcs; + rx_status->encoding =RX_ENC_HE ;if (rate_mcs >ATH11K_HE_MCS_MAX ) { -ath11k_warn (ar->ab, -"Received with invalid mcs in HE mode %d\n" , - rate_mcs); -break ; +ath11k_dbg (ar->ab,ATH11K_DBG_DP_RX , +"Received HE frame with out-of-range mcs %d, capping to %d\n" , + rate_mcs,ATH11K_HE_MCS_MAX ); + rate_mcs =ATH11K_HE_MCS_MAX ; } - rx_status->encoding =RX_ENC_HE ; + rx_status->rate_idx = rate_mcs; rx_status->nss = nss; rx_status->he_gi =ath11k_mac_he_gi_to_nl80211_he_gi (sgi); rx_status->bw =ath11k_mac_bw_to_mac80211_bw (bw);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 532/1376 x86/entry/fred: Encode frame pointer on entry
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Stevens <[email protected]>
[ Upstream commit dab01c597f6bd40e0efe7da967b8374ca1971b79 ]
Add missing ENCODE_FRAME_POINTER macro invocation into FRED_ENTER macro, to prevent the unwinder from encountering a NULL stack frame pointer when CONFIG_UNWINDER_FRAME_POINTER is enabled
--- arch/x86/entry/entry_64_fred.S | 2 ++ 1 file changed, 2 insertions(+)
arch/x86/entry/entry_64_fred.S +2 -0
@@ -6,6 +6,7 @@ #include <linux/export.h> #include <asm/asm.h> +#include <asm/frame.h> #include <asm/fred.h> #include <asm/segment.h>
@@ -18,6 +19,7 @@ UNWIND_HINT_END_OF_STACK ANNOTATE_NOENDBR PUSH_AND_CLEAR_REGS + ENCODE_FRAME_POINTER movq %rsp, %rdi /* %rdi -> pt_regs */ .endm
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 533/1376 firmware: arm_scmi: Publish channel state before callbacks
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit 0314900dcdde044af0208fed212035dbfaa55843 ]
Transport setup can enable callbacks before the setup routine returns. mailbox_chan_setup() registers the mailbox client with mbox_request_channel(), and the mailbox controller startup path can enable interrupt delivery before SCMI mailbox channel state has been published. Similarly, smc_chan_setup() requests the optional A2P completion IRQ before the SMC transport has made its cinfo pointer visible.
If a pending or spurious callback fires in those windows, the transport RX callback can dereference a NULL transport cinfo pointer. Publishing only the transport-private pointer is not sufficient either: an early callback can enter the SCMI core before scmi_chan_setup() has assigned cinfo->handle.
The core derives scmi_info from cinfo->handle in the RX path, so a NULL handle can still fault even when the transport-private cinfo is valid.
Assign cinfo->handle before invoking the transport setup callback. Publish the mailbox and SMC transport-private channel state before requesting the mailbox channels or IRQ, and clear the early-published pointers again on setup failure. Also unwind mailbox setup devres resources on failure so an optional RX setup error that is ignored by the core does not leave stale transport state behind.
--- drivers/firmware/arm_scmi/driver.c | 2 +- drivers/firmware/arm_scmi/transports/mailbox.c | 18 +++++++++++++----- drivers/firmware/arm_scmi/transports/smc.c | 15 +++++++++------ 3 files changed, 23 insertions(+), 12 deletions(-)
drivers/firmware/arm_scmi/driver.c +1 -1
@@ -2657,6 +2657,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node, cinfo->id = prot_id; cinfo->dev = &tdev->dev; + cinfo->handle = &info->handle; ret = info->desc->ops->chan_setup (cinfo, info->dev, tx);if (ret) {of_node_put (of_node);
@@ -2689,7 +2690,6 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node,return ret; } - cinfo->handle = &info->handle;return 0 ; }
drivers/firmware/arm_scmi/transports/mailbox.c +13 -5
@@ -208,13 +208,18 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, cl->tx_block = false; cl->knows_txdone = tx; + cinfo->transport_info = smbox; + smbox->cinfo = cinfo; +mutex_init (&smbox->chan_lock); + smbox->chan =mbox_request_channel (cl, tx ?0 : p2a_chan);if (IS_ERR (smbox->chan)) { ret =PTR_ERR (smbox->chan); + smbox->chan =NULL ;if (ret != -EPROBE_DEFER )dev_err (cdev,"failed to request SCMI %s mailbox\n" , desc); -return ret; + goto err_clear_cinfo; }/* Additional unidirectional channel for TX if needed */
@@ -238,11 +243,14 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, } } - cinfo->transport_info = smbox; - smbox->cinfo = cinfo; -mutex_init (&smbox->chan_lock); -return 0 ; + +err_clear_cinfo: + cinfo->transport_info =NULL ; + smbox->cinfo =NULL ; +devm_iounmap (dev, smbox->shmem); +devm_kfree (dev, smbox); +return ret; }static int mailbox_chan_free (int id,void *p,void *data)
drivers/firmware/arm_scmi/transports/smc.c +9 -6
@@ -169,6 +169,13 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, scmi_info->param_page =SHMEM_PAGE (res.start); scmi_info->param_offset =SHMEM_OFFSET (res.start); } + + scmi_info->func_id = func_id; + scmi_info->cap_id = cap_id; + scmi_info->cinfo = cinfo; +smc_channel_lock_init (scmi_info); + cinfo->transport_info = scmi_info; +/* * If there is an interrupt named "a2p", then the service and * completion of a message is signaled by an interrupt rather than by
@@ -180,18 +187,14 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, IRQF_NO_SUSPEND, dev_name(dev), scmi_info);if (ret) {dev_err (dev,"failed to setup SCMI smc irq\n" ); + cinfo->transport_info =NULL ; + scmi_info->cinfo =NULL ;return ret; } }else { cinfo->no_completion_irq = true; } - scmi_info->func_id = func_id; - scmi_info->cap_id = cap_id; - scmi_info->cinfo = cinfo; -smc_channel_lock_init (scmi_info); - cinfo->transport_info = scmi_info; -return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 534/1376 firmware: arm_scmi: Unregister device notifier before IDR teardown
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit 66a0bbf30cc14140fe13f63cd594a7c1ee352b75 ]
The requested-devices notifier looks up protocol fwnodes from the active_protocols IDR. During remove, unregister the notifier before releasing and destroying active_protocols so no notifier callback can race with the IDR teardown.
Keep the bus notifier registered until after the protocol state is torn down, matching the existing remove ordering for SCMI bus users.
--- drivers/firmware/arm_scmi/driver.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/firmware/arm_scmi/driver.c +3 -2
@@ -3250,6 +3250,9 @@ static void scmi_remove(struct platform_device *pdev)list_del (&info->node);mutex_unlock (&scmi_list_mutex); +blocking_notifier_chain_unregister (&scmi_requested_devices_nh, + &info->dev_req_nb); +scmi_notification_exit (&info->handle);mutex_lock (&info->protocols_mtx);
@@ -3260,8 +3263,6 @@ static void scmi_remove(struct platform_device *pdev)of_node_put (child);idr_destroy (&info->active_protocols); -blocking_notifier_chain_unregister (&scmi_requested_devices_nh, - &info->dev_req_nb);bus_unregister_notifier (&scmi_bus_type, &info->bus_nb);/* Safe to free channels since no more users */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 535/1376 firmware: arm_scmi: Quiesce notifications before teardown
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit 8e49055d0d495c9c07575ad8e111d9eaf0efb13f ]
scmi_notification_exit() clears and releases the notification instance, but transport callbacks can still deliver incoming notifications until the TX/RX channels are freed. During remove, an RX interrupt in that window can enter scmi_notify() while notification state is being torn down and then dereference freed memory. The same ordering exists on the probe error path after notification initialization.
The notification late-init worker has a separate lifetime issue: protocol event registration queues ni->init_work on the system workqueue, so destroying ni->notify_wq does not drain that work. If the devres group is released while init_work is still pending or running, the late-init worker can dereference the freed notification instance.
Quiesce the notification core before TX/RX channels are torn down, then clean up the channels before releasing the notification core resources. Use disable_work_sync() so future late-init queueing is rejected and any already queued or running late-init work has completed before channel teardown starts.
--- drivers/firmware/arm_scmi/driver.c | 13 +++++++------ drivers/firmware/arm_scmi/notify.c | 21 +++++++++++++++++++++ drivers/firmware/arm_scmi/notify.h | 1 + 3 files changed, 29 insertions(+), 6 deletions(-)
drivers/firmware/arm_scmi/driver.c +7 -6
@@ -3176,7 +3176,7 @@ static int scmi_probe(struct platform_device *pdev)dev_err (dev,"%s" , err_str);return 0 ; } - goto notification_exit; + goto raw_mode_cleanup; }mutex_lock (&scmi_list_mutex);
@@ -3216,17 +3216,18 @@ static int scmi_probe(struct platform_device *pdev)return 0 ; -notification_exit: +raw_mode_cleanup:if (IS_ENABLED (CONFIG_ARM_SCMI_RAW_MODE_SUPPORT ))scmi_raw_mode_cleanup (info->raw); -scmi_notification_exit (&info->handle); clear_dev_req_notifier:blocking_notifier_chain_unregister (&scmi_requested_devices_nh, &info->dev_req_nb); clear_bus_notifier:bus_unregister_notifier (&scmi_bus_type, &info->bus_nb); clear_txrx_setup: +scmi_notification_quiesce (&info->handle);scmi_cleanup_txrx_channels (info); +scmi_notification_exit (&info->handle); clear_ida:ida_free (&scmi_id, info->id);
@@ -3253,6 +3254,9 @@ static void scmi_remove(struct platform_device *pdev)blocking_notifier_chain_unregister (&scmi_requested_devices_nh, &info->dev_req_nb); +/* Stop transport callbacks before tearing down notifications. */ +scmi_notification_quiesce (&info->handle); +scmi_cleanup_txrx_channels (info);scmi_notification_exit (&info->handle);mutex_lock (&info->protocols_mtx);
@@ -3265,9 +3269,6 @@ static void scmi_remove(struct platform_device *pdev)bus_unregister_notifier (&scmi_bus_type, &info->bus_nb); -/* Safe to free channels since no more users */ -scmi_cleanup_txrx_channels (info); -ida_free (&scmi_id, info->id); }
drivers/firmware/arm_scmi/notify.c +21 -0
@@ -1685,6 +1685,25 @@ int scmi_notification_init(struct scmi_handle *handle)return -ENOMEM ; } +/** +* scmi_notification_quiesce() - Stop notification late initialization +* @handle: The handle identifying the platform instance to quiesce +* +* Prevent new late-init work from being queued and wait for any already queued +* or running late-init work to complete before transport channels are torn +* down. +*/ +void scmi_notification_quiesce (struct scmi_handle *handle) +{ +struct scmi_notify_instance *ni; + + ni =scmi_notification_instance_data_get (handle); +if (!ni) +return ; + +disable_work_sync (&ni->init_work); +} +/** * scmi_notification_exit() - Shutdown and clean Notification core * @handle: The handle identifying the platform instance to shutdown
@@ -1696,6 +1715,8 @@ void scmi_notification_exit(struct scmi_handle *handle) ni =scmi_notification_instance_data_get (handle);if (!ni)return ; + +scmi_notification_quiesce (handle);scmi_notification_instance_data_set (handle,NULL );/* Destroy while letting pending work complete */
drivers/firmware/arm_scmi/notify.h +1 -0
@@ -82,6 +82,7 @@ struct scmi_protocol_events { };int scmi_notification_init (struct scmi_handle *handle); +void scmi_notification_quiesce (struct scmi_handle *handle);void scmi_notification_exit (struct scmi_handle *handle); int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id, const struct scmi_protocol_handle *ph,
Signature · 1 line
2.53.0