From 10120b0270b540d4d8e4a45f83fc183a6c90918c Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Thu, 26 Oct 2023 19:57:38 +0530 Subject: [PATCH 01/31] UPSTREAM: firmware_loader: Refactor kill_pending_fw_fallback_reqs() Rename 'only_kill_custom' and refactor logic related to it to be more meaningful. Bug: 309378049 Change-Id: I119d2f8c29b9b624e6c1d8546c1533d76a2cc51d Signed-off-by: Mukesh Ojha Acked-by: Luis Chamberlain Link: https://lore.kernel.org/r/1698330459-31776-1-git-send-email-quic_mojha@quicinc.com Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 87ffa98eeee8d62a56afdad80ea697e7a6e5c354) Signed-off-by: Srinivasarao Pathipati --- drivers/base/firmware_loader/fallback.c | 4 ++-- drivers/base/firmware_loader/fallback.h | 4 ++-- drivers/base/firmware_loader/main.c | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/base/firmware_loader/fallback.c b/drivers/base/firmware_loader/fallback.c index 0fdd18ce2c52..37a26edc4113 100644 --- a/drivers/base/firmware_loader/fallback.c +++ b/drivers/base/firmware_loader/fallback.c @@ -106,7 +106,7 @@ static void fw_load_abort(struct fw_sysfs *fw_sysfs) static LIST_HEAD(pending_fw_head); -void kill_pending_fw_fallback_reqs(bool only_kill_custom) +void kill_pending_fw_fallback_reqs(bool kill_all) { struct fw_priv *fw_priv; struct fw_priv *next; @@ -114,7 +114,7 @@ void kill_pending_fw_fallback_reqs(bool only_kill_custom) mutex_lock(&fw_lock); list_for_each_entry_safe(fw_priv, next, &pending_fw_head, pending_list) { - if (!fw_priv->need_uevent || !only_kill_custom) + if (kill_all || !fw_priv->need_uevent) __fw_load_abort(fw_priv); } mutex_unlock(&fw_lock); diff --git a/drivers/base/firmware_loader/fallback.h b/drivers/base/firmware_loader/fallback.h index 3af7205b302f..1d9476d16a01 100644 --- a/drivers/base/firmware_loader/fallback.h +++ b/drivers/base/firmware_loader/fallback.h @@ -35,7 +35,7 @@ int firmware_fallback_sysfs(struct firmware *fw, const char *name, struct device *device, u32 opt_flags, int ret); -void kill_pending_fw_fallback_reqs(bool only_kill_custom); +void kill_pending_fw_fallback_reqs(bool kill_all); void fw_fallback_set_cache_timeout(void); void fw_fallback_set_default_timeout(void); @@ -52,7 +52,7 @@ static inline int firmware_fallback_sysfs(struct firmware *fw, const char *name, return ret; } -static inline void kill_pending_fw_fallback_reqs(bool only_kill_custom) { } +static inline void kill_pending_fw_fallback_reqs(bool kill_all) { } static inline void fw_fallback_set_cache_timeout(void) { } static inline void fw_fallback_set_default_timeout(void) { } diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index 1372f40d0371..1d3067097481 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -1442,10 +1442,10 @@ static int fw_pm_notify(struct notifier_block *notify_block, case PM_SUSPEND_PREPARE: case PM_RESTORE_PREPARE: /* - * kill pending fallback requests with a custom fallback - * to avoid stalling suspend. + * Here, kill pending fallback requests will only kill + * non-uevent firmware request to avoid stalling suspend. */ - kill_pending_fw_fallback_reqs(true); + kill_pending_fw_fallback_reqs(false); device_cache_fw_images(); break; @@ -1530,7 +1530,7 @@ static int fw_shutdown_notify(struct notifier_block *unused1, * Kill all pending fallback requests to avoid both stalling shutdown, * and avoid a deadlock with the usermode_lock. */ - kill_pending_fw_fallback_reqs(false); + kill_pending_fw_fallback_reqs(true); return NOTIFY_DONE; } From ba88bbf1bb7e22d7b18ad233afd948c4e98923be Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Thu, 26 Oct 2023 19:57:39 +0530 Subject: [PATCH 02/31] BACKPORT: firmware_loader: Abort all upcoming firmware load request once reboot triggered There could be following scenario where there is a ongoing reboot is going from processA which tries to call all the reboot notifier callback and one of them is firmware reboot call which tries to abort all the ongoing firmware userspace request under fw_lock but there could be another processB which tries to do request firmware, which came just after abort done from ProcessA and ask for userspace to load the firmware and this can stop the ongoing reboot ProcessA to stall for next 60s(default timeout) which may not be expected behaviour everyone like to see, instead we should abort any firmware load request which came once firmware knows about the reboot through notification. ProcessA ProcessB kernel_restart_prepare blocking_notifier_call_chain fw_shutdown_notify kill_pending_fw_fallback_reqs __fw_load_abort fw_state_aborted request_firmware __fw_state_set firmware_fallback_sysfs ... fw_load_from_user_helper .. ... . .. usermodehelper_read_trylock fw_load_sysfs_fallback fw_sysfs_wait_timeout usermodehelper_disable __usermodehelper_disable down_write() Bug: 309378049 Change-Id: I61eb91f21a01460f340f890b25c60de7597a87ff Signed-off-by: Mukesh Ojha Acked-by: Luis Chamberlain Link: https://lore.kernel.org/r/1698330459-31776-2-git-send-email-quic_mojha@quicinc.com Signed-off-by: Greg Kroah-Hartman (cherry picked from commit effd7c70eaa0440688b60b9d419243695ede3c45) Signed-off-by: Srinivasarao Pathipati --- drivers/base/firmware_loader/fallback.c | 6 +++++- drivers/base/firmware_loader/firmware.h | 1 + drivers/base/firmware_loader/main.c | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/base/firmware_loader/fallback.c b/drivers/base/firmware_loader/fallback.c index 37a26edc4113..45dfb6e09c24 100644 --- a/drivers/base/firmware_loader/fallback.c +++ b/drivers/base/firmware_loader/fallback.c @@ -117,6 +117,10 @@ void kill_pending_fw_fallback_reqs(bool kill_all) if (kill_all || !fw_priv->need_uevent) __fw_load_abort(fw_priv); } + + if (kill_all) + fw_load_abort_all = true; + mutex_unlock(&fw_lock); } @@ -511,7 +515,7 @@ static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, long timeout) } mutex_lock(&fw_lock); - if (fw_state_is_aborted(fw_priv)) { + if (fw_load_abort_all || fw_state_is_aborted(fw_priv)) { mutex_unlock(&fw_lock); retval = -EINTR; goto out; diff --git a/drivers/base/firmware_loader/firmware.h b/drivers/base/firmware_loader/firmware.h index a3014e9e2c85..53e08de04b86 100644 --- a/drivers/base/firmware_loader/firmware.h +++ b/drivers/base/firmware_loader/firmware.h @@ -87,6 +87,7 @@ struct fw_priv { }; extern struct mutex fw_lock; +extern bool fw_load_abort_all; static inline bool __fw_state_check(struct fw_priv *fw_priv, enum fw_status status) diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index 1d3067097481..9dbfdf9a5645 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -91,6 +91,7 @@ static inline struct fw_priv *to_fw_priv(struct kref *ref) DEFINE_MUTEX(fw_lock); static struct firmware_cache fw_cache; +bool fw_load_abort_all; /* Builtin firmware support */ From 464ef3ee59421dc80da0929abe66eec1f2957458 Mon Sep 17 00:00:00 2001 From: lfc Date: Thu, 21 Sep 2023 14:09:38 +0800 Subject: [PATCH 03/31] ANDROID: vendor_hooks: Add hooks for binder Add hooks to support oem's binder feature of improving binder_thread->task sched priority 1) Check if it is a specific task in trace_android_vh_alloc_oem_binder_struct() and store the flag to t->android_vendor_data1 2) If it is a specific binder task and binder_thread selected, raise the sched priority of binder_thread->task in runqueue. 3) If it is a specific binder task but no binder_thread selected (e.g pending_async or no free threads), insert t->work to the appropriate position in the list. 4) Reset the sched priority when BR_TRANSACTION or BC_FREE_BUFFER. Some high-priority async binder task reset the sched priority when BC_FREE_BUFFER in trace_android_vh_binder_free_buf(). Some middle-priority async binder task reset the sched priority when driver return server "BR_TRANSACTION" in trace_android_vh_binder_transaction_received(). Bug: 308391339 Change-Id: Iab4939fe4a4881b31961aaa2fef500b51c944743 Signed-off-by: lfc --- drivers/android/binder.c | 25 +++++++++++++++++++++---- drivers/android/vendor_hooks.c | 6 ++++++ include/trace/hooks/binder.h | 26 ++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 4165922e93ec..f767ceee9c5c 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -1673,6 +1673,7 @@ static void binder_free_transaction(struct binder_transaction *t) { struct binder_proc *target_proc = t->to_proc; + trace_android_vh_free_oem_binder_struct(t); if (target_proc) { binder_inner_proc_lock(target_proc); target_proc->outstanding_txns--; @@ -2855,6 +2856,7 @@ static int binder_proc_transaction(struct binder_transaction *t, bool oneway = !!(t->flags & TF_ONE_WAY); bool pending_async = false; struct binder_transaction *t_outdated = NULL; + bool enqueue_task = true; BUG_ON(!node); binder_node_lock(node); @@ -2894,7 +2896,10 @@ static int binder_proc_transaction(struct binder_transaction *t, node->inherit_rt); binder_enqueue_thread_work_ilocked(thread, &t->work); } else if (!pending_async) { - binder_enqueue_work_ilocked(&t->work, &proc->todo); + trace_android_vh_binder_special_task(t, proc, thread, + &t->work, &proc->todo, !oneway, &enqueue_task); + if (enqueue_task) + binder_enqueue_work_ilocked(&t->work, &proc->todo); } else { if ((t->flags & TF_UPDATE_TXN) && proc->is_frozen) { t_outdated = binder_find_outdated_transaction_ilocked(t, @@ -2907,11 +2912,16 @@ static int binder_proc_transaction(struct binder_transaction *t, proc->outstanding_txns--; } } - binder_enqueue_work_ilocked(&t->work, &node->async_todo); + trace_android_vh_binder_special_task(t, proc, thread, + &t->work, &node->async_todo, !oneway, &enqueue_task); + if (enqueue_task) + binder_enqueue_work_ilocked(&t->work, &node->async_todo); } trace_android_vh_binder_proc_transaction_end(current, proc->tsk, thread ? thread->task : NULL, t->code, pending_async, !oneway); + trace_android_vh_binder_proc_transaction_finish(proc, t, + thread ? thread->task : NULL, pending_async, !oneway); if (!pending_async) binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */); @@ -3349,6 +3359,7 @@ static void binder_transaction(struct binder_proc *proc, t->buffer->target_node = target_node; t->buffer->clear_on_free = !!(t->flags & TF_CLEAR_BUF); trace_binder_transaction_alloc_buf(t->buffer); + trace_android_vh_alloc_oem_binder_struct(tr, t, target_proc); if (binder_alloc_copy_user_to_buffer( &target_proc->alloc, @@ -3818,6 +3829,9 @@ binder_free_buf(struct binder_proc *proc, struct binder_thread *thread, struct binder_buffer *buffer, bool is_failure) { + bool enqueue_task = true; + + trace_android_vh_binder_free_buf(proc, thread, buffer); binder_inner_proc_lock(proc); if (buffer->transaction) { buffer->transaction->buffer = NULL; @@ -3837,8 +3851,10 @@ binder_free_buf(struct binder_proc *proc, if (!w) { buf_node->has_async_transaction = false; } else { - binder_enqueue_work_ilocked( - w, &proc->todo); + trace_android_vh_binder_special_task(NULL, proc, thread, w, + &proc->todo, false, &enqueue_task); + if (enqueue_task) + binder_enqueue_work_ilocked(w, &proc->todo); binder_wakeup_proc_ilocked(proc); } binder_node_inner_unlock(buf_node); @@ -4785,6 +4801,7 @@ retry: ptr += trsize; trace_binder_transaction_received(t); + trace_android_vh_binder_transaction_received(t, proc, thread, cmd); binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_TRANSACTION, "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n", diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index 3ca92b6b1172..979dc6a1957d 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -499,6 +499,12 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_madvise_cold_or_pageout_abort); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_compact_finished); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_wakeup_bypass); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_skip_swapcache); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_proc_transaction_finish); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_oem_binder_struct); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_transaction_received); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_oem_binder_struct); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_special_task); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_free_buf); /* * For type visibility */ diff --git a/include/trace/hooks/binder.h b/include/trace/hooks/binder.h index fd877ec5b67f..c12926edc615 100644 --- a/include/trace/hooks/binder.h +++ b/include/trace/hooks/binder.h @@ -17,6 +17,8 @@ struct binder_proc; struct binder_thread; struct binder_transaction; struct binder_transaction_data; +struct binder_work; +struct binder_buffer; #else /* struct binder_alloc */ #include <../drivers/android/binder_alloc.h> @@ -114,6 +116,30 @@ DECLARE_HOOK(android_vh_binder_read_done, DECLARE_HOOK(android_vh_binder_has_work_ilocked, TP_PROTO(struct binder_thread *thread, bool do_proc_work, int *ret), TP_ARGS(thread, do_proc_work, ret)); +DECLARE_HOOK(android_vh_binder_proc_transaction_finish, + TP_PROTO(struct binder_proc *proc, struct binder_transaction *t, + struct task_struct *binder_th_task, bool pending_async, bool sync), + TP_ARGS(proc, t, binder_th_task, pending_async, sync)); +DECLARE_HOOK(android_vh_alloc_oem_binder_struct, + TP_PROTO(struct binder_transaction_data *tr, struct binder_transaction *t, + struct binder_proc *proc), + TP_ARGS(tr, t, proc)); +DECLARE_HOOK(android_vh_binder_transaction_received, + TP_PROTO(struct binder_transaction *t, struct binder_proc *proc, + struct binder_thread *thread, uint32_t cmd), + TP_ARGS(t, proc, thread, cmd)); +DECLARE_HOOK(android_vh_free_oem_binder_struct, + TP_PROTO(struct binder_transaction *t), + TP_ARGS(t)); +DECLARE_HOOK(android_vh_binder_special_task, + TP_PROTO(struct binder_transaction *t, struct binder_proc *proc, + struct binder_thread *thread, struct binder_work *w, + struct list_head *head, bool sync, bool *special_task), + TP_ARGS(t, proc, thread, w, head, sync, special_task)); +DECLARE_HOOK(android_vh_binder_free_buf, + TP_PROTO(struct binder_proc *proc, struct binder_thread *thread, + struct binder_buffer *buffer), + TP_ARGS(proc, thread, buffer)); /* macro versions of hooks are no longer required */ #endif /* _TRACE_HOOK_BINDER_H */ From efe30da3a33248b5e4bbd940105cee24623daef2 Mon Sep 17 00:00:00 2001 From: lfc Date: Tue, 21 Nov 2023 10:38:11 +0800 Subject: [PATCH 04/31] ANDROID: ABI: Update oplus symbol list Leaf changes summary: 12 artifacts changed Changed leaf types summary: 0 leaf type changed Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 6 Added functions Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 6 Added variables 6 Added functions: [A] 'function int __traceiter_android_vh_alloc_oem_binder_struct(void*, binder_transaction_data*, binder_transaction*, binder_proc*)' [A] 'function int __traceiter_android_vh_binder_free_buf(void*, binder_proc*, binder_thread*, binder_buffer*)' [A] 'function int __traceiter_android_vh_binder_proc_transaction_finish(void*, binder_proc*, binder_transaction*, task_struct*, bool, bool)' [A] 'function int __traceiter_android_vh_binder_special_task(void*, binder_transaction*, binder_proc*, binder_thread*, binder_work*, list_head*, bool, bool*)' [A] 'function int __traceiter_android_vh_binder_transaction_received(void*, binder_transaction*, binder_proc*, binder_thread*, uint32_t)' [A] 'function int __traceiter_android_vh_free_oem_binder_struct(void*, binder_transaction*)' 6 Added variables: [A] 'tracepoint __tracepoint_android_vh_alloc_oem_binder_struct' [A] 'tracepoint __tracepoint_android_vh_binder_free_buf' [A] 'tracepoint __tracepoint_android_vh_binder_proc_transaction_finish' [A] 'tracepoint __tracepoint_android_vh_binder_special_task' [A] 'tracepoint __tracepoint_android_vh_binder_transaction_received' [A] 'tracepoint __tracepoint_android_vh_free_oem_binder_struct' Bug: 308391339 Change-Id: Id46f5d977fa8f9bbc7496a115ec4683eb4c768ef Signed-off-by: lfc --- android/abi_gki_aarch64.xml | 4258 +++++++++++++++++---------------- android/abi_gki_aarch64_oplus | 12 + 2 files changed, 2174 insertions(+), 2096 deletions(-) diff --git a/android/abi_gki_aarch64.xml b/android/abi_gki_aarch64.xml index 2aacb29c6fd9..6df87b000b69 100644 --- a/android/abi_gki_aarch64.xml +++ b/android/abi_gki_aarch64.xml @@ -425,6 +425,7 @@ + @@ -438,6 +439,7 @@ + @@ -447,14 +449,17 @@ + + + @@ -512,6 +517,7 @@ + @@ -6512,6 +6518,7 @@ + @@ -6525,6 +6532,7 @@ + @@ -6534,14 +6542,17 @@ + + + @@ -6599,6 +6610,7 @@ + @@ -8333,7 +8345,7 @@ - + @@ -9710,12 +9722,12 @@ - + - + - + @@ -11048,9 +11060,9 @@ - + - + @@ -11557,12 +11569,12 @@ - + - + - + @@ -12773,24 +12785,24 @@ - + - + - + - + - + - + - + @@ -13240,30 +13252,30 @@ - + - + - + - + - + - + - + - + - + @@ -13947,93 +13959,93 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -15935,51 +15947,51 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -17300,12 +17312,12 @@ - + - + - + @@ -19637,12 +19649,12 @@ - + - + - + @@ -22086,9 +22098,9 @@ - + - + @@ -24853,42 +24865,42 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -25082,12 +25094,12 @@ - + - + - + @@ -28034,18 +28046,18 @@ - + - + - + - + - + @@ -28483,12 +28495,12 @@ - + - + - + @@ -30277,141 +30289,141 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -33247,30 +33259,30 @@ - + - + - + - + - + - + - + - + - + @@ -33991,18 +34003,18 @@ - + - + - + - + - + @@ -34718,18 +34730,18 @@ - + - + - + - + - + @@ -34740,60 +34752,60 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -37461,12 +37473,12 @@ - + - + - + @@ -39682,60 +39694,60 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -40171,21 +40183,21 @@ - + - + - + - + - + - + @@ -40790,7 +40802,7 @@ - + @@ -40891,24 +40903,24 @@ - + - + - + - + - + - + - + @@ -43037,27 +43049,27 @@ - + - + - + - + - + - + - + - + @@ -43958,12 +43970,12 @@ - + - + - + @@ -44743,7 +44755,7 @@ - + @@ -45147,12 +45159,12 @@ - + - + - + @@ -48635,252 +48647,252 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -50850,9 +50862,9 @@ - + - + @@ -51879,18 +51891,18 @@ - + - + - + - + - + @@ -52039,24 +52051,24 @@ - + - + - + - + - + - + - + @@ -52488,67 +52500,67 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -53692,18 +53704,18 @@ - + - + - + - + - + @@ -54381,18 +54393,18 @@ - + - + - + - + - + @@ -54780,15 +54792,15 @@ - + - + - + - + @@ -58458,39 +58470,39 @@ - + - + - + - + - + - + - + - + - + - + - + - + @@ -58605,390 +58617,390 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -62201,18 +62213,18 @@ - + - + - + - + - + @@ -62454,9 +62466,9 @@ - + - + @@ -62533,18 +62545,18 @@ - + - + - + - + - + @@ -62972,12 +62984,12 @@ - + - + - + @@ -63225,21 +63237,21 @@ - + - + - + - + - + - + @@ -65934,39 +65946,39 @@ - + - + - + - + - + - + - + - + - + - + - + - + @@ -68608,7 +68620,7 @@ - + @@ -72517,45 +72529,45 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -77323,15 +77335,15 @@ - + - + - + - + @@ -77934,9 +77946,9 @@ - + - + @@ -78352,18 +78364,18 @@ - + - + - + - + - + @@ -83130,7 +83142,8 @@ - + + @@ -84055,18 +84068,18 @@ - + - + - + - + - + @@ -91826,15 +91839,15 @@ - + - + - + - + @@ -93719,15 +93732,15 @@ - + - + - + - + @@ -100524,78 +100537,78 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -102920,24 +102933,24 @@ - + - + - + - + - + - + - + @@ -104837,12 +104850,12 @@ - + - + - + @@ -105193,21 +105206,21 @@ - + - + - + - + - + - + @@ -105944,33 +105957,33 @@ - + - + - + - + - + - + - + - + - + - + @@ -107073,18 +107086,18 @@ - + - + - + - + - + @@ -110124,9 +110137,9 @@ - + - + @@ -112221,15 +112234,15 @@ - + - + - + - + @@ -112651,15 +112664,15 @@ - + - + - + - + @@ -114781,27 +114794,27 @@ - + - + - + - + - + - + - + - + @@ -114954,33 +114967,33 @@ - + - + - + - + - + - + - + - + - + - + @@ -116242,36 +116255,36 @@ - + - + - + - + - + - + - + - + - + - + - + @@ -116521,9 +116534,9 @@ - + - + @@ -116852,49 +116865,49 @@ - - - - - - - - + + + + + + + + - - - + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - + + + + @@ -117051,21 +117064,21 @@ - - - - + + + + - - - - + + + + - - - + + + @@ -117237,9 +117250,9 @@ - - - + + + @@ -117690,9 +117703,9 @@ - - - + + + @@ -117753,7 +117766,7 @@ - + @@ -117845,34 +117858,34 @@ - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + @@ -118123,8 +118136,8 @@ - - + + @@ -118139,8 +118152,8 @@ - - + + @@ -118155,13 +118168,13 @@ - - - - - - - + + + + + + + @@ -118318,12 +118331,12 @@ - - - - - - + + + + + + @@ -119065,6 +119078,13 @@ + + + + + + + @@ -119147,148 +119167,183 @@ - - - - - + + + + + - - - - + + + + - - - + + + + + - - - - - + + + - - - - + + + + + - - - - - + + + + - - - - + + + + + - - - - - - + + + + - - - - + + + + + + - - - - - - - - + + + + - - - - - - - - + + + + + + + + - - - - + + + + + + + + - - - - - - + + + + + + + - - - - + + + + - - - - + + + + + + - - - - - + + + + - - - - + + + + - - - - - - + + + + + + + + + - - - + + + + + - - - - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -119646,6 +119701,11 @@ + + + + + @@ -120670,10 +120730,10 @@ - - - - + + + + @@ -121374,7 +121434,7 @@ - + @@ -121488,6 +121548,7 @@ + @@ -121499,27 +121560,31 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -121575,6 +121640,7 @@ + @@ -121743,7 +121809,7 @@ - + @@ -121867,37 +121933,37 @@ - - - + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + @@ -121918,12 +121984,12 @@ - - - - - - + + + + + + @@ -121989,9 +122055,9 @@ - - - + + + @@ -122319,8 +122385,8 @@ - - + + @@ -122526,12 +122592,12 @@ - - - - - - + + + + + + @@ -122550,18 +122616,18 @@ - - + + - - - + + + - - - + + + @@ -122992,8 +123058,8 @@ - - + + @@ -123003,10 +123069,10 @@ - - - - + + + + @@ -123028,27 +123094,27 @@ - - + + - - + + - - - - + + + + - - - + + + @@ -123267,8 +123333,8 @@ - - + + @@ -123447,8 +123513,8 @@ - - + + @@ -123468,10 +123534,10 @@ - - - - + + + + @@ -123587,10 +123653,10 @@ - - - - + + + + @@ -123608,12 +123674,87 @@ - - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -123621,13 +123762,9 @@ - - - - - + @@ -123636,13 +123773,9 @@ - - - - - + @@ -123652,90 +123785,23 @@ - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -123870,9 +123936,9 @@ - - - + + + @@ -123960,11 +124026,11 @@ - - - - - + + + + + @@ -124103,31 +124169,31 @@ - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + @@ -124754,16 +124820,16 @@ - - + + - + - + @@ -124791,10 +124857,10 @@ - + - + @@ -124851,31 +124917,31 @@ - - + + - - - + + + - - - + + + - - - - + + + + - + - - + + @@ -124910,45 +124976,45 @@ - - + + - - + + - + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - + + + @@ -124965,29 +125031,29 @@ - - + + - - + + - - - + + + - - + + - - + + - + @@ -125045,15 +125111,15 @@ - + - + - - - + + + @@ -125553,14 +125619,14 @@ - - - + + + - - - + + + @@ -126356,9 +126422,9 @@ - - - + + + @@ -126422,15 +126488,15 @@ - - - - - + + + + + - - + + @@ -126461,14 +126527,14 @@ - - + + - - - - + + + + @@ -126487,36 +126553,36 @@ - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + @@ -126879,11 +126945,11 @@ - - - - - + + + + + @@ -126891,28 +126957,28 @@ - - - - - + + + + + - - - + + + - - - + + + - - - - - + + + + + @@ -127666,10 +127732,10 @@ - - - - + + + + @@ -127678,10 +127744,10 @@ - - - - + + + + @@ -128347,9 +128413,9 @@ - - - + + + @@ -128361,149 +128427,149 @@ - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - - + + + + - - + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - - - - + + + + + - - + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + @@ -129990,8 +130056,8 @@ - - + + @@ -130003,10 +130069,10 @@ - - - - + + + + @@ -131365,22 +131431,22 @@ - - + + - - + + - - - - + + + + @@ -131532,15 +131598,15 @@ - + - - + + @@ -131557,10 +131623,10 @@ - - - - + + + + @@ -131654,10 +131720,10 @@ - - - - + + + + @@ -131686,7 +131752,7 @@ - + @@ -131742,20 +131808,20 @@ - - + + - - + + - - + + - - + + @@ -131812,8 +131878,8 @@ - - + + @@ -132104,8 +132170,8 @@ - - + + @@ -132365,9 +132431,9 @@ - - - + + + @@ -132384,9 +132450,9 @@ - - - + + + @@ -132394,9 +132460,9 @@ - - - + + + @@ -132428,10 +132494,10 @@ - - - - + + + + @@ -132546,14 +132612,14 @@ - - - + + + - - - + + + @@ -132672,12 +132738,12 @@ - - + + - - + + @@ -132691,9 +132757,9 @@ - - - + + + @@ -132733,11 +132799,11 @@ - - - - - + + + + + @@ -133025,10 +133091,10 @@ - - - - + + + + @@ -133056,29 +133122,29 @@ - - + + - - - + + + - - + + - - + + - - + + - - + + @@ -133819,8 +133885,8 @@ - - + + @@ -133839,8 +133905,8 @@ - - + + @@ -134411,11 +134477,11 @@ - + - - + + @@ -134738,10 +134804,10 @@ - - - - + + + + @@ -135149,11 +135215,11 @@ - - - - - + + + + + @@ -135258,23 +135324,23 @@ - - - - + + + + - - - - - + + + + + - - - + + + @@ -135295,25 +135361,25 @@ - - - - - - - + + + + + + + - - - - - - + + + + + + @@ -135321,9 +135387,9 @@ - - - + + + @@ -135395,12 +135461,12 @@ - - + + - - + + @@ -135409,8 +135475,8 @@ - - + + @@ -135577,23 +135643,23 @@ - - - - + + + + - - - + + + - - + + @@ -136068,9 +136134,9 @@ - - - + + + @@ -136808,8 +136874,8 @@ - - + + @@ -136904,8 +136970,8 @@ - - + + @@ -137008,8 +137074,8 @@ - - + + @@ -137128,8 +137194,8 @@ - - + + @@ -137182,24 +137248,24 @@ - - - - - - + + + + + + - - - - - - + + + + + + @@ -137299,16 +137365,16 @@ - - - + + + - - - - - + + + + + @@ -137870,8 +137936,8 @@ - - + + @@ -138735,24 +138801,24 @@ - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + @@ -138856,16 +138922,16 @@ - - - - + + + + - - - - + + + + @@ -138878,8 +138944,8 @@ - - + + @@ -138942,9 +139008,9 @@ - - - + + + @@ -139394,8 +139460,8 @@ - - + + @@ -139514,50 +139580,50 @@ - - + + - - - - - - + + + + + + - - + + - - + + - - - + + + - - - - - + + + + + - - - - + + + + - - + + - - + + @@ -139567,20 +139633,20 @@ - - - - + + + + - - - - + + + + - - + + @@ -139589,15 +139655,15 @@ - - - - - - - - - + + + + + + + + + @@ -140507,50 +140573,50 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + @@ -140870,13 +140936,13 @@ - - - + + + - - + + @@ -140986,8 +141052,8 @@ - - + + @@ -141068,22 +141134,22 @@ - - - + + + - - - - + + + + - - - - - + + + + + @@ -141092,10 +141158,10 @@ - - - - + + + + @@ -141117,10 +141183,10 @@ - - - - + + + + @@ -141133,9 +141199,9 @@ - - - + + + @@ -141209,7 +141275,7 @@ - + @@ -141292,17 +141358,17 @@ - - - - - + + + + + - - - - + + + + @@ -141318,8 +141384,8 @@ - - + + @@ -141346,8 +141412,8 @@ - - + + @@ -141423,12 +141489,12 @@ - - + + - - + + @@ -141925,8 +141991,8 @@ - - + + @@ -141934,8 +142000,8 @@ - - + + @@ -141946,14 +142012,14 @@ - - - - + + + + - - + + @@ -141992,34 +142058,34 @@ - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + @@ -142060,8 +142126,8 @@ - - + + @@ -142220,7 +142286,7 @@ - + @@ -142453,8 +142519,8 @@ - - + + @@ -142687,43 +142753,43 @@ - - - - - - - - - + - - - - + + + + + + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - + + @@ -143438,36 +143504,36 @@ - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - - + + @@ -143503,9 +143569,9 @@ - - - + + + @@ -143781,21 +143847,21 @@ - - - - + + + + - - - + + + - - - - + + + + @@ -143936,16 +144002,16 @@ - - - - - - + + + + + + - - + + @@ -143980,8 +144046,8 @@ - - + + @@ -143991,9 +144057,9 @@ - - - + + + @@ -144048,9 +144114,9 @@ - - - + + + @@ -144058,16 +144124,16 @@ - - - - + + + + - - - - + + + + @@ -144116,9 +144182,9 @@ - - - + + + @@ -144128,11 +144194,11 @@ - - - - - + + + + + @@ -144140,9 +144206,9 @@ - - - + + + @@ -144622,8 +144688,8 @@ - - + + @@ -144632,29 +144698,29 @@ - - - + + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + @@ -144686,12 +144752,12 @@ - - - - - - + + + + + + @@ -145369,84 +145435,84 @@ - - - - - - - + + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - + + - - - - - + + + + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + @@ -145454,34 +145520,34 @@ - - - - + + + + - - + + - - - - - - + + + + + + - - + + - - + + @@ -145963,12 +146029,12 @@ - - + + - - + + @@ -146047,13 +146113,13 @@ - + - + @@ -146249,7 +146315,7 @@ - + @@ -146318,12 +146384,12 @@ - - - - - - + + + + + + @@ -146357,34 +146423,34 @@ - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + @@ -146392,44 +146458,44 @@ - - - + + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - + + - - + + @@ -146532,12 +146598,12 @@ - - + + - - + + @@ -146607,26 +146673,26 @@ - - + + - - - - - + + + + + - - + + @@ -146649,14 +146715,14 @@ - - - - + + + + - - + + @@ -146715,10 +146781,10 @@ - - - - + + + + @@ -146793,9 +146859,9 @@ - - - + + + @@ -147221,8 +147287,8 @@ - - + + @@ -147231,8 +147297,8 @@ - - + + @@ -147240,11 +147306,11 @@ - - - - - + + + + + @@ -147497,10 +147563,10 @@ - - - - + + + + @@ -147787,12 +147853,12 @@ - - + + - - + + @@ -147928,10 +147994,10 @@ - - - - + + + + @@ -148027,20 +148093,20 @@ - - - - - + + + + + - - - + + + @@ -148071,17 +148137,17 @@ - - - - + + + + - - - - - + + + + + @@ -148125,9 +148191,9 @@ - - - + + + @@ -148138,8 +148204,8 @@ - - + + @@ -148350,45 +148416,45 @@ - - + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - - + + + + @@ -148406,31 +148472,31 @@ - - + + - - + + - - - + + + - - - + + + - - - + + + @@ -148439,9 +148505,9 @@ - - - + + + @@ -148540,16 +148606,16 @@ - - + + - - + + @@ -148572,16 +148638,16 @@ - - + + - - + + @@ -148618,8 +148684,8 @@ - - + + @@ -148631,10 +148697,10 @@ - - - - + + + + @@ -148689,8 +148755,8 @@ - - + + @@ -148750,10 +148816,10 @@ - - - - + + + + @@ -148769,28 +148835,28 @@ - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - + + @@ -148817,9 +148883,9 @@ - - - + + + @@ -148835,34 +148901,34 @@ - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + @@ -150174,8 +150240,8 @@ - - + + @@ -150189,8 +150255,8 @@ - - + + @@ -150329,13 +150395,13 @@ - - + + - - - + + + diff --git a/android/abi_gki_aarch64_oplus b/android/abi_gki_aarch64_oplus index aef23e847499..76c9c4c070bf 100644 --- a/android/abi_gki_aarch64_oplus +++ b/android/abi_gki_aarch64_oplus @@ -2966,6 +2966,12 @@ __traceiter_task_newtask __traceiter_task_rename __traceiter_xhci_urb_giveback + __traceiter_android_vh_binder_proc_transaction_finish + __traceiter_android_vh_alloc_oem_binder_struct + __traceiter_android_vh_binder_transaction_received + __traceiter_android_vh_free_oem_binder_struct + __traceiter_android_vh_binder_special_task + __traceiter_android_vh_binder_free_buf __tracepoint_android_rvh_account_irq __tracepoint_android_rvh_after_enqueue_task __tracepoint_android_rvh_build_perf_domains @@ -3238,6 +3244,12 @@ __tracepoint_task_newtask __tracepoint_task_rename __tracepoint_xhci_urb_giveback + __tracepoint_android_vh_binder_proc_transaction_finish + __tracepoint_android_vh_alloc_oem_binder_struct + __tracepoint_android_vh_binder_transaction_received + __tracepoint_android_vh_free_oem_binder_struct + __tracepoint_android_vh_binder_special_task + __tracepoint_android_vh_binder_free_buf trace_print_array_seq trace_print_flags_seq trace_print_hex_seq From 4194727e2ccb81e9e43ff10b16f59fe5e4c34246 Mon Sep 17 00:00:00 2001 From: Daniel Mentz Date: Wed, 13 Apr 2022 16:36:49 -0700 Subject: [PATCH 05/31] UPSTREAM: kheaders: Have cpio unconditionally replace files For out-of-tree builds, this script invokes cpio twice to copy header files from the srctree and subsequently from the objtree. According to a comment in the script, there might be situations in which certain files already exist in the destination directory when header files are copied from the objtree: "The second CPIO can complain if files already exist which can happen with out of tree builds having stale headers in srctree. Just silence CPIO for now." GNU cpio might simply print a warning like "newer or same age version exists", but toybox cpio exits with a non-zero exit code unless the command line option "-u" is specified. To improve compatibility with toybox cpio, add the command line option "-u" to unconditionally replace existing files in the destination directory. Bug: 312397409 Signed-off-by: Daniel Mentz Signed-off-by: Masahiro Yamada Change-Id: I1797f7ca3f36c71a313cccce1bc53fcc2d04ca65 Signed-off-by: Srinivasarao Pathipati (cherry picked from commit 1e8ca62b79dec20aeded4fe283f4890e5016767a) --- kernel/gen_kheaders.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh index c1510f0ab3ea..b2ef29ad82dc 100755 --- a/kernel/gen_kheaders.sh +++ b/kernel/gen_kheaders.sh @@ -76,7 +76,7 @@ fi # of tree builds having stale headers in srctree. Just silence CPIO for now. for f in $dir_list; do find "$f" -name "*.h"; -done | cpio --quiet -pd $cpio_dir >/dev/null 2>&1 +done | cpio --quiet -pdu $cpio_dir >/dev/null 2>&1 # Remove comments except SDPX lines find $cpio_dir -type f -print0 | From e6278ff4b708984f059d838b9c1a42b4cf739323 Mon Sep 17 00:00:00 2001 From: Srinivasarao Pathipati Date: Wed, 22 Nov 2023 10:20:00 +0530 Subject: [PATCH 06/31] ANDROID: abi_gki_aarch64_qcom: Add android_gki_sysctl_vals The commit 44da38b39ca6 ("ANDROID: GKI: fix up sysctl_vals ABI change") introduces new symbol android_gki_sysctl_vals, add it to the symbol list. Leaf changes summary: 1 artifact changed Changed leaf types summary: 0 leaf type changed Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 0 Added function Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 1 Added variable 1 Added variable: [A] 'const int android_gki_sysctl_vals[10]' Bug: 312089212 Change-Id: I68b218becb5a077fce95c2888f2f20e1c5053ad1 Signed-off-by: Srinivasarao Pathipati --- android/abi_gki_aarch64.xml | 5 +++++ android/abi_gki_aarch64_qcom | 1 + 2 files changed, 6 insertions(+) diff --git a/android/abi_gki_aarch64.xml b/android/abi_gki_aarch64.xml index 6df87b000b69..2a0237ec5e8d 100644 --- a/android/abi_gki_aarch64.xml +++ b/android/abi_gki_aarch64.xml @@ -6894,6 +6894,7 @@ + @@ -100817,6 +100818,9 @@ + + + @@ -122638,6 +122642,7 @@ + diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 9079fc8ae46d..32951b84a548 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -34,6 +34,7 @@ android_debug_for_each_module android_debug_per_cpu_symbol android_debug_symbol + android_gki_sysctl_vals android_rvh_probe_register anon_inode_getfile arc4_crypt From 525ecbbfda3c4dfe61242da78187c698993d29e6 Mon Sep 17 00:00:00 2001 From: Biswarup Pal Date: Mon, 1 May 2023 20:19:19 -0700 Subject: [PATCH 07/31] FROMGIT: Input: uinput - allow injecting event times Currently, uinput doesn't use the input_set_timestamp API, so any event injected using uinput is not accurately timestamped in terms of measuring when the actual event happened. Hence, call the input_set_timestamp API from uinput in order to provide a more accurate sense of time for the event. Propagate only the timestamps which are a) positive, b) within a pre-defined offset (10 secs) from the current time, and c) not in the future. Bug: 271946580 Bug: 277040837 Change-Id: I928be61d0114b78e2098995ee49eeb0376bef2a3 (cherry picked from commit 3a2df60200a03f78173f1fd831aa54c08464dcde https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git master) Signed-off-by: Biswarup Pal Reviewed-by: Peter Hutterer Reviewed-by: Siarhei Vishniakou Link: https://lore.kernel.org/r/20230427000152.1407471-1-biswarupp@google.com Signed-off-by: Dmitry Torokhov (cherry picked from commit ee1f5fc55cc7bf1bca78edbb8a1f9d989d4ea03e) --- drivers/input/misc/uinput.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index f2593133e524..d98212d55108 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -33,6 +33,7 @@ #define UINPUT_NAME "uinput" #define UINPUT_BUFFER_SIZE 16 #define UINPUT_NUM_REQUESTS 16 +#define UINPUT_TIMESTAMP_ALLOWED_OFFSET_SECS 10 enum uinput_state { UIST_NEW_DEVICE, UIST_SETUP_COMPLETE, UIST_CREATED }; @@ -569,11 +570,40 @@ static int uinput_setup_device_legacy(struct uinput_device *udev, return retval; } +/* + * Returns true if the given timestamp is valid (i.e., if all the following + * conditions are satisfied), false otherwise. + * 1) given timestamp is positive + * 2) it's within the allowed offset before the current time + * 3) it's not in the future + */ +static bool is_valid_timestamp(const ktime_t timestamp) +{ + ktime_t zero_time; + ktime_t current_time; + ktime_t min_time; + ktime_t offset; + + zero_time = ktime_set(0, 0); + if (ktime_compare(zero_time, timestamp) >= 0) + return false; + + current_time = ktime_get(); + offset = ktime_set(UINPUT_TIMESTAMP_ALLOWED_OFFSET_SECS, 0); + min_time = ktime_sub(current_time, offset); + + if (ktime_after(min_time, timestamp) || ktime_after(timestamp, current_time)) + return false; + + return true; +} + static ssize_t uinput_inject_events(struct uinput_device *udev, const char __user *buffer, size_t count) { struct input_event ev; size_t bytes = 0; + ktime_t timestamp; if (count != 0 && count < input_event_size()) return -EINVAL; @@ -588,6 +618,10 @@ static ssize_t uinput_inject_events(struct uinput_device *udev, if (input_event_from_user(buffer + bytes, &ev)) return -EFAULT; + timestamp = ktime_set(ev.input_event_sec, ev.input_event_usec * NSEC_PER_USEC); + if (is_valid_timestamp(timestamp)) + input_set_timestamp(udev->dev, timestamp); + input_event(udev->dev, ev.type, ev.code, ev.value); bytes += input_event_size(); cond_resched(); From 66b73fb5b9e3b9d0a884122fdb6853a11965ccab Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 31 Oct 2023 11:25:35 +0000 Subject: [PATCH 08/31] UPSTREAM: driver: platform: Add helper for safer setting of driver_override commit 6c2f421174273de8f83cde4286d1c076d43a2d35 upstream. Several core drivers and buses expect that driver_override is a dynamically allocated memory thus later they can kfree() it. However such assumption is not documented, there were in the past and there are already users setting it to a string literal. This leads to kfree() of static memory during device release (e.g. in error paths or during unbind): kernel BUG at ../mm/slub.c:3960! Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM ... (kfree) from [] (platform_device_release+0x88/0xb4) (platform_device_release) from [] (device_release+0x2c/0x90) (device_release) from [] (kobject_put+0xec/0x20c) (kobject_put) from [] (exynos5_clk_probe+0x154/0x18c) (exynos5_clk_probe) from [] (platform_drv_probe+0x6c/0xa4) (platform_drv_probe) from [] (really_probe+0x280/0x414) (really_probe) from [] (driver_probe_device+0x78/0x1c4) (driver_probe_device) from [] (bus_for_each_drv+0x74/0xb8) (bus_for_each_drv) from [] (__device_attach+0xd4/0x16c) (__device_attach) from [] (bus_probe_device+0x88/0x90) (bus_probe_device) from [] (device_add+0x3dc/0x62c) (device_add) from [] (of_platform_device_create_pdata+0x94/0xbc) (of_platform_device_create_pdata) from [] (of_platform_bus_create+0x1a8/0x4fc) (of_platform_bus_create) from [] (of_platform_bus_create+0x20c/0x4fc) (of_platform_bus_create) from [] (of_platform_populate+0x84/0x118) (of_platform_populate) from [] (of_platform_default_populate_init+0xa0/0xb8) (of_platform_default_populate_init) from [] (do_one_initcall+0x8c/0x404) Provide a helper which clearly documents the usage of driver_override. This will allow later to reuse the helper and reduce the amount of duplicated code. Convert the platform driver to use a new helper and make the driver_override field const char (it is not modified by the core). Bug: 95334746 Reviewed-by: Rafael J. Wysocki Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220419113435.246203-2-krzysztof.kozlowski@linaro.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 389190b25472627d010a9eb3c5a7227c3e92fa08) Signed-off-by: Lee Jones Change-Id: I1ef85ee1f3828e947adec4a45363d8434876aade --- drivers/base/driver.c | 69 +++++++++++++++++++++++++++++++++ drivers/base/platform.c | 28 ++----------- include/linux/device/driver.h | 2 + include/linux/platform_device.h | 6 ++- 4 files changed, 80 insertions(+), 25 deletions(-) diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 8c0d33e182fd..1b9d47b10bd0 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -30,6 +30,75 @@ static struct device *next_device(struct klist_iter *i) return dev; } +/** + * driver_set_override() - Helper to set or clear driver override. + * @dev: Device to change + * @override: Address of string to change (e.g. &device->driver_override); + * The contents will be freed and hold newly allocated override. + * @s: NUL-terminated string, new driver name to force a match, pass empty + * string to clear it ("" or "\n", where the latter is only for sysfs + * interface). + * @len: length of @s + * + * Helper to set or clear driver override in a device, intended for the cases + * when the driver_override field is allocated by driver/bus code. + * + * Returns: 0 on success or a negative error code on failure. + */ +int driver_set_override(struct device *dev, const char **override, + const char *s, size_t len) +{ + const char *new, *old; + char *cp; + + if (!override || !s) + return -EINVAL; + + /* + * The stored value will be used in sysfs show callback (sysfs_emit()), + * which has a length limit of PAGE_SIZE and adds a trailing newline. + * Thus we can store one character less to avoid truncation during sysfs + * show. + */ + if (len >= (PAGE_SIZE - 1)) + return -EINVAL; + + if (!len) { + /* Empty string passed - clear override */ + device_lock(dev); + old = *override; + *override = NULL; + device_unlock(dev); + kfree(old); + + return 0; + } + + cp = strnchr(s, len, '\n'); + if (cp) + len = cp - s; + + new = kstrndup(s, len, GFP_KERNEL); + if (!new) + return -ENOMEM; + + device_lock(dev); + old = *override; + if (cp != s) { + *override = new; + } else { + /* "\n" passed - clear override */ + kfree(new); + *override = NULL; + } + device_unlock(dev); + + kfree(old); + + return 0; +} +EXPORT_SYMBOL_GPL(driver_set_override); + /** * driver_for_each_device - Iterator for devices bound to a driver. * @drv: Driver we're iterating. diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 88aef93eb4dd..647066229fec 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1046,31 +1046,11 @@ static ssize_t driver_override_store(struct device *dev, const char *buf, size_t count) { struct platform_device *pdev = to_platform_device(dev); - char *driver_override, *old, *cp; + int ret; - /* We need to keep extra room for a newline */ - if (count >= (PAGE_SIZE - 1)) - return -EINVAL; - - driver_override = kstrndup(buf, count, GFP_KERNEL); - if (!driver_override) - return -ENOMEM; - - cp = strchr(driver_override, '\n'); - if (cp) - *cp = '\0'; - - device_lock(dev); - old = pdev->driver_override; - if (strlen(driver_override)) { - pdev->driver_override = driver_override; - } else { - kfree(driver_override); - pdev->driver_override = NULL; - } - device_unlock(dev); - - kfree(old); + ret = driver_set_override(dev, &pdev->driver_override, buf, count); + if (ret) + return ret; return count; } diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h index d5ad474e4fab..3c7253474683 100644 --- a/include/linux/device/driver.h +++ b/include/linux/device/driver.h @@ -155,6 +155,8 @@ extern int __must_check driver_create_file(struct device_driver *driver, extern void driver_remove_file(struct device_driver *driver, const struct driver_attribute *attr); +int driver_set_override(struct device *dev, const char **override, + const char *s, size_t len); extern int __must_check driver_for_each_device(struct device_driver *drv, struct device *start, void *data, diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 72b8a954e6bb..43976e8901c4 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -31,7 +31,11 @@ struct platform_device { struct resource *resource; const struct platform_device_id *id_entry; - char *driver_override; /* Driver name to force a match */ + /* + * Driver name to force a match. Do not set directly, because core + * frees it. Use driver_set_override() to set or clear it. + */ + const char *driver_override; /* MFD cell pointer */ struct mfd_cell *mfd_cell; From 68482b6bd9592242fc86c679e05aef494f837b59 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 31 Oct 2023 11:25:36 +0000 Subject: [PATCH 09/31] UPSTREAM: rpmsg: Constify local variable in field store macro commit e5f89131a06142e91073b6959d91cea73861d40e upstream. Memory pointed by variable 'old' in field store macro is not modified, so it can be made a pointer to const. Bug: 295334746 Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220419113435.246203-12-krzysztof.kozlowski@linaro.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 5c0da71871d3ac3f96d37067bf1a0ba9c25c2c72) Signed-off-by: Lee Jones Change-Id: If5610892601368e855ec1be57e01dbbe06ae046a --- drivers/rpmsg/rpmsg_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 2037a4692b84..53cc59eeb662 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -368,7 +368,8 @@ field##_store(struct device *dev, struct device_attribute *attr, \ const char *buf, size_t sz) \ { \ struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ - char *new, *old; \ + const char *old; \ + char *new; \ \ new = kstrndup(buf, sz, GFP_KERNEL); \ if (!new) \ From 20f1dfc0f7983f0123602e613b668a307389f739 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 31 Oct 2023 11:25:37 +0000 Subject: [PATCH 10/31] BACKPORT: rpmsg: Fix kfree() of static memory on setting driver_override commit 42cd402b8fd4672b692400fe5f9eecd55d2794ac upstream. The driver_override field from platform driver should not be initialized from static memory (string literal) because the core later kfree() it, for example when driver_override is set via sysfs. Use dedicated helper to set driver_override properly. Bug: 295334746 Fixes: 950a7388f02b ("rpmsg: Turn name service into a stand alone driver") Fixes: c0cdc19f84a4 ("rpmsg: Driver for user space endpoint interface") Reviewed-by: Bjorn Andersson Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220419113435.246203-13-krzysztof.kozlowski@linaro.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 2e76b4f6218c4db3ff00eb15d94d72f371736de4) [Lee: Cater for name change s/rpmsg_chrdev/rpmsg_ctrl/ due to previous backport] Signed-off-by: Lee Jones Change-Id: Ib900ad13efcfdf7e50fb92bb45dff2b8aa8ff443 --- drivers/rpmsg/rpmsg_internal.h | 15 ++++++++++++--- include/linux/rpmsg.h | 6 ++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h index 03356e883b27..d9514c7cfd2a 100644 --- a/drivers/rpmsg/rpmsg_internal.h +++ b/drivers/rpmsg/rpmsg_internal.h @@ -89,10 +89,19 @@ struct device *rpmsg_find_device(struct device *parent, */ static inline int rpmsg_chrdev_register_device(struct rpmsg_device *rpdev) { - strcpy(rpdev->id.name, "rpmsg_chrdev"); - rpdev->driver_override = "rpmsg_chrdev"; + int ret; - return rpmsg_register_device(rpdev); + strcpy(rpdev->id.name, "rpmsg_chrdev"); + ret = driver_set_override(&rpdev->dev, &rpdev->driver_override, + rpdev->id.name, strlen(rpdev->id.name)); + if (ret) + return ret; + + ret = rpmsg_register_device(rpdev); + if (ret) + kfree(rpdev->driver_override); + + return ret; } #endif diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index 7cbb0fbf7d8f..33ec09a341ad 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -42,7 +42,9 @@ struct rpmsg_channel_info { * rpmsg_device - device that belong to the rpmsg bus * @dev: the device struct * @id: device id (used to match between rpmsg drivers and devices) - * @driver_override: driver name to force a match + * @driver_override: driver name to force a match; do not set directly, + * because core frees it; use driver_set_override() to + * set or clear it. * @src: local address * @dst: destination address * @ept: the rpmsg endpoint of this channel @@ -51,7 +53,7 @@ struct rpmsg_channel_info { struct rpmsg_device { struct device dev; struct rpmsg_device_id id; - char *driver_override; + const char *driver_override; u32 src; u32 dst; struct rpmsg_endpoint *ept; From fa6692abc29490f03e264d4141924d9858cfdbe4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 31 Oct 2023 11:25:38 +0000 Subject: [PATCH 11/31] BACKPORT: rpmsg: Fix calling device_lock() on non-initialized device commit bb17d110cbf270d5247a6e261c5ad50e362d1675 upstream. driver_set_override() helper uses device_lock() so it should not be called before rpmsg_register_device() (which calls device_register()). Effect can be seen with CONFIG_DEBUG_MUTEXES: DEBUG_LOCKS_WARN_ON(lock->magic != lock) WARNING: CPU: 3 PID: 57 at kernel/locking/mutex.c:582 __mutex_lock+0x1ec/0x430 ... Call trace: __mutex_lock+0x1ec/0x430 mutex_lock_nested+0x44/0x50 driver_set_override+0x124/0x150 qcom_glink_native_probe+0x30c/0x3b0 glink_rpm_probe+0x274/0x350 platform_probe+0x6c/0xe0 really_probe+0x17c/0x3d0 __driver_probe_device+0x114/0x190 driver_probe_device+0x3c/0xf0 ... Refactor the rpmsg_register_device() function to use two-step device registering (initialization + add) and call driver_set_override() in proper moment. This moves the code around, so while at it also NULL-ify the rpdev->driver_override in error path to be sure it won't be kfree() second time. Bug: 295334746 Fixes: 42cd402b8fd4 ("rpmsg: Fix kfree() of static memory on setting driver_override") Reported-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski Tested-by: Marek Szyprowski Link: https://lore.kernel.org/r/20220429195946.1061725-2-krzysztof.kozlowski@linaro.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman (cherry picked from commit bfd4a664ddfbe12f008efb0b0ab6bf25a8ab2538) [Lee: Git was confused that the hunk being removed had changed] Signed-off-by: Lee Jones Change-Id: Ic07d9ff669e88a50354ad8e978ae8e93316a2a5e --- drivers/rpmsg/rpmsg_core.c | 33 ++++++++++++++++++++++++++++++--- drivers/rpmsg/rpmsg_internal.h | 14 +------------- include/linux/rpmsg.h | 8 ++++++++ 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 53cc59eeb662..769f9703002d 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -566,24 +566,51 @@ static struct bus_type rpmsg_bus = { .remove = rpmsg_dev_remove, }; -int rpmsg_register_device(struct rpmsg_device *rpdev) +/* + * A helper for registering rpmsg device with driver override and name. + * Drivers should not be using it, but instead rpmsg_register_device(). + */ +int rpmsg_register_device_override(struct rpmsg_device *rpdev, + const char *driver_override) { struct device *dev = &rpdev->dev; int ret; + if (driver_override) + strcpy(rpdev->id.name, driver_override); + dev_set_name(&rpdev->dev, "%s.%s.%d.%d", dev_name(dev->parent), rpdev->id.name, rpdev->src, rpdev->dst); rpdev->dev.bus = &rpmsg_bus; - ret = device_register(&rpdev->dev); + device_initialize(dev); + if (driver_override) { + ret = driver_set_override(dev, &rpdev->driver_override, + driver_override, + strlen(driver_override)); + if (ret) { + dev_err(dev, "device_set_override failed: %d\n", ret); + return ret; + } + } + + ret = device_add(dev); if (ret) { - dev_err(dev, "device_register failed: %d\n", ret); + dev_err(dev, "device_add failed: %d\n", ret); + kfree(rpdev->driver_override); + rpdev->driver_override = NULL; put_device(&rpdev->dev); } return ret; } +EXPORT_SYMBOL(rpmsg_register_device_override); + +int rpmsg_register_device(struct rpmsg_device *rpdev) +{ + return rpmsg_register_device_override(rpdev, NULL); +} EXPORT_SYMBOL(rpmsg_register_device); /* diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h index d9514c7cfd2a..23509e7b8312 100644 --- a/drivers/rpmsg/rpmsg_internal.h +++ b/drivers/rpmsg/rpmsg_internal.h @@ -89,19 +89,7 @@ struct device *rpmsg_find_device(struct device *parent, */ static inline int rpmsg_chrdev_register_device(struct rpmsg_device *rpdev) { - int ret; - - strcpy(rpdev->id.name, "rpmsg_chrdev"); - ret = driver_set_override(&rpdev->dev, &rpdev->driver_override, - rpdev->id.name, strlen(rpdev->id.name)); - if (ret) - return ret; - - ret = rpmsg_register_device(rpdev); - if (ret) - kfree(rpdev->driver_override); - - return ret; + return rpmsg_register_device_override(rpdev, "rpmsg_ctrl"); } #endif diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index 33ec09a341ad..5c2420b6a734 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -122,6 +122,8 @@ struct rpmsg_driver { #if IS_ENABLED(CONFIG_RPMSG) +int rpmsg_register_device_override(struct rpmsg_device *rpdev, + const char *driver_override); int register_rpmsg_device(struct rpmsg_device *dev); void unregister_rpmsg_device(struct rpmsg_device *dev); int __register_rpmsg_driver(struct rpmsg_driver *drv, struct module *owner); @@ -149,6 +151,12 @@ int rpmsg_set_signals(struct rpmsg_endpoint *ept, u32 set, u32 clear); #else +static inline int rpmsg_register_device_override(struct rpmsg_device *rpdev, + const char *driver_override) +{ + return -ENXIO; +} + static inline int register_rpmsg_device(struct rpmsg_device *dev) { return -ENXIO; From 0f4467ff35d9f83620a138d4707e71cabc05067b Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 31 Oct 2023 11:25:39 +0000 Subject: [PATCH 12/31] UPSTREAM: rpmsg: glink: Release driver_override commit fb80ef67e8ff6a00d3faad4cb348dafdb8eccfd8 upstream. Upon termination of the rpmsg_device, driver_override needs to be freed to avoid leaking the potentially assigned string. Bug: 295334746 Fixes: 42cd402b8fd4 ("rpmsg: Fix kfree() of static memory on setting driver_override") Fixes: 39e47767ec9b ("rpmsg: Add driver_override device attribute for rpmsg_device") Reviewed-by: Chris Lew Signed-off-by: Bjorn Andersson Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230109223931.1706429-1-quic_bjorande@quicinc.com Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman (cherry picked from commit a82e0fda8a2f8561a6a6681e8b3557e60cad17da) Signed-off-by: Lee Jones Change-Id: I08b147ad640a8e2d71699a09815bbf048425a1fd --- drivers/rpmsg/qcom_glink_native.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index e776d1bfc976..28b6ae0e1a2f 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1379,6 +1379,7 @@ static void qcom_glink_rpdev_release(struct device *dev) struct glink_channel *channel = to_glink_channel(rpdev->ept); channel->rpdev = NULL; + kfree(rpdev->driver_override); kfree(rpdev); } @@ -1607,6 +1608,7 @@ static void qcom_glink_device_release(struct device *dev) /* Release qcom_glink_alloc_channel() reference */ kref_put(&channel->refcount, qcom_glink_channel_release); + kfree(rpdev->driver_override); kfree(rpdev); } From 4172086503153cca9147bcec3ccb9bfe79a01ae6 Mon Sep 17 00:00:00 2001 From: Hangyu Hua Date: Tue, 31 Oct 2023 11:25:40 +0000 Subject: [PATCH 13/31] UPSTREAM: rpmsg: Fix possible refcount leak in rpmsg_register_device_override() commit d7bd416d35121c95fe47330e09a5c04adbc5f928 upstream. rpmsg_register_device_override need to call put_device to free vch when driver_set_override fails. Fix this by adding a put_device() to the error path. Bug: 295334746 Fixes: bb17d110cbf2 ("rpmsg: Fix calling device_lock() on non-initialized device") Reviewed-by: Krzysztof Kozlowski Signed-off-by: Hangyu Hua Link: https://lore.kernel.org/r/20220624024120.11576-1-hbh25y@gmail.com Signed-off-by: Mathieu Poirier Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman (cherry picked from commit d4c8bf5635c4bedaf2470761ced1f502b2d5434e) Signed-off-by: Lee Jones Change-Id: I10440a18479d5d207bafb706311c0467b853cf6c --- drivers/rpmsg/rpmsg_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 769f9703002d..66d1157c6475 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -591,6 +591,7 @@ int rpmsg_register_device_override(struct rpmsg_device *rpdev, strlen(driver_override)); if (ret) { dev_err(dev, "device_set_override failed: %d\n", ret); + put_device(dev); return ret; } } From 72b5689f0260203514fa7497c8dae02d349bf3b6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 25 Nov 2023 18:15:03 +0000 Subject: [PATCH 14/31] ANDROID: fix up platform_device ABI break In commit 063444d66f90 ("driver: platform: Add helper for safer setting of driver_override"), a pointer was changed to const, which messes with the CRC and ABI checks. As the code is fine if this is left as not-const, just put it back to preserve the abi. Bug: 161946584 Fixes: 063444d66f90 ("driver: platform: Add helper for safer setting of driver_override") Signed-off-by: Greg Kroah-Hartman Change-Id: Ieb4a730a6a5767d31fbec2f1ba683617f5cda7a9 (cherry picked from commit c4dd1cfc1d5a7ce8ec37fe4ce11d3ce58bc6f3e9) Signed-off-by: Lee Jones --- drivers/base/platform.c | 2 +- include/linux/platform_device.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 647066229fec..e7749a9f061a 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1048,7 +1048,7 @@ static ssize_t driver_override_store(struct device *dev, struct platform_device *pdev = to_platform_device(dev); int ret; - ret = driver_set_override(dev, &pdev->driver_override, buf, count); + ret = driver_set_override(dev, (const char **)&pdev->driver_override, buf, count); if (ret) return ret; diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 43976e8901c4..a829a769296a 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -35,7 +35,7 @@ struct platform_device { * Driver name to force a match. Do not set directly, because core * frees it. Use driver_set_override() to set or clear it. */ - const char *driver_override; + char *driver_override; /* MFD cell pointer */ struct mfd_cell *mfd_cell; From ced76f823f64864ce9e0da82f78191c9d01198fb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 26 Nov 2023 12:55:14 +0000 Subject: [PATCH 15/31] ANDROID: fix up rpmsg_device ABI break In commit e70898ae1a42 ("rpmsg: Fix kfree() of static memory on setting driver_override") a pointer was changed to const, which messes with the CRC and ABI checks. As the code is fine if this is left as not-const, just put it back to preserve the abi. Bug: 161946584 Fixes: e70898ae1a42 ("rpmsg: Fix kfree() of static memory on setting driver_override") Change-Id: I9a87b9cf412191d9872b48f1f876a81df6701de0 Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 4f2270e2bca1854ebe8be23a82f665eaa27ee831) Signed-off-by: Lee Jones --- drivers/rpmsg/rpmsg_core.c | 2 +- include/linux/rpmsg.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 66d1157c6475..3c6fd032919f 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -586,7 +586,7 @@ int rpmsg_register_device_override(struct rpmsg_device *rpdev, device_initialize(dev); if (driver_override) { - ret = driver_set_override(dev, &rpdev->driver_override, + ret = driver_set_override(dev, (const char **)&rpdev->driver_override, driver_override, strlen(driver_override)); if (ret) { diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index 5c2420b6a734..7e2a4f24fda1 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -53,7 +53,7 @@ struct rpmsg_channel_info { struct rpmsg_device { struct device dev; struct rpmsg_device_id id; - const char *driver_override; + char *driver_override; u32 src; u32 dst; struct rpmsg_endpoint *ept; From 1b6cfcd1ed7fb3ba5442b29bc0dca3174991ee89 Mon Sep 17 00:00:00 2001 From: Yongqin Liu Date: Fri, 1 Dec 2023 12:37:19 +0800 Subject: [PATCH 16/31] ANDROID: GKI: db845c: Update symbols list and ABI on rpmsg_register_device_override android12-5.10 is broken on Dragonboard 845c because of recently added symbol, rpmsg_register_device_override. So updated the symbols list by running: "BUILD_CONFIG=common/build.config.db845c \ KMI_SYMBOL_LIST_ADD_ONLY=1 build/build_abi.sh -s" And the abi_gki_aarch64 ABI by running: "BUILD_CONFIG=common/build.config.gki.aarch64 \ ABI_DEFINITION=abi_gki_aarch64.xml KMI_SYMBOL_LIST_ADD_ONLY=1 \ build/build_abi.sh --update --print-report" ======================================================== Leaf changes summary: 1 artifact changed Changed leaf types summary: 0 leaf type changed Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 1 Added function Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 0 Added variable 1 Added function: [A] 'function int rpmsg_register_device_override(rpmsg_device*, const char*)' ======================================================== Bug: 313495196 Change-Id: I3a3504b6d2061bfce0abe9801e2ecb210c337b9f Signed-off-by: Yongqin Liu Signed-off-by: Isaac J. Manjarres --- android/abi_gki_aarch64.xml | 297 ++++++++++----------------------- android/abi_gki_aarch64_db845c | 33 ++-- 2 files changed, 112 insertions(+), 218 deletions(-) diff --git a/android/abi_gki_aarch64.xml b/android/abi_gki_aarch64.xml index 2a0237ec5e8d..7853b83247ed 100644 --- a/android/abi_gki_aarch64.xml +++ b/android/abi_gki_aarch64.xml @@ -4726,6 +4726,7 @@ + @@ -9274,33 +9275,33 @@ - + - + - + - + - + - + - + - + - + - + @@ -13279,7 +13280,6 @@ - @@ -15496,7 +15496,6 @@ - @@ -20273,24 +20272,24 @@ - + - + - + - + - + - + - + @@ -22463,11 +22462,6 @@ - - - - - @@ -24441,17 +24435,6 @@ - - - - - - - - - - - @@ -45196,11 +45179,7 @@ - - - - - + @@ -47013,7 +46992,7 @@ - + @@ -50539,7 +50518,6 @@ - @@ -54182,11 +54160,6 @@ - - - - - @@ -56482,19 +56455,19 @@ - + - + - + - + - + @@ -66264,14 +66237,6 @@ - - - - - - - - @@ -68766,11 +68731,6 @@ - - - - - @@ -72893,7 +72853,6 @@ - @@ -73565,11 +73524,7 @@ - - - - - + @@ -77279,30 +77234,30 @@ - + - + - + - + - + - + - + - + - + @@ -78320,11 +78275,6 @@ - - - - - @@ -81575,42 +81525,42 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -82839,7 +82789,6 @@ - @@ -84788,12 +84737,6 @@ - - - - - - @@ -86614,7 +86557,6 @@ - @@ -89176,53 +89118,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -90740,7 +90635,6 @@ - @@ -91980,7 +91874,6 @@ - @@ -95950,17 +95843,6 @@ - - - - - - - - - - - @@ -110250,7 +110132,7 @@ - + @@ -111978,30 +111860,30 @@ - + - + - + - + - + - + - + - + - + @@ -117954,9 +117836,9 @@ - - - + + + @@ -128585,29 +128467,29 @@ - - - + + + - - - - - + + + + + - - + + - - - + + + - - + + @@ -140375,7 +140257,7 @@ - + @@ -140426,9 +140308,9 @@ - - - + + + @@ -142330,8 +142212,13 @@ - - + + + + + + + @@ -142366,9 +142253,9 @@ - - - + + + @@ -147927,8 +147814,8 @@ - - + + diff --git a/android/abi_gki_aarch64_db845c b/android/abi_gki_aarch64_db845c index acbd8c5a6d04..ea98679922c1 100644 --- a/android/abi_gki_aarch64_db845c +++ b/android/abi_gki_aarch64_db845c @@ -213,7 +213,6 @@ gpiochip_generic_request gpiochip_get_data gpiochip_remove - gpiod_direction_output gpiod_direction_output_raw gpiod_set_consumer_name gpiod_set_raw_value @@ -469,10 +468,6 @@ qcom_smem_state_unregister queue_delayed_work_on queue_work_on - radix_tree_delete - radix_tree_insert - radix_tree_lookup - radix_tree_next_chunk ___ratelimit rational_best_approximation _raw_spin_lock @@ -526,6 +521,7 @@ reset_control_reset round_jiffies_up rpmsg_register_device + rpmsg_register_device_override rpmsg_send rpmsg_unregister_device rproc_add @@ -609,6 +605,7 @@ strncpy strnlen strpbrk + strscpy strscpy_pad strsep __sw_hweight16 @@ -761,7 +758,6 @@ skb_dequeue_tail skb_realloc_headroom strlcat - strscpy thermal_cooling_device_register vzalloc @@ -769,8 +765,8 @@ pci_clear_master pci_disable_device pci_disable_msi + pcie_capability_clear_and_set_word pcie_capability_read_word - pcie_capability_write_word pci_enable_device pci_enable_msi pci_iomap @@ -1136,9 +1132,12 @@ drm_atomic_private_obj_fini drm_atomic_private_obj_init drm_bridge_attach + drm_bridge_connector_enable_hpd + drm_bridge_connector_init + drm_bridge_detect + drm_bridge_hpd_notify drm_compat_ioctl drm_connector_has_possible_encoder - drm_connector_init_with_ddc drm_connector_list_iter_begin drm_connector_list_iter_end drm_connector_list_iter_next @@ -1285,7 +1284,6 @@ generic_file_llseek get_pid_task get_unused_fd_flags - gpiod_direction_input gpiod_get_value gpiod_set_value hdmi_audio_infoframe_pack @@ -1367,10 +1365,6 @@ tty_termios_baud_rate tty_termios_encode_baud_rate -# required by ns.ko - kernel_bind - radix_tree_iter_resume - # required by nvmem_qfprom.ko devm_nvmem_register @@ -1531,6 +1525,7 @@ srcu_notifier_chain_unregister # required by qcom_geni_serial.ko + devm_krealloc dev_pm_clear_wake_irq dev_pm_set_dedicated_wake_irq oops_in_progress @@ -1590,10 +1585,16 @@ autoremove_wake_function datagram_poll do_wait_intr_irq + kernel_bind lock_sock_nested proto_register proto_unregister + radix_tree_delete + radix_tree_insert radix_tree_iter_delete + radix_tree_iter_resume + radix_tree_lookup + radix_tree_next_chunk _raw_write_lock_bh _raw_write_unlock_bh refcount_dec_and_mutex_lock @@ -1731,6 +1732,9 @@ of_clk_add_provider of_clk_src_simple_get +# required by snd-soc-wsa881x.ko + gpiod_direction_output + # required by socinfo.ko add_device_randomness soc_device_register @@ -1807,8 +1811,11 @@ mfd_remove_devices # preserved by --additions-only + drm_connector_init_with_ddc + gpiod_direction_input idr_alloc_u32 of_clk_get_by_name + pcie_capability_write_word snd_pcm_create_iec958_consumer_hw_params snd_soc_get_volsw_sx snd_soc_info_volsw_sx From 469a933a87af27e581be81caaa3134849fef4f57 Mon Sep 17 00:00:00 2001 From: Peter Wang Date: Wed, 27 Sep 2023 11:35:57 +0800 Subject: [PATCH 17/31] UPSTREAM: ufs: core: wlun send SSU timeout recovery When runtime pm send SSU times out, the SCSI core invokes eh_host_reset_handler, which hooks function ufshcd_eh_host_reset_handler schedule eh_work and stuck at wait flush_work(&hba->eh_work). However, ufshcd_err_handler hangs in wait rpm resume. Do link recovery only in this case. Below is IO hang stack dump in kernel-6.1 kworker/4:0 D __switch_to+0x180/0x344 __schedule+0x5ec/0xa14 schedule+0x78/0xe0 schedule_timeout+0xb0/0x15c io_schedule_timeout+0x48/0x70 do_wait_for_common+0x108/0x19c wait_for_completion_io_timeout+0x50/0x78 blk_execute_rq+0x1b8/0x218 scsi_execute_cmd+0x148/0x238 ufshcd_set_dev_pwr_mode+0xe8/0x244 __ufshcd_wl_resume+0x1e0/0x45c ufshcd_wl_runtime_resume+0x3c/0x174 scsi_runtime_resume+0x7c/0xc8 __rpm_callback+0xa0/0x410 rpm_resume+0x43c/0x67c __rpm_callback+0x1f0/0x410 rpm_resume+0x460/0x67c pm_runtime_work+0xa4/0xac process_one_work+0x208/0x598 worker_thread+0x228/0x438 kthread+0x104/0x1d4 ret_from_fork+0x10/0x20 scsi_eh_0 D __switch_to+0x180/0x344 __schedule+0x5ec/0xa14 schedule+0x78/0xe0 schedule_timeout+0x44/0x15c do_wait_for_common+0x108/0x19c wait_for_completion+0x48/0x64 __flush_work+0x260/0x2d0 flush_work+0x10/0x20 ufshcd_eh_host_reset_handler+0x88/0xcc scsi_try_host_reset+0x48/0xe0 scsi_eh_ready_devs+0x934/0xa40 scsi_error_handler+0x168/0x374 kthread+0x104/0x1d4 ret_from_fork+0x10/0x20 kworker/u16:5 D __switch_to+0x180/0x344 __schedule+0x5ec/0xa14 schedule+0x78/0xe0 rpm_resume+0x114/0x67c __pm_runtime_resume+0x70/0xb4 ufshcd_err_handler+0x1a0/0xe68 process_one_work+0x208/0x598 worker_thread+0x228/0x438 kthread+0x104/0x1d4 ret_from_fork+0x10/0x20 (cherry picked from commit 971237b900c38f50e7865289a2aecb77dc7f09f3) Link: https://lore.kernel.org/all/20230927033557.13801-1-peter.wang@mediatek.com/ Change-Id: I51d4ddec2be7ef71fd333ca7658539f38eeb8c31 Signed-off-by: Peter Wang Reviewed-by: Bart Van Assche Reviewed-by: Stanley Chu Signed-off-by: Peng Zhou --- drivers/scsi/ufs/ufshcd.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 69ea2f977ba9..c22a4602a834 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -7164,6 +7164,20 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd) hba = shost_priv(cmd->device->host); + /* + * If runtime pm send SSU and got timeout, scsi_error_handler + * stuck at this function to wait for flush_work(&hba->eh_work). + * And ufshcd_err_handler(eh_work) stuck at wait for runtime pm active. + * Do ufshcd_link_recovery instead schedule eh_work can prevent + * dead lock to happen. + */ + if (hba->pm_op_in_progress) { + if (ufshcd_link_recovery(hba)) + err = FAILED; + + return err; + } + spin_lock_irqsave(hba->host->host_lock, flags); hba->force_reset = true; ufshcd_schedule_eh_work(hba); From 7b8b02fa37b883fe17993a94ce1ae1f7dfe219ab Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 21 Oct 2023 12:30:29 -0600 Subject: [PATCH 18/31] UPSTREAM: io_uring/fdinfo: lock SQ thread while retrieving thread cpu/pid commit 7644b1a1c9a7ae8ab99175989bfc8676055edb46 upstream. We could race with SQ thread exit, and if we do, we'll hit a NULL pointer dereference when the thread is cleared. Grab the SQPOLL data lock before attempting to get the task cpu and pid for fdinfo, this ensures we have a stable view of it. Bug: 309790656 Cc: stable@vger.kernel.org Link: https://bugzilla.kernel.org/show_bug.cgi?id=218032 Reviewed-by: Gabriel Krisman Bertazi Signed-off-by: Jens Axboe Signed-off-by: He Gao Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 3d7912710e5e187217313fea5c145881cfeaf952) Signed-off-by: Lee Jones Change-Id: I044e0285d4535440606ff593230b873e3145db91 --- io_uring/io_uring.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index a966de4a708b..411f406d0457 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -10248,7 +10248,7 @@ static int io_uring_show_cred(struct seq_file *m, unsigned int id, static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) { - struct io_sq_data *sq = NULL; + int sq_pid = -1, sq_cpu = -1; bool has_lock; int i; @@ -10261,13 +10261,19 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) has_lock = mutex_trylock(&ctx->uring_lock); if (has_lock && (ctx->flags & IORING_SETUP_SQPOLL)) { - sq = ctx->sq_data; - if (!sq->thread) - sq = NULL; + struct io_sq_data *sq = ctx->sq_data; + + if (mutex_trylock(&sq->lock)) { + if (sq->thread) { + sq_pid = task_pid_nr(sq->thread); + sq_cpu = task_cpu(sq->thread); + } + mutex_unlock(&sq->lock); + } } - seq_printf(m, "SqThread:\t%d\n", sq ? task_pid_nr(sq->thread) : -1); - seq_printf(m, "SqThreadCpu:\t%d\n", sq ? task_cpu(sq->thread) : -1); + seq_printf(m, "SqThread:\t%d\n", sq_pid); + seq_printf(m, "SqThreadCpu:\t%d\n", sq_cpu); seq_printf(m, "UserFiles:\t%u\n", ctx->nr_user_files); for (i = 0; has_lock && i < ctx->nr_user_files; i++) { struct file *f = io_file_from_index(ctx, i); From 85d8fb91634a627a0aab361652f0083a56327f60 Mon Sep 17 00:00:00 2001 From: Browse Zhang Date: Mon, 11 Dec 2023 15:13:19 +0800 Subject: [PATCH 19/31] ANDROID: Add vendor hook for ufs perf heuristic and error recovery Added vendor hook to consider ufs host/device perf heuristic and error recovery according to different platform/design Vendor/Platform can take necessary action according to their design/implementation Added vendor hook before calling UFS command ops - trace_android_vh_ufs_perf_huristic_ctrl Added vendor hook after sending UFS command to host - trace_android_vh_ufs_send_command_post_change Added vendor hook for abort success case - trace_android_vh_ufs_abort_success_ctrl Added vendor hook for completion response check - trace_android_vh_ufs_compl_rsp_check_done Added vendor hook for vendor specific error handling - trace_android_vh_ufs_err_handler Added vendor hook for err logs printing control - trace_android_vh_ufs_err_print_ctrl Added vendor hook for error checking flow trigger - trace_android_vh_ufs_err_check_ctrl Bug: 312806167 Change-Id: I2190afe62b60da9d47001307f858f10fc8a59986 Signed-off-by: Sanjeev Yadav Signed-off-by: Browse Zhang --- drivers/android/vendor_hooks.c | 7 +++++++ include/trace/hooks/ufshcd.h | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index 979dc6a1957d..21496961475e 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -505,6 +505,13 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_transaction_received); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_oem_binder_struct); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_special_task); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_free_buf); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ufs_perf_huristic_ctrl); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ufs_send_command_post_change); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ufs_abort_success_ctrl); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ufs_compl_rsp_check_done); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ufs_err_handler); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ufs_err_check_ctrl); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ufs_err_print_ctrl); /* * For type visibility */ diff --git a/include/trace/hooks/ufshcd.h b/include/trace/hooks/ufshcd.h index 906e02740f3f..1dc0ae956a42 100644 --- a/include/trace/hooks/ufshcd.h +++ b/include/trace/hooks/ufshcd.h @@ -75,6 +75,40 @@ DECLARE_HOOK(android_vh_ufs_update_sdev, DECLARE_HOOK(android_vh_ufs_clock_scaling, TP_PROTO(struct ufs_hba *hba, bool *force_out, bool *force_scaling, bool *scale_up), TP_ARGS(hba, force_out, force_scaling, scale_up)); + +DECLARE_HOOK(android_vh_ufs_send_command_post_change, + TP_PROTO(struct ufs_hba *hba, struct ufshcd_lrb *lrbp), + TP_ARGS(hba, lrbp)); + +DECLARE_HOOK(android_vh_ufs_perf_huristic_ctrl, + TP_PROTO(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp, int *err), + TP_ARGS(hba, lrbp, err)); + +DECLARE_HOOK(android_vh_ufs_abort_success_ctrl, + TP_PROTO(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp), + TP_ARGS(hba, lrbp)); + +DECLARE_HOOK(android_vh_ufs_err_handler, + TP_PROTO(struct ufs_hba *hba, + bool *err_handled), + TP_ARGS(hba, err_handled)); + +DECLARE_HOOK(android_vh_ufs_compl_rsp_check_done, + TP_PROTO(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp, bool *done), + TP_ARGS(hba, lrbp, done)); + +DECLARE_HOOK(android_vh_ufs_err_print_ctrl, + TP_PROTO(struct ufs_hba *hba, + bool *skip), + TP_ARGS(hba, skip)); + +DECLARE_HOOK(android_vh_ufs_err_check_ctrl, + TP_PROTO(struct ufs_hba *hba, + bool *err_check), + TP_ARGS(hba, err_check)); #endif /* _TRACE_HOOK_UFSHCD_H */ /* This part must be outside protection */ #include From 83578817d0ce8b29de9e4118f9582ad82986572a Mon Sep 17 00:00:00 2001 From: Browse Zhang Date: Mon, 11 Dec 2023 17:50:13 +0800 Subject: [PATCH 20/31] ANDROID: ABI: Update symbol list for Mediatek Add below symbols into MTK symbol list 7 function symbols added 'int __tracepoint__android_vh_ufs_perf_huristic_ctrl(void*, struct ufs_hba*, struct ufshcd_lrb*, int *)' 'int __tracepoint__android_vh_ufs_send_command_post_change( void*, struct ufs_hba*, struct ufshcd_lrb*)' 'int __tracepoint__android_vh_ufs_abort_success_ctrl(void*, struct ufs_hba*, struct ufshcd_lrb*)' 'int __tracepoint__android_vh_ufs_compl_rsp_check_done(void*, struct ufs_hba*, struct ufshcd_lrb*, bool*)' 'int __tracepoint__android_vh_ufs_err_handler(void*, struct ufs_hba*, bool*)' 'int __tracepoint__android_vh_ufs_err_check_ctrl(void*, struct ufs_hba*, bool*)' 'int __tracepoint__android_vh_ufs_err_print_ctrl(void*, struct ufs_hba*, bool*)' 7 variable symbols added 'struct __tracepoint__android_vh_ufs_perf_huristic_ctrl' 'struct __tracepoint__android_vh_ufs_send_command_post_change' 'struct __tracepoint__android_vh_ufs_abort_success_ctrl' 'struct __tracepoint__android_vh_ufs_compl_rsp_check_done' 'struct __tracepoint__android_vh_ufs_err_handler' 'struct __tracepoint__android_vh_ufs_err_check_ctrl' 'struct __tracepoint__android_vh_ufs_err_print_ctrl' Bug: 312806167 Change-Id: I0134d606c09f26e061439e5f179aab2b482fa10a Signed-off-by: Sanjeev Yadav Signed-off-by: Browse Zhang --- android/abi_gki_aarch64.xml | 927 ++++++++++++++++++++++-------------- android/abi_gki_aarch64_mtk | 14 + 2 files changed, 589 insertions(+), 352 deletions(-) diff --git a/android/abi_gki_aarch64.xml b/android/abi_gki_aarch64.xml index 7853b83247ed..ddb9a85a5a8d 100644 --- a/android/abi_gki_aarch64.xml +++ b/android/abi_gki_aarch64.xml @@ -704,12 +704,19 @@ + + + + + + + @@ -6798,12 +6805,19 @@ + + + + + + + @@ -12320,42 +12334,42 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -13280,6 +13294,7 @@ + @@ -15254,18 +15269,18 @@ - + - + - + - + - + @@ -15496,6 +15511,7 @@ + @@ -16567,18 +16583,18 @@ - + - + - + - + - + @@ -20001,39 +20017,39 @@ - + - + - + - + - + - + - + - + - + - + - + - + @@ -22462,6 +22478,11 @@ + + + + + @@ -24435,6 +24456,17 @@ + + + + + + + + + + + @@ -31833,27 +31865,27 @@ - + - + - + - + - + - + - + - + @@ -39019,24 +39051,24 @@ - + - + - + - + - + - + - + @@ -40150,18 +40182,18 @@ - + - + - + - + - + @@ -44677,7 +44709,23 @@ - + + + + + + + + + + + + + + + + + @@ -45179,7 +45227,11 @@ - + + + + + @@ -49013,6 +49065,7 @@ + @@ -50518,6 +50571,7 @@ + @@ -53969,6 +54023,13 @@ + + + + + + + @@ -54160,6 +54221,11 @@ + + + + + @@ -59143,7 +59209,7 @@ - + @@ -63760,7 +63826,7 @@ - + @@ -66237,6 +66303,14 @@ + + + + + + + + @@ -66403,15 +66477,15 @@ - + - + - + - + @@ -66621,6 +66695,13 @@ + + + + + + + @@ -67204,72 +67285,72 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -68731,6 +68812,11 @@ + + + + + @@ -70349,12 +70435,12 @@ - + - + - + @@ -72853,6 +72939,7 @@ + @@ -72903,7 +72990,7 @@ - + @@ -73524,7 +73611,11 @@ - + + + + + @@ -77343,54 +77434,54 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -78275,6 +78366,11 @@ + + + + + @@ -82789,6 +82885,7 @@ + @@ -84363,12 +84460,12 @@ - + - + - + @@ -84737,6 +84834,12 @@ + + + + + + @@ -84751,7 +84854,7 @@ - + @@ -85850,291 +85953,291 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -86557,6 +86660,7 @@ + @@ -87918,7 +88022,7 @@ - + @@ -89118,6 +89222,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -90635,6 +90786,7 @@ + @@ -91342,6 +91494,7 @@ + @@ -91874,6 +92027,7 @@ + @@ -95843,6 +95997,17 @@ + + + + + + + + + + + @@ -103101,6 +103266,12 @@ + + + + + + @@ -105994,21 +106165,21 @@ - + - + - + - + - + - + @@ -109146,87 +109317,87 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -111347,6 +111518,7 @@ + @@ -116420,9 +116592,9 @@ - + - + @@ -120733,6 +120905,12 @@ + + + + + + @@ -120753,6 +120931,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + @@ -120761,6 +120964,13 @@ + + + + + + + @@ -120775,6 +120985,12 @@ + + + + + + @@ -121713,12 +121929,19 @@ + + + + + + + @@ -147462,48 +147685,48 @@ - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + @@ -147513,13 +147736,13 @@ - - - + + + - - + + @@ -147528,31 +147751,31 @@ - - + + - - + + - - - + + + - - + + - - + + - - - - + + + + @@ -147584,91 +147807,91 @@ - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + diff --git a/android/abi_gki_aarch64_mtk b/android/abi_gki_aarch64_mtk index c27c6a7df54b..21fb3b2771a6 100644 --- a/android/abi_gki_aarch64_mtk +++ b/android/abi_gki_aarch64_mtk @@ -2227,7 +2227,14 @@ __traceiter_android_vh_snd_compr_use_pause_in_drain __traceiter_android_vh_sound_usb_support_cpu_suspend __traceiter_android_vh_syscall_prctl_finished + __traceiter_android_vh_ufs_abort_success_ctrl + __traceiter_android_vh_ufs_compl_rsp_check_done + __traceiter_android_vh_ufs_err_check_ctrl + __traceiter_android_vh_ufs_err_handler + __traceiter_android_vh_ufs_err_print_ctrl + __traceiter_android_vh_ufs_perf_huristic_ctrl __traceiter_android_vh_ufs_send_command + __traceiter_android_vh_ufs_send_command_post_change __traceiter_android_vh_ufs_send_tm_command __traceiter_cpu_frequency __traceiter_gpu_mem_total @@ -2312,7 +2319,14 @@ __tracepoint_android_vh_snd_compr_use_pause_in_drain __tracepoint_android_vh_sound_usb_support_cpu_suspend __tracepoint_android_vh_syscall_prctl_finished + __tracepoint_android_vh_ufs_abort_success_ctrl + __tracepoint_android_vh_ufs_compl_rsp_check_done + __tracepoint_android_vh_ufs_err_check_ctrl + __tracepoint_android_vh_ufs_err_handler + __tracepoint_android_vh_ufs_err_print_ctrl + __tracepoint_android_vh_ufs_perf_huristic_ctrl __tracepoint_android_vh_ufs_send_command + __tracepoint_android_vh_ufs_send_command_post_change __tracepoint_android_vh_ufs_send_tm_command __tracepoint_cpu_frequency __tracepoint_gpu_mem_total From 4246d242fa1b523d7ca8901b7fe0404d1583e078 Mon Sep 17 00:00:00 2001 From: Browse Zhang Date: Tue, 12 Dec 2023 10:06:39 +0800 Subject: [PATCH 21/31] ANDROID: scsi: ufs: add perf heuristic design Added vendor hook to consider ufs host/device perf heuristic according to different platform/design Vendor/Platform can take necessary action according to their design/implementation Added vendor hook before calling UFS command ops - trace_android_vh_ufs_perf_huristic_ctrl Added vendor hook after sending UFS command to host - trace_android_vh_ufs_send_command_post_change Added vendor hook for abort success case - trace_android_vh_ufs_abort_success_ctrl Bug: 312806167 Signed-off-by: Sanjeev Yadav Signed-off-by: Browse Zhang Change-Id: Ibd07480d1086ec82f2ba6a52e21da08750796221 --- drivers/scsi/ufs/ufshcd.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c22a4602a834..36c6646873c5 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2105,6 +2105,7 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag) } /* Make sure that doorbell is committed immediately */ wmb(); + trace_android_vh_ufs_send_command_post_change(hba, lrbp); } /** @@ -2770,7 +2771,9 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) } /* Make sure descriptors are ready before ringing the doorbell */ wmb(); - + trace_android_vh_ufs_perf_huristic_ctrl(hba, lrbp, &err); + if (err) + goto out; ufshcd_send_command(hba, tag); out: up_read(&hba->clk_scaling_lock); @@ -7049,8 +7052,10 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) outstanding = __test_and_clear_bit(tag, &hba->outstanding_reqs); spin_unlock_irqrestore(host->host_lock, flags); - if (outstanding) + if (outstanding) { ufshcd_release_scsi_cmd(hba, lrbp); + trace_android_vh_ufs_abort_success_ctrl(hba, lrbp); + } err = SUCCESS; From b39b9bde93fa039c8619ffe6a070d5d0469a8c79 Mon Sep 17 00:00:00 2001 From: Browse Zhang Date: Fri, 8 Dec 2023 09:20:43 +0800 Subject: [PATCH 22/31] ANDROID: scsi: ufs: vendor check response and recovery addition As per Vendor HW design consideration, added Vendor specific error handling flow Under the error checking flow, Vendor can check errors as per their HW design/arch and recover them accordingly. Added vendor hook for completion response check - trace_android_vh_ufs_compl_rsp_check_done Added vendor hook for vendor specific error handling - trace_android_vh_ufs_err_handler Added vendor hook for err logs printing control - trace_android_vh_ufs_err_print_ctrl Added vendor hook for error checking flow trigger - trace_android_vh_ufs_err_check_ctrl Bug: 312806167 Change-Id: I614737218537f197c68780f5b528b1948d5e29ea Signed-off-by: Sanjeev Yadav Signed-off-by: Browse Zhang --- drivers/scsi/ufs/ufshcd.c | 48 +++++++++++++++++++++++++-------------- drivers/scsi/ufs/ufshcd.h | 19 ++++++++++++++++ 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 36c6646873c5..fa7106d2c8aa 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -145,10 +145,7 @@ enum { UFSHCD_STATE_EH_SCHEDULED_NON_FATAL, }; -/* UFSHCD error handling flags */ -enum { - UFSHCD_EH_IN_PROGRESS = (1 << 0), -}; + /* UFSHCD UIC layer error flags */ enum { @@ -161,12 +158,6 @@ enum { UFSHCD_UIC_PA_GENERIC_ERROR = (1 << 6), /* Generic PA error */ }; -#define ufshcd_set_eh_in_progress(h) \ - ((h)->eh_flags |= UFSHCD_EH_IN_PROGRESS) -#define ufshcd_eh_in_progress(h) \ - ((h)->eh_flags & UFSHCD_EH_IN_PROGRESS) -#define ufshcd_clear_eh_in_progress(h) \ - ((h)->eh_flags &= ~UFSHCD_EH_IN_PROGRESS) struct ufs_pm_lvl_states ufs_pm_lvl_states[] = { {UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE}, @@ -5207,7 +5198,7 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) } /* Release the resources allocated for processing a SCSI command. */ -static void ufshcd_release_scsi_cmd(struct ufs_hba *hba, +void ufshcd_release_scsi_cmd(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { struct scsi_cmnd *cmd = lrbp->cmd; @@ -5218,6 +5209,7 @@ static void ufshcd_release_scsi_cmd(struct ufs_hba *hba, ufshcd_release(hba); ufshcd_clk_scaling_update_busy(hba); } +EXPORT_SYMBOL_GPL(ufshcd_release_scsi_cmd); /** * __ufshcd_transfer_req_compl - handle SCSI and query command completion @@ -5238,9 +5230,13 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, lrbp->compl_time_stamp = ktime_get(); cmd = lrbp->cmd; if (cmd) { + bool done = false; if (unlikely(ufshcd_should_inform_monitor(hba, lrbp))) ufshcd_update_monitor(hba, lrbp); trace_android_vh_ufs_compl_command(hba, lrbp); + trace_android_vh_ufs_compl_rsp_check_done(hba, lrbp, &done); + if (done) + return; ufshcd_add_command_trace(hba, index, "complete"); cmd->result = ufshcd_transfer_rsp_status(hba, lrbp); ufshcd_release_scsi_cmd(hba, lrbp); @@ -5807,11 +5803,13 @@ out: } /* Complete requests that have door-bell cleared */ -static void ufshcd_complete_requests(struct ufs_hba *hba) +void ufshcd_complete_requests(struct ufs_hba *hba) { ufshcd_trc_handler(hba, false); ufshcd_tmc_handler(hba); } +EXPORT_SYMBOL_GPL(ufshcd_complete_requests); + /** * ufshcd_quirk_dl_nac_errors - This function checks if error handling is @@ -5925,7 +5923,7 @@ static void ufshcd_clk_scaling_suspend(struct ufs_hba *hba, bool suspend) } } -static void ufshcd_err_handling_prepare(struct ufs_hba *hba) +void ufshcd_err_handling_prepare(struct ufs_hba *hba) { pm_runtime_get_sync(hba->dev); if (pm_runtime_status_suspended(hba->dev) || hba->is_sys_suspended) { @@ -5960,8 +5958,9 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba) up_write(&hba->clk_scaling_lock); cancel_work_sync(&hba->eeh_work); } +EXPORT_SYMBOL_GPL(ufshcd_err_handling_prepare); -static void ufshcd_err_handling_unprepare(struct ufs_hba *hba) +void ufshcd_err_handling_unprepare(struct ufs_hba *hba) { ufshcd_scsi_unblock_requests(hba); ufshcd_release(hba); @@ -5969,6 +5968,7 @@ static void ufshcd_err_handling_unprepare(struct ufs_hba *hba) ufshcd_clk_scaling_suspend(hba, false); pm_runtime_put(hba->dev); } +EXPORT_SYMBOL_GPL(ufshcd_err_handling_unprepare); static inline bool ufshcd_err_handling_should_stop(struct ufs_hba *hba) { @@ -6041,10 +6041,16 @@ static void ufshcd_err_handler(struct work_struct *work) bool err_tm = false; int err = 0, pmc_err; int tag; + bool err_handled = false; bool needs_reset = false, needs_restore = false; hba = container_of(work, struct ufs_hba, eh_work); + trace_android_vh_ufs_err_handler(hba, &err_handled); + + if (err_handled) + return; + down(&hba->host_sem); spin_lock_irqsave(hba->host->host_lock, flags); if (ufshcd_err_handling_should_stop(hba)) { @@ -6350,14 +6356,16 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status) * update the transfer error masks to sticky bits, let's do this * irrespective of current ufshcd_state. */ + bool skip = false; hba->saved_err |= hba->errors; hba->saved_uic_err |= hba->uic_error; + trace_android_vh_ufs_err_print_ctrl(hba, &skip); /* dump controller state before resetting */ - if ((hba->saved_err & + if (!skip &&((hba->saved_err & (INT_FATAL_ERRORS | UFSHCD_UIC_HIBERN8_MASK)) || (hba->saved_uic_err && - (hba->saved_uic_err != UFSHCD_UIC_PA_GENERIC_ERROR))) { + (hba->saved_uic_err != UFSHCD_UIC_PA_GENERIC_ERROR)))) { dev_err(hba->dev, "%s: saved_err 0x%x saved_uic_err 0x%x\n", __func__, hba->saved_err, hba->saved_uic_err); @@ -6422,6 +6430,7 @@ static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba) static irqreturn_t ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status) { irqreturn_t retval = IRQ_NONE; + bool err_check = false; if (intr_status & UFSHCD_UIC_MASK) retval |= ufshcd_uic_cmd_compl(hba, intr_status); @@ -6432,9 +6441,14 @@ static irqreturn_t ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status) if (intr_status & UTP_TASK_REQ_COMPL) retval |= ufshcd_tmc_handler(hba); - if (intr_status & UTP_TRANSFER_REQ_COMPL) + if (intr_status & UTP_TRANSFER_REQ_COMPL) { retval |= ufshcd_trc_handler(hba, ufshcd_has_utrlcnr(hba)); + trace_android_vh_ufs_err_check_ctrl(hba, &err_check); + if (err_check) + ufshcd_check_errors(hba, hba->errors); + } + return retval; } diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 6b80ac49908c..00a844f6dfa6 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -82,6 +82,19 @@ enum ufs_event_type { UFS_EVT_CNT, }; +/* UFSHCD error handling flags */ +enum { + UFSHCD_EH_IN_PROGRESS = (1 << 0), +}; + +#define ufshcd_set_eh_in_progress(h) \ + ((h)->eh_flags |= UFSHCD_EH_IN_PROGRESS) +#define ufshcd_eh_in_progress(h) \ + ((h)->eh_flags & UFSHCD_EH_IN_PROGRESS) +#define ufshcd_clear_eh_in_progress(h) \ + ((h)->eh_flags &= ~UFSHCD_EH_IN_PROGRESS) + + /** * struct uic_command - UIC command structure * @command: UIC command @@ -1048,6 +1061,12 @@ int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask, void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba, struct clk *refclk); void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val); void ufshcd_hba_stop(struct ufs_hba *hba); +void ufshcd_complete_requests(struct ufs_hba *hba); +void ufshcd_release_scsi_cmd(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp); +void ufshcd_err_handling_prepare(struct ufs_hba *hba); +void ufshcd_err_handling_unprepare(struct ufs_hba *hba); + static inline void check_upiu_size(void) { From 5144c1c2e3cc7f1297c6a152cdb23a539baa66e0 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 15 Dec 2023 09:35:04 +0000 Subject: [PATCH 23/31] ANDROID: Snapshot Mainline's version of checkpatch.pl Nothing fancy here. Keeping full history is not required. `git checkout mainline/master -- scripts/checkpatch.pl` This may need to be done periodically. Bug: 316492624 Signed-off-by: Lee Jones Change-Id: I4c90b50197ca7277c59e96bf332ecf795c4f3d12 --- scripts/checkpatch.pl | 1215 ++++++++++++++++++++++++++++++++--------- 1 file changed, 954 insertions(+), 261 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 0ad235ee96f9..25fdb7fda112 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -23,6 +23,9 @@ my $V = '0.32'; use Getopt::Long qw(:config no_auto_abbrev); my $quiet = 0; +my $verbose = 0; +my %verbose_messages = (); +my %verbose_emitted = (); my $tree = 1; my $chk_signoff = 1; my $chk_patch = 1; @@ -60,7 +63,9 @@ my $min_conf_desc_length = 4; my $spelling_file = "$D/spelling.txt"; my $codespell = 0; my $codespellfile = "/usr/share/codespell/dictionary.txt"; +my $user_codespellfile = ""; my $conststructsfile = "$D/const_structs.checkpatch"; +my $docsfile = "$D/../Documentation/dev-tools/checkpatch.rst"; my $typedefsfile; my $color = "auto"; my $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANCE @@ -69,6 +74,8 @@ my $git_command ='export LANGUAGE=en_US.UTF-8; git'; my $tabsize = 8; my ${CONFIG_} = "CONFIG_"; +my %maybe_linker_symbol; # for externs in c exceptions, when seen in *vmlinux.lds.h + sub help { my ($exitcode) = @_; @@ -78,6 +85,7 @@ Version: $V Options: -q, --quiet quiet + -v, --verbose verbose mode --no-tree run without a kernel tree --no-signoff do not check for 'Signed-off-by' line --patch treat FILE as patchfile (default) @@ -125,7 +133,7 @@ Options: --ignore-perl-version override checking of perl version. expect runtime errors. --codespell Use the codespell dictionary for spelling/typos - (default:/usr/share/codespell/dictionary.txt) + (default:$codespellfile) --codespellfile Use this codespell dictionary --typedefsfile Read additional types from this file --color[=WHEN] Use colors 'always', 'never', or only when output @@ -158,15 +166,51 @@ sub list_types { my $text = <$script>; close($script); - my @types = (); + my %types = (); # Also catch when type or level is passed through a variable - for ($text =~ /(?:(?:\bCHK|\bWARN|\bERROR|&\{\$msg_level})\s*\(|\$msg_type\s*=)\s*"([^"]+)"/g) { - push (@types, $_); + while ($text =~ /(?:(\bCHK|\bWARN|\bERROR|&\{\$msg_level})\s*\(|\$msg_type\s*=)\s*"([^"]+)"/g) { + if (defined($1)) { + if (exists($types{$2})) { + $types{$2} .= ",$1" if ($types{$2} ne $1); + } else { + $types{$2} = $1; + } + } else { + $types{$2} = "UNDETERMINED"; + } } - @types = sort(uniq(@types)); + print("#\tMessage type\n\n"); - foreach my $type (@types) { + if ($color) { + print(" ( Color coding: "); + print(RED . "ERROR" . RESET); + print(" | "); + print(YELLOW . "WARNING" . RESET); + print(" | "); + print(GREEN . "CHECK" . RESET); + print(" | "); + print("Multiple levels / Undetermined"); + print(" )\n\n"); + } + + foreach my $type (sort keys %types) { + my $orig_type = $type; + if ($color) { + my $level = $types{$type}; + if ($level eq "ERROR") { + $type = RED . $type . RESET; + } elsif ($level eq "WARN") { + $type = YELLOW . $type . RESET; + } elsif ($level eq "CHK") { + $type = GREEN . $type . RESET; + } + } print(++$count . "\t" . $type . "\n"); + if ($verbose && exists($verbose_messages{$orig_type})) { + my $message = $verbose_messages{$orig_type}; + $message =~ s/\n/\n\t/g; + print("\t" . $message . "\n\n"); + } } exit($exitcode); @@ -198,6 +242,46 @@ if (-f $conf) { unshift(@ARGV, @conf_args) if @conf_args; } +sub load_docs { + open(my $docs, '<', "$docsfile") + or warn "$P: Can't read the documentation file $docsfile $!\n"; + + my $type = ''; + my $desc = ''; + my $in_desc = 0; + + while (<$docs>) { + chomp; + my $line = $_; + $line =~ s/\s+$//; + + if ($line =~ /^\s*\*\*(.+)\*\*$/) { + if ($desc ne '') { + $verbose_messages{$type} = trim($desc); + } + $type = $1; + $desc = ''; + $in_desc = 1; + } elsif ($in_desc) { + if ($line =~ /^(?:\s{4,}|$)/) { + $line =~ s/^\s{4}//; + $desc .= $line; + $desc .= "\n"; + } else { + $verbose_messages{$type} = trim($desc); + $type = ''; + $desc = ''; + $in_desc = 0; + } + } + } + + if ($desc ne '') { + $verbose_messages{$type} = trim($desc); + } + close($docs); +} + # Perl's Getopt::Long allows options to take optional arguments after a space. # Prevent --color by itself from consuming other arguments foreach (@ARGV) { @@ -208,6 +292,7 @@ foreach (@ARGV) { GetOptions( 'q|quiet+' => \$quiet, + 'v|verbose!' => \$verbose, 'tree!' => \$tree, 'signoff!' => \$chk_signoff, 'patch!' => \$chk_patch, @@ -235,7 +320,7 @@ GetOptions( 'debug=s' => \%debug, 'test-only=s' => \$tst_only, 'codespell!' => \$codespell, - 'codespellfile=s' => \$codespellfile, + 'codespellfile=s' => \$user_codespellfile, 'typedefsfile=s' => \$typedefsfile, 'color=s' => \$color, 'no-color' => \$color, #keep old behaviors of -nocolor @@ -243,17 +328,54 @@ GetOptions( 'kconfig-prefix=s' => \${CONFIG_}, 'h|help' => \$help, 'version' => \$help -) or help(1); +) or $help = 2; -help(0) if ($help); +if ($user_codespellfile) { + # Use the user provided codespell file unconditionally + $codespellfile = $user_codespellfile; +} elsif (!(-f $codespellfile)) { + # If /usr/share/codespell/dictionary.txt is not present, try to find it + # under codespell's install directory: /data/dictionary.txt + if (($codespell || $help) && which("python3") ne "") { + my $python_codespell_dict = << "EOF"; +import os.path as op +import codespell_lib +codespell_dir = op.dirname(codespell_lib.__file__) +codespell_file = op.join(codespell_dir, 'data', 'dictionary.txt') +print(codespell_file, end='') +EOF + + my $codespell_dict = `python3 -c "$python_codespell_dict" 2> /dev/null`; + $codespellfile = $codespell_dict if (-f $codespell_dict); + } +} + +# $help is 1 if either -h, --help or --version is passed as option - exitcode: 0 +# $help is 2 if invalid option is passed - exitcode: 1 +help($help - 1) if ($help); + +die "$P: --git cannot be used with --file or --fix\n" if ($git && ($file || $fix)); +die "$P: --verbose cannot be used with --terse\n" if ($verbose && $terse); + +if ($color =~ /^[01]$/) { + $color = !$color; +} elsif ($color =~ /^always$/i) { + $color = 1; +} elsif ($color =~ /^never$/i) { + $color = 0; +} elsif ($color =~ /^auto$/i) { + $color = (-t STDOUT); +} else { + die "$P: Invalid color mode: $color\n"; +} + +load_docs() if ($verbose); list_types(0) if ($list_types); $fix = 1 if ($fix_inplace); $check_orig = $check; -die "$P: --git cannot be used with --file or --fix\n" if ($git && ($file || $fix)); - my $exit = 0; my $perl_version_ok = 1; @@ -268,18 +390,6 @@ if ($#ARGV < 0) { push(@ARGV, '-'); } -if ($color =~ /^[01]$/) { - $color = !$color; -} elsif ($color =~ /^always$/i) { - $color = 1; -} elsif ($color =~ /^never$/i) { - $color = 0; -} elsif ($color =~ /^auto$/i) { - $color = (-t STDOUT); -} else { - die "$P: Invalid color mode: $color\n"; -} - # skip TAB size 1 to avoid additional checks on $tabsize - 1 die "$P: Invalid TAB size: $tabsize\n" if ($tabsize < 2); @@ -382,6 +492,7 @@ our $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeIni # We need \b after 'init' otherwise 'initconst' will cause a false positive in a check our $Attribute = qr{ const| + volatile| __percpu| __nocast| __safe| @@ -404,7 +515,8 @@ our $Attribute = qr{ ____cacheline_aligned| ____cacheline_aligned_in_smp| ____cacheline_internodealigned_in_smp| - __weak + __weak| + __alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) }x; our $Modifier; our $Inline = qr{inline|__always_inline|noinline|__inline|__inline__}; @@ -416,7 +528,7 @@ our $Binary = qr{(?i)0b[01]+$Int_type?}; our $Hex = qr{(?i)0x[0-9a-f]+$Int_type?}; our $Int = qr{[0-9]+$Int_type?}; our $Octal = qr{0[0-7]+$Int_type?}; -our $String = qr{"[X\t]*"}; +our $String = qr{(?:\b[Lu])?"[X\t]*"}; our $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?}; our $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?}; our $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?}; @@ -466,10 +578,14 @@ our $typeKernelTypedefs = qr{(?x: (?:__)?(?:u|s|be|le)(?:8|16|32|64)| atomic_t )}; +our $typeStdioTypedefs = qr{(?x: + FILE +)}; our $typeTypedefs = qr{(?x: $typeC99Typedefs\b| $typeOtherOSTypedefs\b| - $typeKernelTypedefs\b + $typeKernelTypedefs\b| + $typeStdioTypedefs\b )}; our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b}; @@ -486,7 +602,7 @@ our $logFunctions = qr{(?x: our $allocFunctions = qr{(?x: (?:(?:devm_)? - (?:kv|k|v)[czm]alloc(?:_node|_array)? | + (?:kv|k|v)[czm]alloc(?:_array)?(?:_node)? | kstrdup(?:_const)? | kmemdup(?:_nul)?) | (?:\w+)?alloc_skb(?:_ip_align)? | @@ -506,6 +622,115 @@ our $signature_tags = qr{(?xi: Cc: )}; +our @link_tags = qw(Link Closes); + +#Create a search and print patterns for all these strings to be used directly below +our $link_tags_search = ""; +our $link_tags_print = ""; +foreach my $entry (@link_tags) { + if ($link_tags_search ne "") { + $link_tags_search .= '|'; + $link_tags_print .= ' or '; + } + $entry .= ':'; + $link_tags_search .= $entry; + $link_tags_print .= "'$entry'"; +} +$link_tags_search = "(?:${link_tags_search})"; + +our $tracing_logging_tags = qr{(?xi: + [=-]*> | + <[=-]* | + \[ | + \] | + start | + called | + entered | + entry | + enter | + in | + inside | + here | + begin | + exit | + end | + done | + leave | + completed | + out | + return | + [\.\!:\s]* +)}; + +sub edit_distance_min { + my (@arr) = @_; + my $len = scalar @arr; + if ((scalar @arr) < 1) { + # if underflow, return + return; + } + my $min = $arr[0]; + for my $i (0 .. ($len-1)) { + if ($arr[$i] < $min) { + $min = $arr[$i]; + } + } + return $min; +} + +sub get_edit_distance { + my ($str1, $str2) = @_; + $str1 = lc($str1); + $str2 = lc($str2); + $str1 =~ s/-//g; + $str2 =~ s/-//g; + my $len1 = length($str1); + my $len2 = length($str2); + # two dimensional array storing minimum edit distance + my @distance; + for my $i (0 .. $len1) { + for my $j (0 .. $len2) { + if ($i == 0) { + $distance[$i][$j] = $j; + } elsif ($j == 0) { + $distance[$i][$j] = $i; + } elsif (substr($str1, $i-1, 1) eq substr($str2, $j-1, 1)) { + $distance[$i][$j] = $distance[$i - 1][$j - 1]; + } else { + my $dist1 = $distance[$i][$j - 1]; #insert distance + my $dist2 = $distance[$i - 1][$j]; # remove + my $dist3 = $distance[$i - 1][$j - 1]; #replace + $distance[$i][$j] = 1 + edit_distance_min($dist1, $dist2, $dist3); + } + } + } + return $distance[$len1][$len2]; +} + +sub find_standard_signature { + my ($sign_off) = @_; + my @standard_signature_tags = ( + 'Signed-off-by:', 'Co-developed-by:', 'Acked-by:', 'Tested-by:', + 'Reviewed-by:', 'Reported-by:', 'Suggested-by:' + ); + foreach my $signature (@standard_signature_tags) { + return $signature if (get_edit_distance($sign_off, $signature) <= 2); + } + + return ""; +} + +our $obsolete_archives = qr{(?xi: + \Qfreedesktop.org/archives/dri-devel\E | + \Qlists.infradead.org\E | + \Qlkml.org\E | + \Qmail-archive.com\E | + \Qmailman.alsa-project.org/pipermail\E | + \Qmarc.info\E | + \Qozlabs.org/pipermail\E | + \Qspinics.net\E +)}; + our @typeListMisordered = ( qr{char\s+(?:un)?signed}, qr{int\s+(?:(?:un)?signed\s+)?short\s}, @@ -615,6 +840,10 @@ our %deprecated_apis = ( "rcu_barrier_sched" => "rcu_barrier", "get_state_synchronize_sched" => "get_state_synchronize_rcu", "cond_synchronize_sched" => "cond_synchronize_rcu", + "kmap" => "kmap_local_page", + "kunmap" => "kunmap_local", + "kmap_atomic" => "kmap_local_page", + "kunmap_atomic" => "kunmap_local", ); #Create a search pattern for all these strings to speed up a loop below @@ -850,9 +1079,17 @@ our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)}; our $declaration_macros = qr{(?x: (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(| (?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(| - (?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\( + (?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(| + (?:$Storage\s+)?(?:XA_STATE|XA_STATE_ORDER)\s*\( )}; +our %allow_repeated_words = ( + add => '', + added => '', + bad => '', + be => '', +); + sub deparenthesize { my ($string) = @_; return "" if (!defined($string)); @@ -910,10 +1147,10 @@ sub is_maintained_obsolete { sub is_SPDX_License_valid { my ($license) = @_; - return 1 if (!$tree || which("python") eq "" || !(-e "$root/scripts/spdxcheck.py") || !(-e "$gitroot")); + return 1 if (!$tree || which("python3") eq "" || !(-x "$root/scripts/spdxcheck.py") || !(-e "$gitroot")); my $root_path = abs_path($root); - my $status = `cd "$root_path"; echo "$license" | python scripts/spdxcheck.py -`; + my $status = `cd "$root_path"; echo "$license" | scripts/spdxcheck.py -`; return 0 if ($status ne ""); return 1; } @@ -1007,7 +1244,8 @@ sub git_commit_info { # git log --format='%H %s' -1 $line | # echo "commit $(cut -c 1-12,41-)" # done - } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) { + } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./ || + $lines[0] =~ /^fatal: bad object $commit/) { $id = undef; } else { $id = substr($lines[0], 0, 12); @@ -1152,6 +1390,7 @@ sub parse_email { my ($formatted_email) = @_; my $name = ""; + my $quoted = ""; my $name_comment = ""; my $address = ""; my $comment = ""; @@ -1183,14 +1422,20 @@ sub parse_email { } } - $comment = trim($comment); - $name = trim($name); - $name =~ s/^\"|\"$//g; - if ($name =~ s/(\s*\([^\)]+\))\s*//) { - $name_comment = trim($1); + # Extract comments from names excluding quoted parts + # "John D. (Doe)" - Do not extract + if ($name =~ s/\"(.+)\"//) { + $quoted = $1; } + while ($name =~ s/\s*($balanced_parens)\s*/ /) { + $name_comment .= trim($1); + } + $name =~ s/^[ \"]+|[ \"]+$//g; + $name = trim("$quoted $name"); + $address = trim($address); $address =~ s/^\<|\>$//g; + $comment = trim($comment); if ($name =~ /[^\w \-]/i) { ##has "must quote" chars $name =~ s/(? 1) { WARN("BAD_SIGN_OFF", - "email address '$email' might be better as '$suggested_email'\n" . $herecurr); + "Use a single name comment in email: '$email'\n" . $herecurr); + } + + + # stable@vger.kernel.org or stable@kernel.org shouldn't + # have an email name. In addition comments should strictly + # begin with a # + if ($email =~ /^.*stable\@(?:vger\.)?kernel\.org/i) { + if (($comment ne "" && $comment !~ /^#.+/) || + ($email_name ne "")) { + my $cur_name = $email_name; + my $new_comment = $comment; + $cur_name =~ s/[a-zA-Z\s\-\"]+//g; + + # Remove brackets enclosing comment text + # and # from start of comments to get comment text + $new_comment =~ s/^\((.*)\)$/$1/; + $new_comment =~ s/^\[(.*)\]$/$1/; + $new_comment =~ s/^[\s\#]+|\s+$//g; + + $new_comment = trim("$new_comment $cur_name") if ($cur_name ne $new_comment); + $new_comment = " # $new_comment" if ($new_comment ne ""); + my $new_email = "$email_address$new_comment"; + + if (WARN("BAD_STABLE_ADDRESS_STYLE", + "Invalid email format for stable: '$email', prefer '$new_email'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\Q$email\E/$new_email/; + } + } + } elsif ($comment ne "" && $comment !~ /^(?:#.+|\(.+\))$/) { + my $new_comment = $comment; + + # Extract comment text from within brackets or + # c89 style /*...*/ comments + $new_comment =~ s/^\[(.*)\]$/$1/; + $new_comment =~ s/^\/\*(.*)\*\/$/$1/; + + $new_comment = trim($new_comment); + $new_comment =~ s/^[^\w]$//; # Single lettered comment with non word character is usually a typo + $new_comment = "($new_comment)" if ($new_comment ne ""); + my $new_email = format_email($email_name, $name_comment, $email_address, $new_comment); + + if (WARN("BAD_SIGN_OFF", + "Unexpected content after email: '$email', should be: '$new_email'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\Q$email\E/$new_email/; + } } } @@ -2821,17 +3162,73 @@ sub process { if ($sign_off =~ /^co-developed-by:$/i) { if ($email eq $author) { WARN("BAD_SIGN_OFF", - "Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $rawline); + "Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . $herecurr); } if (!defined $lines[$linenr]) { WARN("BAD_SIGN_OFF", - "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline); - } elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) { + "Co-developed-by: must be immediately followed by Signed-off-by:\n" . $herecurr); + } elsif ($rawlines[$linenr] !~ /^signed-off-by:\s*(.*)/i) { WARN("BAD_SIGN_OFF", - "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]); + "Co-developed-by: must be immediately followed by Signed-off-by:\n" . $herecurr . $rawlines[$linenr] . "\n"); } elsif ($1 ne $email) { WARN("BAD_SIGN_OFF", - "Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]); + "Co-developed-by and Signed-off-by: name/email do not match\n" . $herecurr . $rawlines[$linenr] . "\n"); + } + } + +# check if Reported-by: is followed by a Closes: tag + if ($sign_off =~ /^reported(?:|-and-tested)-by:$/i) { + if (!defined $lines[$linenr]) { + WARN("BAD_REPORTED_BY_LINK", + "Reported-by: should be immediately followed by Closes: with a URL to the report\n" . $herecurr . "\n"); + } elsif ($rawlines[$linenr] !~ /^closes:\s*/i) { + WARN("BAD_REPORTED_BY_LINK", + "Reported-by: should be immediately followed by Closes: with a URL to the report\n" . $herecurr . $rawlines[$linenr] . "\n"); + } + } + } + + +# Check Fixes: styles is correct + if (!$in_header_lines && + $line =~ /^\s*fixes:?\s*(?:commit\s*)?[0-9a-f]{5,}\b/i) { + my $orig_commit = ""; + my $id = "0123456789ab"; + my $title = "commit title"; + my $tag_case = 1; + my $tag_space = 1; + my $id_length = 1; + my $id_case = 1; + my $title_has_quotes = 0; + + if ($line =~ /(\s*fixes:?)\s+([0-9a-f]{5,})\s+($balanced_parens)/i) { + my $tag = $1; + $orig_commit = $2; + $title = $3; + + $tag_case = 0 if $tag eq "Fixes:"; + $tag_space = 0 if ($line =~ /^fixes:? [0-9a-f]{5,} ($balanced_parens)/i); + + $id_length = 0 if ($orig_commit =~ /^[0-9a-f]{12}$/i); + $id_case = 0 if ($orig_commit !~ /[A-F]/); + + # Always strip leading/trailing parens then double quotes if existing + $title = substr($title, 1, -1); + if ($title =~ /^".*"$/) { + $title = substr($title, 1, -1); + $title_has_quotes = 1; + } + } + + my ($cid, $ctitle) = git_commit_info($orig_commit, $id, + $title); + + if ($ctitle ne $title || $tag_case || $tag_space || + $id_length || $id_case || !$title_has_quotes) { + if (WARN("BAD_FIXES_TAG", + "Please use correct Fixes: style 'Fixes: <12 chars of sha1> (\"\")' - ie: 'Fixes: $cid (\"$ctitle\")'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] = "Fixes: $cid (\"$ctitle\")"; } } } @@ -2845,8 +3242,11 @@ sub process { # Check for Gerrit Change-Ids not in any patch context if ($realfile eq '' && !$has_patch_separator && $line =~ /^\s*change-id:/i) { - ERROR("GERRIT_CHANGE_ID", - "Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr); + if (ERROR("GERRIT_CHANGE_ID", + "Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr) && + $fix) { + fix_delete_line($fixlinenr, $rawline); + } } # Check if the commit log is in a possible stack dump @@ -2866,13 +3266,13 @@ sub process { length($line) > 75 && !($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ || # file delta changes - $line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ || + $line =~ /^\s*(?:[\w\.\-\+]*\/)++[\w\.\-\+]+:/ || # filename then : - $line =~ /^\s*(?:Fixes:|Link:)/i || - # A Fixes: or Link: line + $line =~ /^\s*(?:Fixes:|$link_tags_search|$signature_tags)/i || + # A Fixes:, link or signature tag line $commit_log_possible_stack_dump)) { WARN("COMMIT_LOG_LONG_LINE", - "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr); + "Prefer a maximum 75 chars per line (possible unwrapped commit description?)\n" . $herecurr); $commit_log_long_line = 1; } @@ -2882,11 +3282,53 @@ sub process { $commit_log_possible_stack_dump = 0; } +# Check for odd tags before a URI/URL + if ($in_commit_log && + $line =~ /^\s*(\w+:)\s*http/ && $1 !~ /^$link_tags_search$/) { + if ($1 =~ /^v(?:ersion)?\d+/i) { + WARN("COMMIT_LOG_VERSIONING", + "Patch version information should be after the --- line\n" . $herecurr); + } else { + WARN("COMMIT_LOG_USE_LINK", + "Unknown link reference '$1', use $link_tags_print instead\n" . $herecurr); + } + } + +# Check for misuse of the link tags + if ($in_commit_log && + $line =~ /^\s*(\w+:)\s*(\S+)/) { + my $tag = $1; + my $value = $2; + if ($tag =~ /^$link_tags_search$/ && $value !~ m{^https?://}) { + WARN("COMMIT_LOG_WRONG_LINK", + "'$tag' should be followed by a public http(s) link\n" . $herecurr); + } + } + +# Check for lines starting with a # + if ($in_commit_log && $line =~ /^#/) { + if (WARN("COMMIT_COMMENT_SYMBOL", + "Commit log lines starting with '#' are dropped by git as comments\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/^/ /; + } + } + # Check for git id commit length and improperly formed commit descriptions - if ($in_commit_log && !$commit_log_possible_stack_dump && +# A correctly formed commit description is: +# commit <SHA-1 hash length 12+ chars> ("Complete commit subject") +# with the commit subject '("' prefix and '")' suffix +# This is a fairly compilicated block as it tests for what appears to be +# bare SHA-1 hash with minimum length of 5. It also avoids several types of +# possible SHA-1 matches. +# A commit match can span multiple lines so this block attempts to find a +# complete typical commit on a maximum of 3 lines + if ($perl_version_ok && + $in_commit_log && !$commit_log_possible_stack_dump && $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink|base-commit):/i && $line !~ /^This reverts commit [0-9a-f]{7,40}/ && - ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i || + (($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i || + ($line =~ /\bcommit\s*$/i && defined($rawlines[$linenr]) && $rawlines[$linenr] =~ /^\s*[0-9a-f]{5,}\b/i)) || ($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i && $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i && $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) { @@ -2896,49 +3338,62 @@ sub process { my $long = 0; my $case = 1; my $space = 1; - my $hasdesc = 0; - my $hasparens = 0; my $id = '0123456789ab'; my $orig_desc = "commit description"; my $description = ""; + my $herectx = $herecurr; + my $has_parens = 0; + my $has_quotes = 0; - if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) { - $init_char = $1; - $orig_commit = lc($2); - } elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) { - $orig_commit = lc($1); + my $input = $line; + if ($line =~ /(?:\bcommit\s+[0-9a-f]{5,}|\bcommit\s*$)/i) { + for (my $n = 0; $n < 2; $n++) { + if ($input =~ /\bcommit\s+[0-9a-f]{5,}\s*($balanced_parens)/i) { + $orig_desc = $1; + $has_parens = 1; + # Always strip leading/trailing parens then double quotes if existing + $orig_desc = substr($orig_desc, 1, -1); + if ($orig_desc =~ /^".*"$/) { + $orig_desc = substr($orig_desc, 1, -1); + $has_quotes = 1; + } + last; + } + last if ($#lines < $linenr + $n); + $input .= " " . trim($rawlines[$linenr + $n]); + $herectx .= "$rawlines[$linenr + $n]\n"; + } + $herectx = $herecurr if (!$has_parens); } - $short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i); - $long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i); - $space = 0 if ($line =~ /\bcommit [0-9a-f]/i); - $case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/); - if ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)"\)/i) { - $orig_desc = $1; - $hasparens = 1; - } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s*$/i && - defined $rawlines[$linenr] && - $rawlines[$linenr] =~ /^\s*\("([^"]+)"\)/) { - $orig_desc = $1; - $hasparens = 1; - } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("[^"]+$/i && - defined $rawlines[$linenr] && - $rawlines[$linenr] =~ /^\s*[^"]+"\)/) { - $line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)$/i; - $orig_desc = $1; - $rawlines[$linenr] =~ /^\s*([^"]+)"\)/; - $orig_desc .= " " . $1; - $hasparens = 1; + if ($input =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) { + $init_char = $1; + $orig_commit = lc($2); + $short = 0 if ($input =~ /\bcommit\s+[0-9a-f]{12,40}/i); + $long = 1 if ($input =~ /\bcommit\s+[0-9a-f]{41,}/i); + $space = 0 if ($input =~ /\bcommit [0-9a-f]/i); + $case = 0 if ($input =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/); + } elsif ($input =~ /\b([0-9a-f]{12,40})\b/i) { + $orig_commit = lc($1); } ($id, $description) = git_commit_info($orig_commit, $id, $orig_desc); if (defined($id) && - ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens)) { + ($short || $long || $space || $case || ($orig_desc ne $description) || !$has_quotes) && + $last_git_commit_id_linenr != $linenr - 1) { ERROR("GIT_COMMIT_ID", - "Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr); + "Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herectx); } + #don't report the next line if this line ends in commit and the sha1 hash is the next line + $last_git_commit_id_linenr = $linenr if ($line =~ /\bcommit\s*$/i); + } + +# Check for mailing list archives other than lore.kernel.org + if ($rawline =~ m{http.*\b$obsolete_archives}) { + WARN("PREFER_LORE_ARCHIVE", + "Use lore.kernel.org archive links when possible - see https://lore.kernel.org/lists.html\n" . $herecurr); } # Check for added, moved or deleted files @@ -2958,7 +3413,7 @@ sub process { ($line =~ /^new file mode\s*\d+\s*$/) && ($realfile =~ m@^Documentation/devicetree/bindings/.*\.txt$@)) { WARN("DT_SCHEMA_BINDING_PATCH", - "DT bindings should be in DT schema format. See: Documentation/devicetree/writing-schema.rst\n"); + "DT bindings should be in DT schema format. See: Documentation/devicetree/bindings/writing-schema.rst\n"); } # Check for wrappage within a valid hunk of the file @@ -3022,15 +3477,18 @@ sub process { # Check for various typo / spelling mistakes if (defined($misspellings) && ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) { - while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) { + while ($rawline =~ /(?:^|[^\w\-'`])($misspellings)(?:[^\w\-'`]|$)/gi) { my $typo = $1; + my $blank = copy_spacing($rawline); + my $ptr = substr($blank, 0, $-[1]) . "^" x length($typo); + my $hereptr = "$hereline$ptr\n"; my $typo_fix = $spelling_fix{lc($typo)}; $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/); $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/); my $msg_level = \&WARN; $msg_level = \&CHK if ($file); if (&{$msg_level}("TYPO_SPELLING", - "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) && + "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $hereptr) && $fix) { $fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/; } @@ -3049,20 +3507,38 @@ sub process { } # check for repeated words separated by a single space - if ($rawline =~ /^\+/ || $in_commit_log) { +# avoid false positive from list command eg, '-rw-r--r-- 1 root root' + if (($rawline =~ /^\+/ || $in_commit_log) && + $rawline !~ /[bcCdDlMnpPs\?-][rwxsStT-]{9}/) { + pos($rawline) = 1 if (!$in_commit_log); while ($rawline =~ /\b($word_pattern) (?=($word_pattern))/g) { my $first = $1; my $second = $2; - + my $start_pos = $-[1]; + my $end_pos = $+[2]; if ($first =~ /(?:struct|union|enum)/) { pos($rawline) += length($first) + length($second) + 1; next; } - next if ($first ne $second); + next if (lc($first) ne lc($second)); next if ($first eq 'long'); + # check for character before and after the word matches + my $start_char = ''; + my $end_char = ''; + $start_char = substr($rawline, $start_pos - 1, 1) if ($start_pos > ($in_commit_log ? 0 : 1)); + $end_char = substr($rawline, $end_pos, 1) if ($end_pos < length($rawline)); + + next if ($start_char =~ /^\S$/); + next if (index(" \t.,;?!", $end_char) == -1); + + # avoid repeating hex occurrences like 'ff ff fe 09 ...' + if ($first =~ /\b[0-9a-f]{2,}\b/i) { + next if (!exists($allow_repeated_words{lc($first)})); + } + if (WARN("REPEATED_WORD", "Possible repeated word: '$first'\n" . $herecurr) && $fix) { @@ -3126,47 +3602,47 @@ sub process { # Kconfig supports named choices), so use a word boundary # (\b) rather than a whitespace character (\s) $line =~ /^\+\s*(?:config|menuconfig|choice)\b/) { - my $length = 0; - my $cnt = $realcnt; - my $ln = $linenr + 1; - my $f; - my $is_start = 0; - my $is_end = 0; - for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) { - $f = $lines[$ln - 1]; - $cnt-- if ($lines[$ln - 1] !~ /^-/); - $is_end = $lines[$ln - 1] =~ /^\+/; + my $ln = $linenr; + my $needs_help = 0; + my $has_help = 0; + my $help_length = 0; + while (defined $lines[$ln]) { + my $f = $lines[$ln++]; next if ($f =~ /^-/); - last if (!$file && $f =~ /^\@\@/); + last if ($f !~ /^[\+ ]/); # !patch context - if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) { - $is_start = 1; - } elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) { - $length = -1; + if ($f =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) { + $needs_help = 1; + next; + } + if ($f =~ /^\+\s*help\s*$/) { + $has_help = 1; + next; } - $f =~ s/^.//; - $f =~ s/#.*//; - $f =~ s/^\s+//; - next if ($f =~ /^$/); + $f =~ s/^.//; # strip patch context [+ ] + $f =~ s/#.*//; # strip # directives + $f =~ s/^\s+//; # strip leading blanks + next if ($f =~ /^$/); # skip blank lines + # At the end of this Kconfig block: # This only checks context lines in the patch # and so hopefully shouldn't trigger false # positives, even though some of these are # common words in help texts - if ($f =~ /^\s*(?:config|menuconfig|choice|endchoice| - if|endif|menu|endmenu|source)\b/x) { - $is_end = 1; + if ($f =~ /^(?:config|menuconfig|choice|endchoice| + if|endif|menu|endmenu|source)\b/x) { last; } - $length++; + $help_length++ if ($has_help); } - if ($is_start && $is_end && $length < $min_conf_desc_length) { + if ($needs_help && + $help_length < $min_conf_desc_length) { + my $stat_real = get_stat_real($linenr, $ln - 1); WARN("CONFIG_DESCRIPTION", - "please write a paragraph that describes the config symbol fully\n" . $herecurr); + "please write a help paragraph that fully describes the config symbol\n" . "$here\n$stat_real\n"); } - #print "is_start<$is_start> is_end<$is_end> length<$length>\n"; } # check MAINTAINERS entries @@ -3209,13 +3685,6 @@ sub process { } } -# discourage the use of boolean for type definition attributes of Kconfig options - if ($realfile =~ /Kconfig/ && - $line =~ /^\+\s*\bboolean\b/) { - WARN("CONFIG_TYPE_BOOLEAN", - "Use of boolean is deprecated, please use bool instead.\n" . $herecurr); - } - if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) && ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) { my $flag = $1; @@ -3269,7 +3738,7 @@ sub process { my $comment = ""; if ($realfile =~ /\.(h|s|S)$/) { $comment = '/*'; - } elsif ($realfile =~ /\.(c|dts|dtsi)$/) { + } elsif ($realfile =~ /\.(c|rs|dts|dtsi)$/) { $comment = '//'; } elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc|yaml)$/) { $comment = '#'; @@ -3296,7 +3765,7 @@ sub process { "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr); } if ($realfile =~ m@^Documentation/devicetree/bindings/@ && - not $spdx_license =~ /GPL-2\.0.*BSD-2-Clause/) { + $spdx_license !~ /GPL-2\.0(?:-only)? OR BSD-2-Clause/) { my $msg_level = \&WARN; $msg_level = \&CHK if ($file); if (&{$msg_level}("SPDX_LICENSE_TAG", @@ -3306,18 +3775,23 @@ sub process { $fixed[$fixlinenr] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/; } } + if ($realfile =~ m@^include/dt-bindings/@ && + $spdx_license !~ /GPL-2\.0(?:-only)? OR \S+/) { + WARN("SPDX_LICENSE_TAG", + "DT binding headers should be licensed (GPL-2.0-only OR .*)\n" . $herecurr); + } } } } # check for embedded filenames - if ($rawline =~ /^\+.*\Q$realfile\E/) { + if ($rawline =~ /^\+.*\b\Q$realfile\E\b/) { WARN("EMBEDDED_FILENAME", "It's generally not useful to have the filename in the file\n" . $herecurr); } # check we are in a valid source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/); + next if ($realfile !~ /\.(h|c|rs|s|S|sh|dtsi|dts)$/); # check for using SPDX-License-Identifier on the wrong line number if ($realline != $checklicenseline && @@ -3393,8 +3867,18 @@ sub process { # check for adding lines without a newline. if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) { - WARN("MISSING_EOF_NEWLINE", - "adding a line without newline at end of file\n" . $herecurr); + if (WARN("MISSING_EOF_NEWLINE", + "adding a line without newline at end of file\n" . $herecurr) && + $fix) { + fix_delete_line($fixlinenr+1, "No newline at end of file"); + } + } + +# check for .L prefix local symbols in .S files + if ($realfile =~ /\.S$/ && + $line =~ /^\+\s*(?:[A-Z]+_)?SYM_[A-Z]+_(?:START|END)(?:_[A-Z_]+)?\s*\(\s*\.L/) { + WARN("AVOID_L_PREFIX", + "Avoid using '.L' prefixed local symbol names for denoting a range of code via 'SYM_*_START/END' annotations; see Documentation/core-api/asm-annotations.rst\n" . $herecurr); } # check we are in a valid source file C or perl if not then ignore this hunk @@ -3428,14 +3912,28 @@ sub process { # check for assignments on the start of a line if ($sline =~ /^\+\s+($Assignment)[^=]/) { - CHK("ASSIGNMENT_CONTINUATIONS", - "Assignment operator '$1' should be on the previous line\n" . $hereprev); + my $operator = $1; + if (CHK("ASSIGNMENT_CONTINUATIONS", + "Assignment operator '$1' should be on the previous line\n" . $hereprev) && + $fix && $prevrawline =~ /^\+/) { + # add assignment operator to the previous line, remove from current line + $fixed[$fixlinenr - 1] .= " $operator"; + $fixed[$fixlinenr] =~ s/\Q$operator\E\s*//; + } } # check for && or || at the start of a line if ($rawline =~ /^\+\s*(&&|\|\|)/) { - CHK("LOGICAL_CONTINUATIONS", - "Logical continuations should be on the previous line\n" . $hereprev); + my $operator = $1; + if (CHK("LOGICAL_CONTINUATIONS", + "Logical continuations should be on the previous line\n" . $hereprev) && + $fix && $prevrawline =~ /^\+/) { + # insert logical operator at last non-comment, non-whitepsace char on previous line + $prevline =~ /[\s$;]*$/; + my $line_end = substr($prevrawline, $-[0]); + $fixed[$fixlinenr - 1] =~ s/\Q$line_end\E$/ $operator$line_end/; + $fixed[$fixlinenr] =~ s/\Q$operator\E\s*//; + } } # check indentation starts on a tab stop @@ -3556,7 +4054,7 @@ sub process { if ($prevline =~ /^[\+ ]};?\s*$/ && $line =~ /^\+/ && !($line =~ /^\+\s*$/ || - $line =~ /^\+\s*EXPORT_SYMBOL/ || + $line =~ /^\+\s*(?:EXPORT_SYMBOL|early_param)/ || $line =~ /^\+\s*MODULE_/i || $line =~ /^\+\s*\#\s*(?:end|elif|else)/ || $line =~ /^\+[a-z_]*init/ || @@ -3585,43 +4083,48 @@ sub process { } # check for missing blank lines after declarations - if ($sline =~ /^\+\s+\S/ && #Not at char 1 - # actual declarations - ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || +# (declarations must have the same indentation and not be at the start of line) + if (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/) { + # use temporaries + my $sl = $sline; + my $pl = $prevline; + # remove $Attribute/$Sparse uses to simplify comparisons + $sl =~ s/\b(?:$Attribute|$Sparse)\b//g; + $pl =~ s/\b(?:$Attribute|$Sparse)\b//g; + if (($pl =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || # function pointer declarations - $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || + $pl =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || # foo bar; where foo is some local typedef or #define - $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || + $pl =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || # known declaration macros - $prevline =~ /^\+\s+$declaration_macros/) && + $pl =~ /^\+\s+$declaration_macros/) && # for "else if" which can look like "$Ident $Ident" - !($prevline =~ /^\+\s+$c90_Keywords\b/ || + !($pl =~ /^\+\s+$c90_Keywords\b/ || # other possible extensions of declaration lines - $prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ || + $pl =~ /(?:$Compare|$Assignment|$Operators)\s*$/ || # not starting a section or a macro "\" extended line - $prevline =~ /(?:\{\s*|\\)$/) && + $pl =~ /(?:\{\s*|\\)$/) && # looks like a declaration - !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || + !($sl =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || # function pointer declarations - $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || + $sl =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || # foo bar; where foo is some local typedef or #define - $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || + $sl =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || # known declaration macros - $sline =~ /^\+\s+$declaration_macros/ || + $sl =~ /^\+\s+$declaration_macros/ || # start of struct or union or enum - $sline =~ /^\+\s+(?:static\s+)?(?:const\s+)?(?:union|struct|enum|typedef)\b/ || + $sl =~ /^\+\s+(?:static\s+)?(?:const\s+)?(?:union|struct|enum|typedef)\b/ || # start or end of block or continuation of declaration - $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ || + $sl =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ || # bitfield continuation - $sline =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ || + $sl =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ || # other possible extensions of declaration lines - $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) && - # indentation of previous and current line are the same - (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) { - if (WARN("LINE_SPACING", - "Missing a blank line after declarations\n" . $hereprev) && - $fix) { - fix_insert_line($fixlinenr, "\+"); + $sl =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/)) { + if (WARN("LINE_SPACING", + "Missing a blank line after declarations\n" . $hereprev) && + $fix) { + fix_insert_line($fixlinenr, "\+"); + } } } @@ -3674,12 +4177,16 @@ sub process { } # check indentation of a line with a break; -# if the previous line is a goto or return and is indented the same # of tabs +# if the previous line is a goto, return or break +# and is indented the same # of tabs if ($sline =~ /^\+([\t]+)break\s*;\s*$/) { my $tabs = $1; - if ($prevline =~ /^\+$tabs(?:goto|return)\b/) { - WARN("UNNECESSARY_BREAK", - "break is not useful after a goto or return\n" . $hereprev); + if ($prevline =~ /^\+$tabs(goto|return|break)\b/) { + if (WARN("UNNECESSARY_BREAK", + "break is not useful after a $1\n" . $hereprev) && + $fix) { + fix_delete_line($fixlinenr, $rawline); + } } } @@ -4088,13 +4595,13 @@ sub process { if (defined $realline_next && exists $lines[$realline_next - 1] && !defined $suppress_export{$realline_next} && - ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ || - $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { + ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/)) { # Handle definitions which produce identifiers with # a prefix: # XXX(foo); # EXPORT_SYMBOL(something_foo); my $name = $1; + $name =~ s/^\s*($Ident).*/$1/; if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ && $name =~ /^${Ident}_$2/) { #print "FOO C name<$name>\n"; @@ -4116,8 +4623,7 @@ sub process { } if (!defined $suppress_export{$linenr} && $prevline =~ /^.\s*$/ && - ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ || - $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { + ($line =~ /EXPORT_SYMBOL.*\((.*)\)/)) { #print "FOO B <$lines[$linenr - 1]>\n"; $suppress_export{$linenr} = 2; } @@ -4128,7 +4634,8 @@ sub process { } # check for global initialisers. - if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/) { + if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/ && + !exclude_global_initialisers($realfile)) { if (ERROR("GLOBAL_INITIALISERS", "do not initialise globals to $1\n" . $herecurr) && $fix) { @@ -4207,12 +4714,24 @@ sub process { } } +# check for const static or static <non ptr type> const declarations +# prefer 'static const <foo>' over 'const static <foo>' and 'static <foo> const' + if ($sline =~ /^\+\s*const\s+static\s+($Type)\b/ || + $sline =~ /^\+\s*static\s+($BasicType)\s+const\b/) { + if (WARN("STATIC_CONST", + "Move const after static - use 'static const $1'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\bconst\s+static\b/static const/; + $fixed[$fixlinenr] =~ s/\bstatic\s+($BasicType)\s+const\b/static const $1/; + } + } + # check for non-global char *foo[] = {"bar", ...} declarations. if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) { WARN("STATIC_CONST_CHAR_ARRAY", "char * array declaration might be better as static const\n" . $herecurr); - } + } # check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo) if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) { @@ -4303,12 +4822,12 @@ sub process { } } -# avoid BUG() or BUG_ON() - if ($line =~ /\b(?:BUG|BUG_ON)\b/) { +# do not use BUG() or variants + if ($line =~ /\b(?!AA_|BUILD_|DCCP_|IDA_|KVM_|RWLOCK_|snd_|SPIN_)(?:[a-zA-Z_]*_)?BUG(?:_ON)?(?:_[A-Z_]+)?\s*\(/) { my $msg_level = \&WARN; $msg_level = \&CHK if ($file); &{$msg_level}("AVOID_BUG", - "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr); + "Do not crash the kernel unless it is absolutely unavoidable--use WARN_ON_ONCE() plus recovery code (if feasible) instead of BUG() or variants\n" . $herecurr); } # avoid LINUX_VERSION_CODE @@ -4329,16 +4848,23 @@ sub process { "printk() should include KERN_<LEVEL> facility level\n" . $herecurr); } - if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) { - my $orig = $1; +# prefer variants of (subsystem|netdev|dev|pr)_<level> to printk(KERN_<LEVEL> + if ($line =~ /\b(printk(_once|_ratelimited)?)\s*\(\s*KERN_([A-Z]+)/) { + my $printk = $1; + my $modifier = $2; + my $orig = $3; + $modifier = "" if (!defined($modifier)); my $level = lc($orig); $level = "warn" if ($level eq "warning"); my $level2 = $level; $level2 = "dbg" if ($level eq "debug"); + $level .= $modifier; + $level2 .= $modifier; WARN("PREFER_PR_LEVEL", - "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr); + "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to $printk(KERN_$orig ...\n" . $herecurr); } +# prefer dev_<level> to dev_printk(KERN_<LEVEL> if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) { my $orig = $1; my $level = lc($orig); @@ -4522,7 +5048,7 @@ sub process { if|for|while|switch|return|case| volatile|__volatile__| __attribute__|format|__extension__| - asm|__asm__)$/x) + asm|__asm__|scoped_guard)$/x) { # cpp #define statements have non-optional spaces, ie # if there is a space between the name and the open @@ -4795,7 +5321,7 @@ sub process { # A colon needs no spaces before when it is # terminating a case value or a label. } elsif ($opv eq ':C' || $opv eq ':L') { - if ($ctx =~ /Wx./) { + if ($ctx =~ /Wx./ and $realfile !~ m@.*\.lds\.h$@) { if (ERROR("SPACING", "space prohibited before that '$op' $at\n" . $hereptr)) { $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); @@ -4879,7 +5405,7 @@ sub process { ## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) { ## ## # Remove any bracketed sections to ensure we do not -## # falsly report the parameters of functions. +## # falsely report the parameters of functions. ## my $ln = $line; ## while ($ln =~ s/\([^\(\)]*\)//g) { ## } @@ -5009,9 +5535,13 @@ sub process { } } -#goto labels aren't indented, allow a single space however - if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and - !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { +# check that goto labels aren't indented (allow a single space indentation) +# and ignore bitfield definitions like foo:1 +# Strictly, labels can have whitespace after the identifier and before the : +# but this is not allowed here as many ?: uses would appear to be labels + if ($sline =~ /^.\s+[A-Za-z_][A-Za-z\d_]*:(?!\s*\d+)/ && + $sline !~ /^. [A-Za-z\d_][A-Za-z\d_]*:/ && + $sline !~ /^.\s+default:/) { if (WARN("INDENTED_LABEL", "labels should not be indented\n" . $herecurr) && $fix) { @@ -5058,7 +5588,7 @@ sub process { $lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) { WARN("RETURN_VOID", "void function return statements are not generally useful\n" . $hereprev); - } + } # if statements using unnecessary parentheses - ie: if ((foo == bar)) if ($perl_version_ok && @@ -5106,7 +5636,7 @@ sub process { # Return of what appears to be an errno should normally be negative if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) { my $name = $1; - if ($name ne 'EOF' && $name ne 'ERROR') { + if ($name ne 'EOF' && $name ne 'ERROR' && $name !~ /^EPOLL/) { WARN("USE_NEGATIVE_ERRNO", "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr); } @@ -5149,6 +5679,7 @@ sub process { defined($stat) && defined($cond) && $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) { my ($s, $c) = ($stat, $cond); + my $fixed_assign_in_if = 0; if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) { if (ERROR("ASSIGN_IN_IF", @@ -5173,6 +5704,7 @@ sub process { $newline .= ')'; $newline .= " {" if (defined($brace)); fix_insert_line($fixlinenr + 1, $newline); + $fixed_assign_in_if = 1; } } } @@ -5196,8 +5728,20 @@ sub process { $stat_real = "[...]\n$stat_real"; } - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr . $stat_real); + if (ERROR("TRAILING_STATEMENTS", + "trailing statements should be on next line\n" . $herecurr . $stat_real) && + !$fixed_assign_in_if && + $cond_lines == 0 && + $fix && $perl_version_ok && + $fixed[$fixlinenr] =~ /^\+(\s*)((?:if|while|for)\s*$balanced_parens)\s*(.*)$/) { + my $indent = $1; + my $test = $2; + my $rest = rtrim($4); + if ($rest =~ /;$/) { + $fixed[$fixlinenr] = "\+$indent$test"; + fix_insert_line($fixlinenr + 1, "$indent\t$rest"); + } + } } } @@ -5295,14 +5839,18 @@ sub process { #CamelCase if ($var !~ /^$Constant$/ && $var =~ /[A-Z][a-z]|[a-z][A-Z]/ && +#Ignore some autogenerated defines and enum values + $var !~ /^(?:[A-Z]+_){1,5}[A-Z]{1,3}[a-z]/ && #Ignore Page<foo> variants $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ && +#Ignore ETHTOOL_LINK_MODE_<foo> variants + $var !~ /^ETHTOOL_LINK_MODE_/ && #Ignore SI style variants like nS, mV and dB #(ie: max_uV, regulator_min_uA_show, RANGE_mA_VALUE) $var !~ /^(?:[a-z0-9_]*|[A-Z0-9_]*)?_?[a-z][A-Z](?:_[a-z0-9_]+|_[A-Z0-9_]+)?$/ && #Ignore some three character SI units explicitly, like MiB and KHz $var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) { - while ($var =~ m{($Ident)}g) { + while ($var =~ m{\b($Ident)}g) { my $word = $1; next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/); if ($check) { @@ -5432,6 +5980,7 @@ sub process { $dstat !~ /$exceptions/ && $dstat !~ /^\.$Ident\s*=/ && # .foo = $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo + $dstat !~ /^case\b/ && # case ... $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...) $dstat !~ /^while\s*$Constant\s*$Constant\s*$/ && # while (...) {...} $dstat !~ /^for\s*$Constant$/ && # for (...) @@ -5475,7 +6024,7 @@ sub process { next if ($arg =~ /\.\.\./); next if ($arg =~ /^type$/i); my $tmp_stmt = $define_stmt; - $tmp_stmt =~ s/\b(sizeof|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g; + $tmp_stmt =~ s/\b(__must_be_array|offsetof|sizeof|sizeof_field|__stringify|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g; $tmp_stmt =~ s/\#+\s*$arg\b//g; $tmp_stmt =~ s/\b$arg\s*\#\#//g; my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g; @@ -5504,6 +6053,9 @@ sub process { # check for line continuations outside of #defines, preprocessor #, and asm + } elsif ($realfile =~ m@/vmlinux.lds.h$@) { + $line =~ s/(\w+)/$maybe_linker_symbol{$1}++/ge; + #print "REAL: $realfile\nln: $line\nkeys:", sort keys %maybe_linker_symbol; } else { if ($prevline !~ /^..*\\$/ && $line !~ /^\+\s*\#.*\\$/ && # preprocessor @@ -5752,6 +6304,17 @@ sub process { "Prefer using '\"%s...\", __func__' to using '$context_function', this function's name, in a string\n" . $herecurr); } +# check for unnecessary function tracing like uses +# This does not use $logFunctions because there are many instances like +# 'dprintk(FOO, "%s()\n", __func__);' which do not match $logFunctions + if ($rawline =~ /^\+.*\([^"]*"$tracing_logging_tags{0,3}%s(?:\s*\(\s*\)\s*)?$tracing_logging_tags{0,3}(?:\\n)?"\s*,\s*__func__\s*\)\s*;/) { + if (WARN("TRACING_LOGGING", + "Unnecessary ftrace-like logging - prefer using ftrace\n" . $herecurr) && + $fix) { + fix_delete_line($fixlinenr, $rawline); + } + } + # check for spaces before a quoted newline if ($rawline =~ /^.*\".*\s\\n/) { if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", @@ -5763,7 +6326,8 @@ sub process { } # concatenated string without spaces between elements - if ($line =~ /$String[A-Za-z0-9_]/ || $line =~ /[A-Za-z0-9_]$String/) { + if ($line =~ /$String[A-Z_]/ || + ($line =~ /([A-Za-z0-9_]+)$String/ && $1 !~ /^[Lu]$/)) { if (CHK("CONCATENATED_STRING", "Concatenated strings should use spaces between elements\n" . $herecurr) && $fix) { @@ -5776,7 +6340,7 @@ sub process { } # uncoalesced string fragments - if ($line =~ /$String\s*"/) { + if ($line =~ /$String\s*[Lu]?"/) { if (WARN("STRING_FRAGMENTS", "Consecutive strings are generally better as a single string\n" . $herecurr) && $fix) { @@ -5898,6 +6462,28 @@ sub process { "Avoid logging continuation uses where feasible\n" . $herecurr); } +# check for unnecessary use of %h[xudi] and %hh[xudi] in logging functions + if (defined $stat && + $line =~ /\b$logFunctions\s*\(/ && + index($stat, '"') >= 0) { + my $lc = $stat =~ tr@\n@@; + $lc = $lc + $linenr; + my $stat_real = get_stat_real($linenr, $lc); + pos($stat_real) = index($stat_real, '"'); + while ($stat_real =~ /[^\"%]*(%[\#\d\.\*\-]*(h+)[idux])/g) { + my $pspec = $1; + my $h = $2; + my $lineoff = substr($stat_real, 0, $-[1]) =~ tr@\n@@; + if (WARN("UNNECESSARY_MODIFIER", + "Integer promotion: Using '$h' in '$pspec' is unnecessary\n" . "$here\n$stat_real\n") && + $fix && $fixed[$fixlinenr + $lineoff] =~ /^\+/) { + my $nspec = $pspec; + $nspec =~ s/h//g; + $fixed[$fixlinenr + $lineoff] =~ s/\Q$pspec\E/$nspec/; + } + } + } + # check for mask then right shift without a parentheses if ($perl_version_ok && $line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ && @@ -6144,50 +6730,68 @@ sub process { } } -# Check for __attribute__ packed, prefer __packed +# Check for compiler attributes if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) { - WARN("PREFER_PACKED", - "__packed is preferred over __attribute__((packed))\n" . $herecurr); - } + $rawline =~ /\b__attribute__\s*\(\s*($balanced_parens)\s*\)/) { + my $attr = $1; + $attr =~ s/\s*\(\s*(.*)\)\s*/$1/; -# Check for __attribute__ aligned, prefer __aligned - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) { - WARN("PREFER_ALIGNED", - "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr); - } + my %attr_list = ( + "alias" => "__alias", + "aligned" => "__aligned", + "always_inline" => "__always_inline", + "assume_aligned" => "__assume_aligned", + "cold" => "__cold", + "const" => "__attribute_const__", + "copy" => "__copy", + "designated_init" => "__designated_init", + "externally_visible" => "__visible", + "format" => "printf|scanf", + "gnu_inline" => "__gnu_inline", + "malloc" => "__malloc", + "mode" => "__mode", + "no_caller_saved_registers" => "__no_caller_saved_registers", + "noclone" => "__noclone", + "noinline" => "noinline", + "nonstring" => "__nonstring", + "noreturn" => "__noreturn", + "packed" => "__packed", + "pure" => "__pure", + "section" => "__section", + "used" => "__used", + "weak" => "__weak" + ); -# Check for __attribute__ section, prefer __section - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(.*_*section_*\s*\(\s*("[^"]*")/) { - my $old = substr($rawline, $-[1], $+[1] - $-[1]); - my $new = substr($old, 1, -1); - if (WARN("PREFER_SECTION", - "__section($new) is preferred over __attribute__((section($old)))\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*_*section_*\s*\(\s*\Q$old\E\s*\)\s*\)\s*\)/__section($new)/; + while ($attr =~ /\s*(\w+)\s*(${balanced_parens})?/g) { + my $orig_attr = $1; + my $params = ''; + $params = $2 if defined($2); + my $curr_attr = $orig_attr; + $curr_attr =~ s/^[\s_]+|[\s_]+$//g; + if (exists($attr_list{$curr_attr})) { + my $new = $attr_list{$curr_attr}; + if ($curr_attr eq "format" && $params) { + $params =~ /^\s*\(\s*(\w+)\s*,\s*(.*)/; + $new = "__$1\($2"; + } else { + $new = "$new$params"; + } + if (WARN("PREFER_DEFINED_ATTRIBUTE_MACRO", + "Prefer $new over __attribute__(($orig_attr$params))\n" . $herecurr) && + $fix) { + my $remove = "\Q$orig_attr\E" . '\s*' . "\Q$params\E" . '(?:\s*,\s*)?'; + $fixed[$fixlinenr] =~ s/$remove//; + $fixed[$fixlinenr] =~ s/\b__attribute__/$new __attribute__/; + $fixed[$fixlinenr] =~ s/\}\Q$new\E/} $new/; + $fixed[$fixlinenr] =~ s/ __attribute__\s*\(\s*\(\s*\)\s*\)//; + } + } } - } -# Check for __attribute__ format(printf, prefer __printf - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) { - if (WARN("PREFER_PRINTF", - "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex; - - } - } - -# Check for __attribute__ format(scanf, prefer __scanf - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) { - if (WARN("PREFER_SCANF", - "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex; + # Check for __attribute__ unused, prefer __always_unused or __maybe_unused + if ($attr =~ /^_*unused/) { + WARN("PREFER_DEFINED_ATTRIBUTE_MACRO", + "__always_unused or __maybe_unused is preferred over __attribute__((__unused__))\n" . $herecurr); } } @@ -6223,18 +6827,18 @@ sub process { if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) { my $cast = $1; my $const = $2; + my $suffix = ""; + my $newconst = $const; + $newconst =~ s/${Int_type}$//; + $suffix .= 'U' if ($cast =~ /\bunsigned\b/); + if ($cast =~ /\blong\s+long\b/) { + $suffix .= 'LL'; + } elsif ($cast =~ /\blong\b/) { + $suffix .= 'L'; + } if (WARN("TYPECAST_INT_CONSTANT", - "Unnecessary typecast of c90 int constant\n" . $herecurr) && + "Unnecessary typecast of c90 int constant - '$cast$const' could be '$const$suffix'\n" . $herecurr) && $fix) { - my $suffix = ""; - my $newconst = $const; - $newconst =~ s/${Int_type}$//; - $suffix .= 'U' if ($cast =~ /\bunsigned\b/); - if ($cast =~ /\blong\s+long\b/) { - $suffix .= 'LL'; - } elsif ($cast =~ /\blong\b/) { - $suffix .= 'L'; - } $fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/; } } @@ -6294,9 +6898,11 @@ sub process { $specifier = $1; $extension = $2; $qualifier = $3; - if ($extension !~ /[SsBKRraEehMmIiUDdgVCbGNOxtf]/ || + if ($extension !~ /[4SsBKRraEehMmIiUDdgVCbGNOxtf]/ || ($extension eq "f" && - defined $qualifier && $qualifier !~ /^w/)) { + defined $qualifier && $qualifier !~ /^w/) || + ($extension eq "4" && + defined $qualifier && $qualifier !~ /^cc/)) { $bad_specifier = $specifier; last; } @@ -6310,15 +6916,19 @@ sub process { } if ($bad_specifier ne "") { my $stat_real = get_stat_real($linenr, $lc); + my $msg_level = \&WARN; my $ext_type = "Invalid"; my $use = ""; if ($bad_specifier =~ /p[Ff]/) { $use = " - use %pS instead"; $use =~ s/pS/ps/ if ($bad_specifier =~ /pf/); + } elsif ($bad_specifier =~ /pA/) { + $use = " - '%pA' is only intended to be used from Rust code"; + $msg_level = \&ERROR; } - WARN("VSPRINTF_POINTER_EXTENSION", - "$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n"); + &{$msg_level}("VSPRINTF_POINTER_EXTENSION", + "$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n"); } } } @@ -6383,6 +6993,24 @@ sub process { # } # } +# strcpy uses that should likely be strscpy + if ($line =~ /\bstrcpy\s*\(/) { + WARN("STRCPY", + "Prefer strscpy over strcpy - see: https://github.com/KSPP/linux/issues/88\n" . $herecurr); + } + +# strlcpy uses that should likely be strscpy + if ($line =~ /\bstrlcpy\s*\(/) { + WARN("STRLCPY", + "Prefer strscpy over strlcpy - see: https://github.com/KSPP/linux/issues/89\n" . $herecurr); + } + +# strncpy uses that should likely be strscpy or strscpy_pad + if ($line =~ /\bstrncpy\s*\(/) { + WARN("STRNCPY", + "Prefer strscpy, strscpy_pad, or __nonstring over strncpy - see: https://github.com/KSPP/linux/issues/90\n" . $herecurr); + } + # typecasts on min/max could be min_t/max_t if ($perl_version_ok && defined $stat && @@ -6487,6 +7115,21 @@ sub process { "arguments for function declarations should follow identifier\n" . $herecurr); } + } elsif ($realfile =~ /\.c$/ && defined $stat && + $stat =~ /^\+extern struct\s+(\w+)\s+(\w+)\[\];/) + { + my ($st_type, $st_name) = ($1, $2); + + for my $s (keys %maybe_linker_symbol) { + #print "Linker symbol? $st_name : $s\n"; + goto LIKELY_LINKER_SYMBOL + if $st_name =~ /$s/; + } + WARN("AVOID_EXTERNS", + "found a file-scoped extern type:$st_type name:$st_name in .c file\n" + . "is this a linker symbol ?\n" . $herecurr); + LIKELY_LINKER_SYMBOL: + } elsif ($realfile =~ /\.c$/ && defined $stat && $stat =~ /^.\s*extern\s+/) { @@ -6555,14 +7198,16 @@ sub process { "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr); } -# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc +# check for (kv|k)[mz]alloc with multiplies that could be kmalloc_array/kvmalloc_array/kvcalloc/kcalloc if ($perl_version_ok && defined $stat && - $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) { + $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) { my $oldfunc = $3; my $a1 = $4; my $a2 = $10; my $newfunc = "kmalloc_array"; + $newfunc = "kvmalloc_array" if ($oldfunc eq "kvmalloc"); + $newfunc = "kvcalloc" if ($oldfunc eq "kvzalloc"); $newfunc = "kcalloc" if ($oldfunc eq "kzalloc"); my $r1 = $a1; my $r2 = $a2; @@ -6579,7 +7224,7 @@ sub process { "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) && $cnt == 1 && $fix) { - $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e; + $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e; } } } @@ -6593,7 +7238,7 @@ sub process { } # check for alloc argument mismatch - if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) { + if ($line =~ /\b((?:devm_)?((?:k|kv)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/) { WARN("ALLOC_ARRAY_ARGS", "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr); } @@ -6759,12 +7404,14 @@ sub process { # use of NR_CPUS is usually wrong # ignore definitions of NR_CPUS and usage to define arrays as likely right +# ignore designated initializers using NR_CPUS if ($line =~ /\bNR_CPUS\b/ && $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ && $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ && $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ && $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ && - $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/) + $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/ && + $line !~ /^.\s*\.\w+\s*=\s*.*\bNR_CPUS\b/) { WARN("NR_CPUS", "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr); @@ -6783,6 +7430,27 @@ sub process { "Using $1 should generally have parentheses around the comparison\n" . $herecurr); } +# return sysfs_emit(foo, fmt, ...) fmt without newline + if ($line =~ /\breturn\s+sysfs_emit\s*\(\s*$FuncArg\s*,\s*($String)/ && + substr($rawline, $-[6], $+[6] - $-[6]) !~ /\\n"$/) { + my $offset = $+[6] - 1; + if (WARN("SYSFS_EMIT", + "return sysfs_emit(...) formats should include a terminating newline\n" . $herecurr) && + $fix) { + substr($fixed[$fixlinenr], $offset, 0) = '\\n'; + } + } + +# check for array definition/declarations that should use flexible arrays instead + if ($sline =~ /^[\+ ]\s*\}(?:\s*__packed)?\s*;\s*$/ && + $prevline =~ /^\+\s*(?:\}(?:\s*__packed\s*)?|$Type)\s*$Ident\s*\[\s*(0|1)\s*\]\s*;\s*$/) { + if (ERROR("FLEXIBLE_ARRAY", + "Use C99 flexible arrays - see https://docs.kernel.org/process/deprecated.html#zero-length-and-one-element-arrays\n" . $hereprev) && + $1 == '0' && $fix) { + $fixed[$fixlinenr - 1] =~ s/\[\s*0\s*\]/[]/; + } + } + # nested likely/unlikely calls if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) { WARN("LIKELY_MISUSE", @@ -6800,10 +7468,28 @@ sub process { } } -# check for mutex_trylock_recursive usage - if ($line =~ /mutex_trylock_recursive/) { - ERROR("LOCKING", - "recursive locking is bad, do not use this ever.\n" . $herecurr); +# Complain about RCU Tasks Trace used outside of BPF (and of course, RCU). + our $rcu_trace_funcs = qr{(?x: + rcu_read_lock_trace | + rcu_read_lock_trace_held | + rcu_read_unlock_trace | + call_rcu_tasks_trace | + synchronize_rcu_tasks_trace | + rcu_barrier_tasks_trace | + rcu_request_urgent_qs_task + )}; + our $rcu_trace_paths = qr{(?x: + kernel/bpf/ | + include/linux/bpf | + net/bpf/ | + kernel/rcu/ | + include/linux/rcu + )}; + if ($line =~ /\b($rcu_trace_funcs)\s*\(/) { + if ($realfile !~ m{^$rcu_trace_paths}) { + WARN("RCU_TASKS_TRACE", + "use of RCU tasks trace is incorrect outside BPF or core RCU code\n" . $herecurr); + } } # check for lockdep_set_novalidate_class @@ -6947,6 +7633,13 @@ sub process { WARN("MODULE_LICENSE", "unknown module license " . $extracted_string . "\n" . $herecurr); } + if (!$file && $extracted_string eq '"GPL v2"') { + if (WARN("MODULE_LICENSE", + "Prefer \"GPL\" over \"GPL v2\" - see commit bf7fbeeae6db (\"module: Cure the MODULE_LICENSE \"GPL\" vs. \"GPL v2\" bogosity\")\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\bMODULE_LICENSE\s*\(\s*"GPL v2"\s*\)/MODULE_LICENSE("GPL")/; + } + } } # check for sysctl duplicate constants @@ -6968,7 +7661,7 @@ sub process { exit(0); } - # This is not a patch, and we are are in 'no-patch' mode so + # This is not a patch, and we are in 'no-patch' mode so # just keep quiet. if (!$chk_patch && !$is_patch) { exit(0); From f22c548c9123a71a351f9edd64219e084fe79e80 Mon Sep 17 00:00:00 2001 From: Carlos Llamas <cmllamas@google.com> Date: Fri, 8 Dec 2023 03:48:42 +0000 Subject: [PATCH 24/31] FROMLIST: binder: fix memory leaks of spam and pending work commit 1aa3aaf8953c84bad398adf6c3cabc9d6685bf7d upstream A transaction complete work is allocated and queued for each transaction. Under certain conditions the work->type might be marked as BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT to notify userspace about potential spamming threads or as BINDER_WORK_TRANSACTION_PENDING when the target is currently frozen. However, these work types are not being handled in binder_release_work() so they will leak during a cleanup. This was reported by syzkaller with the following kmemleak dump: BUG: memory leak unreferenced object 0xffff88810e2d6de0 (size 32): comm "syz-executor338", pid 5046, jiffies 4294968230 (age 13.590s) hex dump (first 32 bytes): e0 6d 2d 0e 81 88 ff ff e0 6d 2d 0e 81 88 ff ff .m-......m-..... 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffff81573b75>] kmalloc_trace+0x25/0x90 mm/slab_common.c:1114 [<ffffffff83d41873>] kmalloc include/linux/slab.h:599 [inline] [<ffffffff83d41873>] kzalloc include/linux/slab.h:720 [inline] [<ffffffff83d41873>] binder_transaction+0x573/0x4050 drivers/android/binder.c:3152 [<ffffffff83d45a05>] binder_thread_write+0x6b5/0x1860 drivers/android/binder.c:4010 [<ffffffff83d486dc>] binder_ioctl_write_read drivers/android/binder.c:5066 [inline] [<ffffffff83d486dc>] binder_ioctl+0x1b2c/0x3cf0 drivers/android/binder.c:5352 [<ffffffff816b25f2>] vfs_ioctl fs/ioctl.c:51 [inline] [<ffffffff816b25f2>] __do_sys_ioctl fs/ioctl.c:871 [inline] [<ffffffff816b25f2>] __se_sys_ioctl fs/ioctl.c:857 [inline] [<ffffffff816b25f2>] __x64_sys_ioctl+0xf2/0x140 fs/ioctl.c:857 [<ffffffff84b30008>] do_syscall_x64 arch/x86/entry/common.c:50 [inline] [<ffffffff84b30008>] do_syscall_64+0x38/0xb0 arch/x86/entry/common.c:80 [<ffffffff84c0008b>] entry_SYSCALL_64_after_hwframe+0x63/0xcd Fix the leaks by kfreeing these work types in binder_release_work() and handle them as a BINDER_WORK_TRANSACTION_COMPLETE cleanup. Cc: stable@vger.kernel.org Fixes: a7dc1e6f99df ("binder: tell userspace to dump current backtrace when detected oneway spamming") Reported-by: syzbot+7f10c1653e35933c0f1e@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=7f10c1653e35933c0f1e Suggested-by: Alice Ryhl <aliceryhl@google.com> Signed-off-by: Carlos Llamas <cmllamas@google.com> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Acked-by: Todd Kjos <tkjos@google.com> Link: https://lore.kernel.org/r/20230922175138.230331-1-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> [cmllamas: backport to v5.15 by dropping BINDER_WORK_TRANSACTION_PENDING as commit 0567461a7a6e is not present. Remove fixes tag accordingly.] Signed-off-by: Carlos Llamas <cmllamas@google.com> Signed-off-by: Sasha Levin <sashal@kernel.org> Link: https://lore.kernel.org/all/20231208034842.997899-1-cmllamas@google.com/ Change-Id: I8e1ee7af87ef5706544e4f320e9498b8f4855a6b [cmllamas: also backport to v5.10 to fix OOT 0493c72d6d0c] Signed-off-by: Carlos Llamas <cmllamas@google.com> --- drivers/android/binder.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index f767ceee9c5c..cf3ffa31dbff 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -4884,6 +4884,7 @@ static void binder_release_work(struct binder_proc *proc, "undelivered TRANSACTION_ERROR: %u\n", e->cmd); } break; + case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT: case BINDER_WORK_TRANSACTION_COMPLETE: { binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, "undelivered TRANSACTION_COMPLETE\n"); From 0edf68775aab76428256f7d30013bdeec3da9fe2 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg <sagi@grimberg.me> Date: Mon, 2 Oct 2023 13:54:28 +0300 Subject: [PATCH 25/31] UPSTREAM: nvmet-tcp: Fix a possible UAF in queue intialization setup commit d920abd1e7c4884f9ecd0749d1921b7ab19ddfbd upstream. From Alon: "Due to a logical bug in the NVMe-oF/TCP subsystem in the Linux kernel, a malicious user can cause a UAF and a double free, which may lead to RCE (may also lead to an LPE in case the attacker already has local privileges)." Hence, when a queue initialization fails after the ahash requests are allocated, it is guaranteed that the queue removal async work will be called, hence leave the deallocation to the queue removal. Also, be extra careful not to continue processing the socket, so set queue rcv_state to NVMET_TCP_RECV_ERR upon a socket error. Bug: 310114968 Cc: stable@vger.kernel.org Reported-by: Alon Zahavi <zahavi.alon@gmail.com> Tested-by: Alon Zahavi <zahavi.alon@gmail.com> Signed-off-by: Sagi Grimberg <sagi@grimberg.me> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com> Signed-off-by: Keith Busch <kbusch@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit e985d78bdcf37f7ef73666a43b0d2407715f00d3) Signed-off-by: Lee Jones <joneslee@google.com> Change-Id: Ifd7ec8294182a6bf6d8c261aeda5d989e909f7ff --- drivers/nvme/target/tcp.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index 2ddbd4f4f628..7ce22d173fc7 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -336,6 +336,7 @@ static void nvmet_tcp_fatal_error(struct nvmet_tcp_queue *queue) static void nvmet_tcp_socket_error(struct nvmet_tcp_queue *queue, int status) { + queue->rcv_state = NVMET_TCP_RECV_ERR; if (status == -EPIPE || status == -ECONNRESET) kernel_sock_shutdown(queue->sock, SHUT_RDWR); else @@ -882,15 +883,11 @@ static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue) iov.iov_len = sizeof(*icresp); ret = kernel_sendmsg(queue->sock, &msg, &iov, 1, iov.iov_len); if (ret < 0) - goto free_crypto; + return ret; /* queue removal will cleanup */ queue->state = NVMET_TCP_Q_LIVE; nvmet_prepare_receive_pdu(queue); return 0; -free_crypto: - if (queue->hdr_digest || queue->data_digest) - nvmet_tcp_free_crypto(queue); - return ret; } static void nvmet_tcp_handle_req_failure(struct nvmet_tcp_queue *queue, From 5b118b5b1db554169f91b9bd3f34a42d1678e2a7 Mon Sep 17 00:00:00 2001 From: Joerg Roedel <jroedel@suse.de> Date: Wed, 21 Jun 2023 17:42:42 +0200 Subject: [PATCH 26/31] UPSTREAM: x86/sev: Check IOBM for IOIO exceptions from user-space Upstream commit: b9cb9c45583b911e0db71d09caa6b56469eb2bdf Check the IO permission bitmap (if present) before emulating IOIO #VC exceptions for user-space. These permissions are checked by hardware already before the #VC is raised, but due to the VC-handler decoding race it needs to be checked again in software. Bug: 309733863 Fixes: 25189d08e516 ("x86/sev-es: Add support for handling IOIO exceptions") Reported-by: Tom Dohrmann <erbse.13@gmx.de> Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Tested-by: Tom Dohrmann <erbse.13@gmx.de> Cc: <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit 5bb9ba7dafbe18e027e335f74372ca65f07f7edd) Signed-off-by: Lee Jones <joneslee@google.com> Change-Id: I559d1ee6aa0793f7bfd7b5e603cdaba2336d0562 --- arch/x86/boot/compressed/sev-es.c | 5 +++++ arch/x86/kernel/sev-es-shared.c | 22 +++++++++++++++------- arch/x86/kernel/sev-es.c | 27 +++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/arch/x86/boot/compressed/sev-es.c b/arch/x86/boot/compressed/sev-es.c index 27826c265aab..0c2c87696d03 100644 --- a/arch/x86/boot/compressed/sev-es.c +++ b/arch/x86/boot/compressed/sev-es.c @@ -106,6 +106,11 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt, return ES_OK; } +static enum es_result vc_ioio_check(struct es_em_ctxt *ctxt, u16 port, size_t size) +{ + return ES_OK; +} + #undef __init #undef __pa #define __init diff --git a/arch/x86/kernel/sev-es-shared.c b/arch/x86/kernel/sev-es-shared.c index 82db4014deb2..ec699f113fa9 100644 --- a/arch/x86/kernel/sev-es-shared.c +++ b/arch/x86/kernel/sev-es-shared.c @@ -281,6 +281,9 @@ static enum es_result vc_insn_string_write(struct es_em_ctxt *ctxt, static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo) { struct insn *insn = &ctxt->insn; + size_t size; + u64 port; + *exitinfo = 0; switch (insn->opcode.bytes[0]) { @@ -289,7 +292,7 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo) case 0x6d: *exitinfo |= IOIO_TYPE_INS; *exitinfo |= IOIO_SEG_ES; - *exitinfo |= (ctxt->regs->dx & 0xffff) << 16; + port = ctxt->regs->dx & 0xffff; break; /* OUTS opcodes */ @@ -297,41 +300,43 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo) case 0x6f: *exitinfo |= IOIO_TYPE_OUTS; *exitinfo |= IOIO_SEG_DS; - *exitinfo |= (ctxt->regs->dx & 0xffff) << 16; + port = ctxt->regs->dx & 0xffff; break; /* IN immediate opcodes */ case 0xe4: case 0xe5: *exitinfo |= IOIO_TYPE_IN; - *exitinfo |= (u8)insn->immediate.value << 16; + port = (u8)insn->immediate.value & 0xffff; break; /* OUT immediate opcodes */ case 0xe6: case 0xe7: *exitinfo |= IOIO_TYPE_OUT; - *exitinfo |= (u8)insn->immediate.value << 16; + port = (u8)insn->immediate.value & 0xffff; break; /* IN register opcodes */ case 0xec: case 0xed: *exitinfo |= IOIO_TYPE_IN; - *exitinfo |= (ctxt->regs->dx & 0xffff) << 16; + port = ctxt->regs->dx & 0xffff; break; /* OUT register opcodes */ case 0xee: case 0xef: *exitinfo |= IOIO_TYPE_OUT; - *exitinfo |= (ctxt->regs->dx & 0xffff) << 16; + port = ctxt->regs->dx & 0xffff; break; default: return ES_DECODE_FAILED; } + *exitinfo |= port << 16; + switch (insn->opcode.bytes[0]) { case 0x6c: case 0x6e: @@ -341,12 +346,15 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo) case 0xee: /* Single byte opcodes */ *exitinfo |= IOIO_DATA_8; + size = 1; break; default: /* Length determined by instruction parsing */ *exitinfo |= (insn->opnd_bytes == 2) ? IOIO_DATA_16 : IOIO_DATA_32; + size = (insn->opnd_bytes == 2) ? 2 : 4; } + switch (insn->addr_bytes) { case 2: *exitinfo |= IOIO_ADDR_16; @@ -362,7 +370,7 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo) if (insn_has_rep_prefix(insn)) *exitinfo |= IOIO_REP; - return ES_OK; + return vc_ioio_check(ctxt, (u16)port, size); } static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt) diff --git a/arch/x86/kernel/sev-es.c b/arch/x86/kernel/sev-es.c index f441002c2327..c9e0aef15d79 100644 --- a/arch/x86/kernel/sev-es.c +++ b/arch/x86/kernel/sev-es.c @@ -448,6 +448,33 @@ static enum es_result vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt return ES_OK; } +static enum es_result vc_ioio_check(struct es_em_ctxt *ctxt, u16 port, size_t size) +{ + BUG_ON(size > 4); + + if (user_mode(ctxt->regs)) { + struct thread_struct *t = ¤t->thread; + struct io_bitmap *iobm = t->io_bitmap; + size_t idx; + + if (!iobm) + goto fault; + + for (idx = port; idx < port + size; ++idx) { + if (test_bit(idx, iobm->bitmap)) + goto fault; + } + } + + return ES_OK; + +fault: + ctxt->fi.vector = X86_TRAP_GP; + ctxt->fi.error_code = 0; + + return ES_EXCEPTION; +} + /* Include code shared with pre-decompression boot stage */ #include "sev-es-shared.c" From 718225bcc1ee7d9c11a1d323cd342389690e715e Mon Sep 17 00:00:00 2001 From: Joerg Roedel <jroedel@suse.de> Date: Mon, 16 Oct 2023 14:42:50 +0200 Subject: [PATCH 27/31] UPSTREAM: x86/sev: Check for user-space IOIO pointing to kernel space Upstream commit: 63e44bc52047f182601e7817da969a105aa1f721 Check the memory operand of INS/OUTS before emulating the instruction. The #VC exception can get raised from user-space, but the memory operand can be manipulated to access kernel memory before the emulation actually begins and after the exception handler has run. [ bp: Massage commit message. ] Bug: 309733863 Fixes: 597cfe48212a ("x86/boot/compressed/64: Setup a GHCB-based VC Exception handler") Reported-by: Tom Dohrmann <erbse.13@gmx.de> Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Cc: <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit 6550cbe25de182f6c0176909a90b324cb375133f) Signed-off-by: Lee Jones <joneslee@google.com> Change-Id: Ie21d33ca750d1668244c9a954cb7ab6872066c2e --- arch/x86/boot/compressed/sev-es.c | 5 +++++ arch/x86/kernel/sev-es-shared.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/arch/x86/boot/compressed/sev-es.c b/arch/x86/boot/compressed/sev-es.c index 0c2c87696d03..e23748fa2d5f 100644 --- a/arch/x86/boot/compressed/sev-es.c +++ b/arch/x86/boot/compressed/sev-es.c @@ -111,6 +111,11 @@ static enum es_result vc_ioio_check(struct es_em_ctxt *ctxt, u16 port, size_t si return ES_OK; } +static bool fault_in_kernel_space(unsigned long address) +{ + return false; +} + #undef __init #undef __pa #define __init diff --git a/arch/x86/kernel/sev-es-shared.c b/arch/x86/kernel/sev-es-shared.c index ec699f113fa9..e9f8a2bc5de9 100644 --- a/arch/x86/kernel/sev-es-shared.c +++ b/arch/x86/kernel/sev-es-shared.c @@ -217,6 +217,23 @@ fail: asm volatile("hlt\n"); } +static enum es_result vc_insn_string_check(struct es_em_ctxt *ctxt, + unsigned long address, + bool write) +{ + if (user_mode(ctxt->regs) && fault_in_kernel_space(address)) { + ctxt->fi.vector = X86_TRAP_PF; + ctxt->fi.error_code = X86_PF_USER; + ctxt->fi.cr2 = address; + if (write) + ctxt->fi.error_code |= X86_PF_WRITE; + + return ES_EXCEPTION; + } + + return ES_OK; +} + static enum es_result vc_insn_string_read(struct es_em_ctxt *ctxt, void *src, char *buf, unsigned int data_size, @@ -224,7 +241,12 @@ static enum es_result vc_insn_string_read(struct es_em_ctxt *ctxt, bool backwards) { int i, b = backwards ? -1 : 1; - enum es_result ret = ES_OK; + unsigned long address = (unsigned long)src; + enum es_result ret; + + ret = vc_insn_string_check(ctxt, address, false); + if (ret != ES_OK) + return ret; for (i = 0; i < count; i++) { void *s = src + (i * data_size * b); @@ -245,7 +267,12 @@ static enum es_result vc_insn_string_write(struct es_em_ctxt *ctxt, bool backwards) { int i, s = backwards ? -1 : 1; - enum es_result ret = ES_OK; + unsigned long address = (unsigned long)dst; + enum es_result ret; + + ret = vc_insn_string_check(ctxt, address, true); + if (ret != ES_OK) + return ret; for (i = 0; i < count; i++) { void *d = dst + (i * data_size * s); From a72131befe6fe21a2ed8915196e1e2d1eafc1220 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao <shaozhengchao@huawei.com> Date: Thu, 23 Nov 2023 15:13:14 +0800 Subject: [PATCH 28/31] UPSTREAM: ipv4: igmp: fix refcnt uaf issue when receiving igmp query packet [ Upstream commit e2b706c691905fe78468c361aaabc719d0a496f1 ] When I perform the following test operations: 1.ip link add br0 type bridge 2.brctl addif br0 eth0 3.ip addr add 239.0.0.1/32 dev eth0 4.ip addr add 239.0.0.1/32 dev br0 5.ip addr add 224.0.0.1/32 dev br0 6.while ((1)) do ifconfig br0 up ifconfig br0 down done 7.send IGMPv2 query packets to port eth0 continuously. For example, ./mausezahn ethX -c 0 "01 00 5e 00 00 01 00 72 19 88 aa 02 08 00 45 00 00 1c 00 01 00 00 01 02 0e 7f c0 a8 0a b7 e0 00 00 01 11 64 ee 9b 00 00 00 00" The preceding tests may trigger the refcnt uaf issue of the mc list. The stack is as follows: refcount_t: addition on 0; use-after-free. WARNING: CPU: 21 PID: 144 at lib/refcount.c:25 refcount_warn_saturate (lib/refcount.c:25) CPU: 21 PID: 144 Comm: ksoftirqd/21 Kdump: loaded Not tainted 6.7.0-rc1-next-20231117-dirty #80 Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 RIP: 0010:refcount_warn_saturate (lib/refcount.c:25) RSP: 0018:ffffb68f00657910 EFLAGS: 00010286 RAX: 0000000000000000 RBX: ffff8a00c3bf96c0 RCX: ffff8a07b6160908 RDX: 00000000ffffffd8 RSI: 0000000000000027 RDI: ffff8a07b6160900 RBP: ffff8a00cba36862 R08: 0000000000000000 R09: 00000000ffff7fff R10: ffffb68f006577c0 R11: ffffffffb0fdcdc8 R12: ffff8a00c3bf9680 R13: ffff8a00c3bf96f0 R14: 0000000000000000 R15: ffff8a00d8766e00 FS: 0000000000000000(0000) GS:ffff8a07b6140000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055f10b520b28 CR3: 000000039741a000 CR4: 00000000000006f0 Call Trace: <TASK> igmp_heard_query (net/ipv4/igmp.c:1068) igmp_rcv (net/ipv4/igmp.c:1132) ip_protocol_deliver_rcu (net/ipv4/ip_input.c:205) ip_local_deliver_finish (net/ipv4/ip_input.c:234) __netif_receive_skb_one_core (net/core/dev.c:5529) netif_receive_skb_internal (net/core/dev.c:5729) netif_receive_skb (net/core/dev.c:5788) br_handle_frame_finish (net/bridge/br_input.c:216) nf_hook_bridge_pre (net/bridge/br_input.c:294) __netif_receive_skb_core (net/core/dev.c:5423) __netif_receive_skb_list_core (net/core/dev.c:5606) __netif_receive_skb_list (net/core/dev.c:5674) netif_receive_skb_list_internal (net/core/dev.c:5764) napi_gro_receive (net/core/gro.c:609) e1000_clean_rx_irq (drivers/net/ethernet/intel/e1000/e1000_main.c:4467) e1000_clean (drivers/net/ethernet/intel/e1000/e1000_main.c:3805) __napi_poll (net/core/dev.c:6533) net_rx_action (net/core/dev.c:6735) __do_softirq (kernel/softirq.c:554) run_ksoftirqd (kernel/softirq.c:913) smpboot_thread_fn (kernel/smpboot.c:164) kthread (kernel/kthread.c:388) ret_from_fork (arch/x86/kernel/process.c:153) ret_from_fork_asm (arch/x86/entry/entry_64.S:250) </TASK> The root causes are as follows: Thread A Thread B ... netif_receive_skb br_dev_stop ... br_multicast_leave_snoopers ... __ip_mc_dec_group ... __igmp_group_dropped igmp_rcv igmp_stop_timer igmp_heard_query //ref = 1 ip_ma_put igmp_mod_timer refcount_dec_and_test igmp_start_timer //ref = 0 ... refcount_inc //ref increases from 0 When the device receives an IGMPv2 Query message, it starts the timer immediately, regardless of whether the device is running. If the device is down and has left the multicast group, it will cause the mc list refcount uaf issue. Bug: 316932391 Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Zhengchao Shao <shaozhengchao@huawei.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Hangbin Liu <liuhangbin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org> (cherry picked from commit 94445d9583079e0ccc5dde1370076ff24800d86e) Signed-off-by: Lee Jones <joneslee@google.com> Change-Id: I277be2304e564994e05b981ccd6cd8cbb9dc85be --- net/ipv4/igmp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index b82b959764e7..1f3e1a1cc44e 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -216,8 +216,10 @@ static void igmp_start_timer(struct ip_mc_list *im, int max_delay) int tv = prandom_u32() % max_delay; im->tm_running = 1; - if (!mod_timer(&im->timer, jiffies+tv+2)) - refcount_inc(&im->refcnt); + if (refcount_inc_not_zero(&im->refcnt)) { + if (mod_timer(&im->timer, jiffies + tv + 2)) + ip_ma_put(im); + } } static void igmp_gq_start_timer(struct in_device *in_dev) From 22747510994b9d3c92ddd7ea49ae76ae9da40154 Mon Sep 17 00:00:00 2001 From: Florian Westphal <fw@strlen.de> Date: Fri, 1 Dec 2023 15:47:13 +0100 Subject: [PATCH 29/31] UPSTREAM: netfilter: nft_set_pipapo: skip inactive elements during set walk commit 317eb9685095678f2c9f5a8189de698c5354316a upstream. Otherwise set elements can be deactivated twice which will cause a crash. Bug: 316310313 Reported-by: Xingyuan Mo <hdthky0@gmail.com> Fixes: 3c4287f62044 ("nf_tables: Add set type for arbitrary concatenation of ranges") Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit 189c2a82933c67ad360c421258d5449f6647544a) Signed-off-by: Lee Jones <joneslee@google.com> Change-Id: I27fb6ee806642e23ca02700763a387341dd463e6 --- net/netfilter/nft_set_pipapo.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c index fbfcc3275cad..bc30bd121ff2 100644 --- a/net/netfilter/nft_set_pipapo.c +++ b/net/netfilter/nft_set_pipapo.c @@ -2028,6 +2028,9 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set, e = f->mt[r].e; + if (!nft_set_elem_active(&e->ext, iter->genmask)) + goto cont; + elem.priv = e; iter->err = iter->fn(ctx, set, iter, &elem); From d5552f63b8bcda99adb9beb9723f1917a9b4670b Mon Sep 17 00:00:00 2001 From: Wu Bo <bo.wu@vivo.com> Date: Tue, 21 Nov 2023 20:51:50 -0700 Subject: [PATCH 30/31] UPSTREAM: dm verity: don't perform FEC for failed readahead IO We found an issue under Android OTA scenario that many BIOs have to do FEC where the data under dm-verity is 100% complete and no corruption. Android OTA has many dm-block layers, from upper to lower: dm-verity dm-snapshot dm-origin & dm-cow dm-linear ufs DM tables have to change 2 times during Android OTA merging process. When doing table change, the dm-snapshot will be suspended for a while. During this interval, many readahead IOs are submitted to dm_verity from filesystem. Then the kverity works are busy doing FEC process which cost too much time to finish dm-verity IO. This causes needless delay which feels like system is hung. After adding debugging it was found that each readahead IO needed around 10s to finish when this situation occurred. This is due to IO amplification: dm-snapshot suspend erofs_readahead // 300+ io is submitted dm_submit_bio (dm_verity) dm_submit_bio (dm_snapshot) bio return EIO bio got nothing, it's empty verity_end_io verity_verify_io forloop range(0, io->n_blocks) // each io->nblocks ~= 20 verity_fec_decode fec_decode_rsb fec_read_bufs forloop range(0, v->fec->rsn) // v->fec->rsn = 253 new_read submit_bio (dm_snapshot) end loop end loop dm-snapshot resume Readahead BIOs get nothing while dm-snapshot is suspended, so all of them will cause verity's FEC. Each readahead BIO needs to verify ~20 (io->nblocks) blocks. Each block needs to do FEC, and every block needs to do 253 (v->fec->rsn) reads. So during the suspend interval(~200ms), 300 readahead BIOs trigger ~1518000 (300*20*253) IOs to dm-snapshot. As readahead IO is not required by userspace, and to fix this issue, it is best to pass readahead errors to upper layer to handle it. Cc: stable@vger.kernel.org Fixes: a739ff3f543a ("dm verity: add support for forward error correction") Bug: 316972624 Link: https://lore.kernel.org/dm-devel/b84fb49-bf63-3442-8c99-d565e134f2@redhat.com Signed-off-by: Wu Bo <bo.wu@vivo.com> Reviewed-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@kernel.org> Signed-off-by: Akilesh Kailash <akailash@google.com> (cherry picked from commit 0193e3966ceeeef69e235975918b287ab093082b) Change-Id: I73560e5660cebdc1997e1f9926cbb8888789eb46 --- drivers/md/dm-verity-target.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index 0ca29974b043..901d40a0203f 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -583,7 +583,9 @@ static void verity_end_io(struct bio *bio) struct dm_verity_io *io = bio->bi_private; if (bio->bi_status && - (!verity_fec_is_enabled(io->v) || verity_is_system_shutting_down())) { + (!verity_fec_is_enabled(io->v) || + verity_is_system_shutting_down() || + (bio->bi_opf & REQ_RAHEAD))) { verity_finish_io(io, bio->bi_status); return; } From 99512f12160fd57accf13e7d75847c2e3d9eccb5 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha <quic_mojha@quicinc.com> Date: Sat, 25 Nov 2023 02:41:58 +0530 Subject: [PATCH 31/31] FROMGIT: PM / devfreq: Synchronize devfreq_monitor_[start/stop] There is a chance if a frequent switch of the governor done in a loop result in timer list corruption where timer cancel being done from two place one from cancel_delayed_work_sync() and followed by expire_timers() can be seen from the traces[1]. while true do echo "simple_ondemand" > /sys/class/devfreq/1d84000.ufshc/governor echo "performance" > /sys/class/devfreq/1d84000.ufshc/governor done It looks to be issue with devfreq driver where device_monitor_[start/stop] need to synchronized so that delayed work should get corrupted while it is either being queued or running or being cancelled. Let's use polling flag and devfreq lock to synchronize the queueing the timer instance twice and work data being corrupted. [1] ... .. <idle>-0 [003] 9436.209662: timer_cancel timer=0xffffff80444f0428 <idle>-0 [003] 9436.209664: timer_expire_entry timer=0xffffff80444f0428 now=0x10022da1c function=__typeid__ZTSFvP10timer_listE_global_addr baseclk=0x10022da1c <idle>-0 [003] 9436.209718: timer_expire_exit timer=0xffffff80444f0428 kworker/u16:6-14217 [003] 9436.209863: timer_start timer=0xffffff80444f0428 function=__typeid__ZTSFvP10timer_listE_global_addr expires=0x10022da2b now=0x10022da1c flags=182452227 vendor.xxxyyy.ha-1593 [004] 9436.209888: timer_cancel timer=0xffffff80444f0428 vendor.xxxyyy.ha-1593 [004] 9436.216390: timer_init timer=0xffffff80444f0428 vendor.xxxyyy.ha-1593 [004] 9436.216392: timer_start timer=0xffffff80444f0428 function=__typeid__ZTSFvP10timer_listE_global_addr expires=0x10022da2c now=0x10022da1d flags=186646532 vendor.xxxyyy.ha-1593 [005] 9436.220992: timer_cancel timer=0xffffff80444f0428 xxxyyyTraceManag-7795 [004] 9436.261641: timer_cancel timer=0xffffff80444f0428 [2] 9436.261653][ C4] Unable to handle kernel paging request at virtual address dead00000000012a [ 9436.261664][ C4] Mem abort info: [ 9436.261666][ C4] ESR = 0x96000044 [ 9436.261669][ C4] EC = 0x25: DABT (current EL), IL = 32 bits [ 9436.261671][ C4] SET = 0, FnV = 0 [ 9436.261673][ C4] EA = 0, S1PTW = 0 [ 9436.261675][ C4] Data abort info: [ 9436.261677][ C4] ISV = 0, ISS = 0x00000044 [ 9436.261680][ C4] CM = 0, WnR = 1 [ 9436.261682][ C4] [dead00000000012a] address between user and kernel address ranges [ 9436.261685][ C4] Internal error: Oops: 96000044 [#1] PREEMPT SMP [ 9436.261701][ C4] Skip md ftrace buffer dump for: 0x3a982d0 ... [ 9436.262138][ C4] CPU: 4 PID: 7795 Comm: TraceManag Tainted: G S W O 5.10.149-android12-9-o-g17f915d29d0c #1 [ 9436.262141][ C4] Hardware name: Qualcomm Technologies, Inc. (DT) [ 9436.262144][ C4] pstate: 22400085 (nzCv daIf +PAN -UAO +TCO BTYPE=--) [ 9436.262161][ C4] pc : expire_timers+0x9c/0x438 [ 9436.262164][ C4] lr : expire_timers+0x2a4/0x438 [ 9436.262168][ C4] sp : ffffffc010023dd0 [ 9436.262171][ C4] x29: ffffffc010023df0 x28: ffffffd0636fdc18 [ 9436.262178][ C4] x27: ffffffd063569dd0 x26: ffffffd063536008 [ 9436.262182][ C4] x25: 0000000000000001 x24: ffffff88f7c69280 [ 9436.262185][ C4] x23: 00000000000000e0 x22: dead000000000122 [ 9436.262188][ C4] x21: 000000010022da29 x20: ffffff8af72b4e80 [ 9436.262191][ C4] x19: ffffffc010023e50 x18: ffffffc010025038 [ 9436.262195][ C4] x17: 0000000000000240 x16: 0000000000000201 [ 9436.262199][ C4] x15: ffffffffffffffff x14: ffffff889f3c3100 [ 9436.262203][ C4] x13: ffffff889f3c3100 x12: 00000000049f56b8 [ 9436.262207][ C4] x11: 00000000049f56b8 x10: 00000000ffffffff [ 9436.262212][ C4] x9 : ffffffc010023e50 x8 : dead000000000122 [ 9436.262216][ C4] x7 : ffffffffffffffff x6 : ffffffc0100239d8 [ 9436.262220][ C4] x5 : 0000000000000000 x4 : 0000000000000101 [ 9436.262223][ C4] x3 : 0000000000000080 x2 : ffffff889edc155c [ 9436.262227][ C4] x1 : ffffff8001005200 x0 : ffffff80444f0428 [ 9436.262232][ C4] Call trace: [ 9436.262236][ C4] expire_timers+0x9c/0x438 [ 9436.262240][ C4] __run_timers+0x1f0/0x330 [ 9436.262245][ C4] run_timer_softirq+0x28/0x58 [ 9436.262255][ C4] efi_header_end+0x168/0x5ec [ 9436.262265][ C4] __irq_exit_rcu+0x108/0x124 [ 9436.262274][ C4] __handle_domain_irq+0x118/0x1e4 [ 9436.262282][ C4] gic_handle_irq.30369+0x6c/0x2bc [ 9436.262286][ C4] el0_irq_naked+0x60/0x6c Bug: 317188938 Change-Id: I9a22325f6abbf28217c8f37b093cf77509b0139a Link: https://lore.kernel.org/all/1700860318-4025-1-git-send-email-quic_mojha@quicinc.com/ Reported-by: Joyyoung Huang <huangzaiyang@oppo.com> Acked-by: MyungJoo Ham <myungjoo.ham@samsung.com> Signed-off-by: Mukesh Ojha <quic_mojha@quicinc.com> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> (cherry picked from commit aed5ed595960c6d301dcd4ed31aeaa7a8054c0c6 https://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git devfreq-next) Signed-off-by: Srinivasarao Pathipati <quic_c_spathi@quicinc.com> --- drivers/devfreq/devfreq.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 2073f3feef95..208c874848da 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -438,10 +438,14 @@ static void devfreq_monitor(struct work_struct *work) if (err) dev_err(&devfreq->dev, "dvfs failed with (%d) error\n", err); + if (devfreq->stop_polling) + goto out; + queue_delayed_work(devfreq_wq, &devfreq->work, msecs_to_jiffies(devfreq->profile->polling_ms)); - mutex_unlock(&devfreq->lock); +out: + mutex_unlock(&devfreq->lock); trace_devfreq_monitor(devfreq); } @@ -459,6 +463,10 @@ void devfreq_monitor_start(struct devfreq *devfreq) if (devfreq->governor->interrupt_driven) return; + mutex_lock(&devfreq->lock); + if (delayed_work_pending(&devfreq->work)) + goto out; + switch (devfreq->profile->timer) { case DEVFREQ_TIMER_DEFERRABLE: INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor); @@ -467,12 +475,16 @@ void devfreq_monitor_start(struct devfreq *devfreq) INIT_DELAYED_WORK(&devfreq->work, devfreq_monitor); break; default: - return; + goto out; } if (devfreq->profile->polling_ms) queue_delayed_work(devfreq_wq, &devfreq->work, msecs_to_jiffies(devfreq->profile->polling_ms)); + +out: + devfreq->stop_polling = false; + mutex_unlock(&devfreq->lock); } EXPORT_SYMBOL(devfreq_monitor_start); @@ -489,6 +501,14 @@ void devfreq_monitor_stop(struct devfreq *devfreq) if (devfreq->governor->interrupt_driven) return; + mutex_lock(&devfreq->lock); + if (devfreq->stop_polling) { + mutex_unlock(&devfreq->lock); + return; + } + + devfreq->stop_polling = true; + mutex_unlock(&devfreq->lock); cancel_delayed_work_sync(&devfreq->work); } EXPORT_SYMBOL(devfreq_monitor_stop);