commit: d7e7f2ad6ee719ecb585e302141124540d80f29c Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Thu Nov 18 15:32:32 2021 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Thu Nov 18 15:32:32 2021 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=d7e7f2ad
Linux patch 5.14.20 Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org> 0000_README | 4 + 1019_linux-5.14.20.patch | 947 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 951 insertions(+) diff --git a/0000_README b/0000_README index 534f161e..6e5582fd 100644 --- a/0000_README +++ b/0000_README @@ -123,6 +123,10 @@ Patch: 1018_linux-5.14.19.patch From: http://www.kernel.org Desc: Linux 5.14.19 +Patch: 1019_linux-5.14.20.patch +From: http://www.kernel.org +Desc: Linux 5.14.20 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1019_linux-5.14.20.patch b/1019_linux-5.14.20.patch new file mode 100644 index 00000000..2762b0a9 --- /dev/null +++ b/1019_linux-5.14.20.patch @@ -0,0 +1,947 @@ +diff --git a/Makefile b/Makefile +index f4773aee95c4e..0e14a3a30d073 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 5 + PATCHLEVEL = 14 +-SUBLEVEL = 19 ++SUBLEVEL = 20 + EXTRAVERSION = + NAME = Opossums on Parade + +diff --git a/arch/alpha/include/asm/processor.h b/arch/alpha/include/asm/processor.h +index 090499c99c1c1..6100431da07a3 100644 +--- a/arch/alpha/include/asm/processor.h ++++ b/arch/alpha/include/asm/processor.h +@@ -42,7 +42,7 @@ extern void start_thread(struct pt_regs *, unsigned long, unsigned long); + struct task_struct; + extern void release_thread(struct task_struct *); + +-unsigned long __get_wchan(struct task_struct *p); ++unsigned long get_wchan(struct task_struct *p); + + #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) + +diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c +index 5f8527081da92..a5123ea426ce5 100644 +--- a/arch/alpha/kernel/process.c ++++ b/arch/alpha/kernel/process.c +@@ -376,11 +376,12 @@ thread_saved_pc(struct task_struct *t) + } + + unsigned long +-__get_wchan(struct task_struct *p) ++get_wchan(struct task_struct *p) + { + unsigned long schedule_frame; + unsigned long pc; +- ++ if (!p || p == current || task_is_running(p)) ++ return 0; + /* + * This one depends on the frame size of schedule(). Do a + * "disass schedule" in gdb to find the frame size. Also, the +diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h +index 04a5268e592b9..e4031ecd3c8c1 100644 +--- a/arch/arc/include/asm/processor.h ++++ b/arch/arc/include/asm/processor.h +@@ -70,7 +70,7 @@ struct task_struct; + extern void start_thread(struct pt_regs * regs, unsigned long pc, + unsigned long usp); + +-extern unsigned int __get_wchan(struct task_struct *p); ++extern unsigned int get_wchan(struct task_struct *p); + + #endif /* !__ASSEMBLY__ */ + +diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c +index db96cc8783891..1b9576d21e244 100644 +--- a/arch/arc/kernel/stacktrace.c ++++ b/arch/arc/kernel/stacktrace.c +@@ -15,7 +15,7 @@ + * = specifics of data structs where trace is saved(CONFIG_STACKTRACE etc) + * + * vineetg: March 2009 +- * -Implemented correct versions of thread_saved_pc() and __get_wchan() ++ * -Implemented correct versions of thread_saved_pc() and get_wchan() + * + * rajeshwarr: 2008 + * -Initial implementation +@@ -248,7 +248,7 @@ void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl) + * Of course just returning schedule( ) would be pointless so unwind until + * the function is not in schedular code + */ +-unsigned int __get_wchan(struct task_struct *tsk) ++unsigned int get_wchan(struct task_struct *tsk) + { + return arc_unwind_core(tsk, NULL, __get_first_nonsched, NULL); + } +diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h +index 6af68edfa53ab..9e6b972863077 100644 +--- a/arch/arm/include/asm/processor.h ++++ b/arch/arm/include/asm/processor.h +@@ -84,7 +84,7 @@ struct task_struct; + /* Free all resources held by a thread. */ + extern void release_thread(struct task_struct *); + +-unsigned long __get_wchan(struct task_struct *p); ++unsigned long get_wchan(struct task_struct *p); + + #define task_pt_regs(p) \ + ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index 261be96fa0c30..fc9e8b37eaa84 100644 +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -283,11 +283,13 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start, + return 0; + } + +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + struct stackframe frame; + unsigned long stack_page; + int count = 0; ++ if (!p || p == current || task_is_running(p)) ++ return 0; + + frame.fp = thread_saved_fp(p); + frame.sp = thread_saved_sp(p); +diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h +index 922355eb7eefa..b6517fd03d7b6 100644 +--- a/arch/arm64/include/asm/processor.h ++++ b/arch/arm64/include/asm/processor.h +@@ -251,7 +251,7 @@ struct task_struct; + /* Free all resources held by a thread. */ + extern void release_thread(struct task_struct *); + +-unsigned long __get_wchan(struct task_struct *p); ++unsigned long get_wchan(struct task_struct *p); + + void set_task_sctlr_el1(u64 sctlr); + +diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c +index 46995c972ff5f..c858b857c1ecf 100644 +--- a/arch/arm64/kernel/process.c ++++ b/arch/arm64/kernel/process.c +@@ -544,11 +544,13 @@ __notrace_funcgraph struct task_struct *__switch_to(struct task_struct *prev, + return last; + } + +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + struct stackframe frame; + unsigned long stack_page, ret = 0; + int count = 0; ++ if (!p || p == current || task_is_running(p)) ++ return 0; + + stack_page = (unsigned long)try_get_task_stack(p); + if (!stack_page) +diff --git a/arch/csky/include/asm/processor.h b/arch/csky/include/asm/processor.h +index 817dd60ff152d..9e933021fe8e0 100644 +--- a/arch/csky/include/asm/processor.h ++++ b/arch/csky/include/asm/processor.h +@@ -81,7 +81,7 @@ static inline void release_thread(struct task_struct *dead_task) + + extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); + +-unsigned long __get_wchan(struct task_struct *p); ++unsigned long get_wchan(struct task_struct *p); + + #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) + #define KSTK_ESP(tsk) (task_pt_regs(tsk)->usp) +diff --git a/arch/csky/kernel/stacktrace.c b/arch/csky/kernel/stacktrace.c +index 9f78f5d215117..1b280ef080045 100644 +--- a/arch/csky/kernel/stacktrace.c ++++ b/arch/csky/kernel/stacktrace.c +@@ -111,11 +111,12 @@ static bool save_wchan(unsigned long pc, void *arg) + return false; + } + +-unsigned long __get_wchan(struct task_struct *task) ++unsigned long get_wchan(struct task_struct *task) + { + unsigned long pc = 0; + +- walk_stackframe(task, NULL, save_wchan, &pc); ++ if (likely(task && task != current && !task_is_running(task))) ++ walk_stackframe(task, NULL, save_wchan, &pc); + return pc; + } + +diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h +index 141a23eb62b74..a060b41b2d31c 100644 +--- a/arch/h8300/include/asm/processor.h ++++ b/arch/h8300/include/asm/processor.h +@@ -105,7 +105,7 @@ static inline void release_thread(struct task_struct *dead_task) + { + } + +-unsigned long __get_wchan(struct task_struct *p); ++unsigned long get_wchan(struct task_struct *p); + + #define KSTK_EIP(tsk) \ + ({ \ +diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c +index 8833fa4f5d516..2ac27e4248a46 100644 +--- a/arch/h8300/kernel/process.c ++++ b/arch/h8300/kernel/process.c +@@ -128,12 +128,15 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, + return 0; + } + +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + unsigned long fp, pc; + unsigned long stack_page; + int count = 0; + ++ if (!p || p == current || task_is_running(p)) ++ return 0; ++ + stack_page = (unsigned long)p; + fp = ((struct pt_regs *)p->thread.ksp)->er6; + do { +diff --git a/arch/hexagon/include/asm/processor.h b/arch/hexagon/include/asm/processor.h +index 615f7e49968e6..9f0cc99420bee 100644 +--- a/arch/hexagon/include/asm/processor.h ++++ b/arch/hexagon/include/asm/processor.h +@@ -64,7 +64,7 @@ struct thread_struct { + extern void release_thread(struct task_struct *dead_task); + + /* Get wait channel for task P. */ +-extern unsigned long __get_wchan(struct task_struct *p); ++extern unsigned long get_wchan(struct task_struct *p); + + /* The following stuff is pretty HEXAGON specific. */ + +diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c +index 232dfd8956aa2..6a6835fb42425 100644 +--- a/arch/hexagon/kernel/process.c ++++ b/arch/hexagon/kernel/process.c +@@ -130,11 +130,13 @@ void flush_thread(void) + * is an identification of the point at which the scheduler + * was invoked by a blocked thread. + */ +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + unsigned long fp, pc; + unsigned long stack_page; + int count = 0; ++ if (!p || p == current || task_is_running(p)) ++ return 0; + + stack_page = (unsigned long)task_stack_page(p); + fp = ((struct hexagon_switch_stack *)p->thread.switch_sp)->fp; +diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h +index 45365c2ef5983..2d8bcdc27d7f8 100644 +--- a/arch/ia64/include/asm/processor.h ++++ b/arch/ia64/include/asm/processor.h +@@ -330,7 +330,7 @@ struct task_struct; + #define release_thread(dead_task) + + /* Get wait channel for task P. */ +-extern unsigned long __get_wchan (struct task_struct *p); ++extern unsigned long get_wchan (struct task_struct *p); + + /* Return instruction pointer of blocked task TSK. */ + #define KSTK_EIP(tsk) \ +diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c +index 834df24a88f12..e56d63f4abf9d 100644 +--- a/arch/ia64/kernel/process.c ++++ b/arch/ia64/kernel/process.c +@@ -523,12 +523,15 @@ exit_thread (struct task_struct *tsk) + } + + unsigned long +-__get_wchan (struct task_struct *p) ++get_wchan (struct task_struct *p) + { + struct unw_frame_info info; + unsigned long ip; + int count = 0; + ++ if (!p || p == current || task_is_running(p)) ++ return 0; ++ + /* + * Note: p may not be a blocked task (it could be current or + * another process running on some other CPU. Rather than +diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h +index bacec548cb3c6..3750819ac5a13 100644 +--- a/arch/m68k/include/asm/processor.h ++++ b/arch/m68k/include/asm/processor.h +@@ -125,7 +125,7 @@ static inline void release_thread(struct task_struct *dead_task) + { + } + +-unsigned long __get_wchan(struct task_struct *p); ++unsigned long get_wchan(struct task_struct *p); + + #define KSTK_EIP(tsk) \ + ({ \ +diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c +index d2357cba09abe..db49f90917112 100644 +--- a/arch/m68k/kernel/process.c ++++ b/arch/m68k/kernel/process.c +@@ -263,11 +263,13 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu) + } + EXPORT_SYMBOL(dump_fpu); + +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + unsigned long fp, pc; + unsigned long stack_page; + int count = 0; ++ if (!p || p == current || task_is_running(p)) ++ return 0; + + stack_page = (unsigned long)task_stack_page(p); + fp = ((struct switch_stack *)p->thread.ksp)->a6; +diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h +index 7e9e92670df33..06c6e493590a2 100644 +--- a/arch/microblaze/include/asm/processor.h ++++ b/arch/microblaze/include/asm/processor.h +@@ -68,7 +68,7 @@ static inline void release_thread(struct task_struct *dead_task) + { + } + +-unsigned long __get_wchan(struct task_struct *p); ++unsigned long get_wchan(struct task_struct *p); + + /* The size allocated for kernel stacks. This _must_ be a power of two! */ + # define KERNEL_STACK_SIZE 0x2000 +diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c +index 5e2b91c1e8ced..62aa237180b67 100644 +--- a/arch/microblaze/kernel/process.c ++++ b/arch/microblaze/kernel/process.c +@@ -112,7 +112,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, + return 0; + } + +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + /* TBD (used by procfs) */ + return 0; +diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h +index 252ed38ce8c5a..0c3550c82b726 100644 +--- a/arch/mips/include/asm/processor.h ++++ b/arch/mips/include/asm/processor.h +@@ -369,7 +369,7 @@ static inline void flush_thread(void) + { + } + +-unsigned long __get_wchan(struct task_struct *p); ++unsigned long get_wchan(struct task_struct *p); + + #define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + \ + THREAD_SIZE - 32 - sizeof(struct pt_regs)) +diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c +index 637e6207e3500..73c8e7990a973 100644 +--- a/arch/mips/kernel/process.c ++++ b/arch/mips/kernel/process.c +@@ -511,7 +511,7 @@ static int __init frame_info_init(void) + + /* + * Without schedule() frame info, result given by +- * thread_saved_pc() and __get_wchan() are not reliable. ++ * thread_saved_pc() and get_wchan() are not reliable. + */ + if (schedule_mfi.pc_offset < 0) + printk("Can't analyze schedule() prologue at %p\n", schedule); +@@ -652,9 +652,9 @@ unsigned long unwind_stack(struct task_struct *task, unsigned long *sp, + #endif + + /* +- * __get_wchan - a maintenance nightmare^W^Wpain in the ass ... ++ * get_wchan - a maintenance nightmare^W^Wpain in the ass ... + */ +-unsigned long __get_wchan(struct task_struct *task) ++unsigned long get_wchan(struct task_struct *task) + { + unsigned long pc = 0; + #ifdef CONFIG_KALLSYMS +@@ -662,6 +662,8 @@ unsigned long __get_wchan(struct task_struct *task) + unsigned long ra = 0; + #endif + ++ if (!task || task == current || task_is_running(task)) ++ goto out; + if (!task_stack_page(task)) + goto out; + +diff --git a/arch/nds32/include/asm/processor.h b/arch/nds32/include/asm/processor.h +index e6bfc74972bb3..b82369c7659d4 100644 +--- a/arch/nds32/include/asm/processor.h ++++ b/arch/nds32/include/asm/processor.h +@@ -83,7 +83,7 @@ extern struct task_struct *last_task_used_math; + /* Prepare to copy thread state - unlazy all lazy status */ + #define prepare_to_copy(tsk) do { } while (0) + +-unsigned long __get_wchan(struct task_struct *p); ++unsigned long get_wchan(struct task_struct *p); + + #define cpu_relax() barrier() + +diff --git a/arch/nds32/kernel/process.c b/arch/nds32/kernel/process.c +index 49fab9e39cbff..391895b54d13c 100644 +--- a/arch/nds32/kernel/process.c ++++ b/arch/nds32/kernel/process.c +@@ -233,12 +233,15 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpu) + + EXPORT_SYMBOL(dump_fpu); + +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + unsigned long fp, lr; + unsigned long stack_start, stack_end; + int count = 0; + ++ if (!p || p == current || task_is_running(p)) ++ return 0; ++ + if (IS_ENABLED(CONFIG_FRAME_POINTER)) { + stack_start = (unsigned long)end_of_stack(p); + stack_end = (unsigned long)task_stack_page(p) + THREAD_SIZE; +@@ -255,3 +258,5 @@ unsigned long __get_wchan(struct task_struct *p) + } + return 0; + } ++ ++EXPORT_SYMBOL(get_wchan); +diff --git a/arch/nios2/include/asm/processor.h b/arch/nios2/include/asm/processor.h +index b8125dfbcad2d..94bcb86f679f5 100644 +--- a/arch/nios2/include/asm/processor.h ++++ b/arch/nios2/include/asm/processor.h +@@ -69,7 +69,7 @@ static inline void release_thread(struct task_struct *dead_task) + { + } + +-extern unsigned long __get_wchan(struct task_struct *p); ++extern unsigned long get_wchan(struct task_struct *p); + + #define task_pt_regs(p) \ + ((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1) +diff --git a/arch/nios2/kernel/process.c b/arch/nios2/kernel/process.c +index f8ea522a15880..9ff37ba2bb603 100644 +--- a/arch/nios2/kernel/process.c ++++ b/arch/nios2/kernel/process.c +@@ -217,12 +217,15 @@ void dump(struct pt_regs *fp) + pr_emerg("\n\n"); + } + +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + unsigned long fp, pc; + unsigned long stack_page; + int count = 0; + ++ if (!p || p == current || task_is_running(p)) ++ return 0; ++ + stack_page = (unsigned long)p; + fp = ((struct switch_stack *)p->thread.ksp)->fp; /* ;dgt2 */ + do { +diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h +index aa1699c18add8..ad53b31848859 100644 +--- a/arch/openrisc/include/asm/processor.h ++++ b/arch/openrisc/include/asm/processor.h +@@ -73,7 +73,7 @@ struct thread_struct { + + void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp); + void release_thread(struct task_struct *); +-unsigned long __get_wchan(struct task_struct *p); ++unsigned long get_wchan(struct task_struct *p); + + #define cpu_relax() barrier() + +diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c +index eeea6d54b198c..eb62429681fc8 100644 +--- a/arch/openrisc/kernel/process.c ++++ b/arch/openrisc/kernel/process.c +@@ -265,7 +265,7 @@ void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs) + dest[35] = 0; + } + +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + /* TODO */ + +diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h +index 5e5ceb5b9631f..b5fbcd2c17808 100644 +--- a/arch/parisc/include/asm/processor.h ++++ b/arch/parisc/include/asm/processor.h +@@ -277,7 +277,7 @@ struct mm_struct; + /* Free all resources held by a thread. */ + extern void release_thread(struct task_struct *); + +-extern unsigned long __get_wchan(struct task_struct *p); ++extern unsigned long get_wchan(struct task_struct *p); + + #define KSTK_EIP(tsk) ((tsk)->thread.regs.iaoq[0]) + #define KSTK_ESP(tsk) ((tsk)->thread.regs.gr[30]) +diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c +index 05e89d4fa911a..184ec3c1eae44 100644 +--- a/arch/parisc/kernel/process.c ++++ b/arch/parisc/kernel/process.c +@@ -243,12 +243,15 @@ copy_thread(unsigned long clone_flags, unsigned long usp, + } + + unsigned long +-__get_wchan(struct task_struct *p) ++get_wchan(struct task_struct *p) + { + struct unwind_frame_info info; + unsigned long ip; + int count = 0; + ++ if (!p || p == current || task_is_running(p)) ++ return 0; ++ + /* + * These bracket the sleeping functions.. + */ +diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h +index e39bd0ff69f3a..f348e564f7dd5 100644 +--- a/arch/powerpc/include/asm/processor.h ++++ b/arch/powerpc/include/asm/processor.h +@@ -300,7 +300,7 @@ struct thread_struct { + + #define task_pt_regs(tsk) ((tsk)->thread.regs) + +-unsigned long __get_wchan(struct task_struct *p); ++unsigned long get_wchan(struct task_struct *p); + + #define KSTK_EIP(tsk) ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0) + #define KSTK_ESP(tsk) ((tsk)->thread.regs? (tsk)->thread.regs->gpr[1]: 0) +diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c +index 247ef0b9bfa4e..185beb2905801 100644 +--- a/arch/powerpc/kernel/process.c ++++ b/arch/powerpc/kernel/process.c +@@ -2111,11 +2111,14 @@ int validate_sp(unsigned long sp, struct task_struct *p, + + EXPORT_SYMBOL(validate_sp); + +-static unsigned long ___get_wchan(struct task_struct *p) ++static unsigned long __get_wchan(struct task_struct *p) + { + unsigned long ip, sp; + int count = 0; + ++ if (!p || p == current || task_is_running(p)) ++ return 0; ++ + sp = p->thread.ksp; + if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD)) + return 0; +@@ -2134,14 +2137,14 @@ static unsigned long ___get_wchan(struct task_struct *p) + return 0; + } + +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + unsigned long ret; + + if (!try_get_task_stack(p)) + return 0; + +- ret = ___get_wchan(p); ++ ret = __get_wchan(p); + + put_task_stack(p); + +diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h +index 086821b44def1..021ed64ee608f 100644 +--- a/arch/riscv/include/asm/processor.h ++++ b/arch/riscv/include/asm/processor.h +@@ -58,7 +58,7 @@ static inline void release_thread(struct task_struct *dead_task) + { + } + +-extern unsigned long __get_wchan(struct task_struct *p); ++extern unsigned long get_wchan(struct task_struct *p); + + + static inline void wait_for_interrupt(void) +diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c +index 0fcdc0233faca..315db3d0229bf 100644 +--- a/arch/riscv/kernel/stacktrace.c ++++ b/arch/riscv/kernel/stacktrace.c +@@ -128,14 +128,16 @@ static bool save_wchan(void *arg, unsigned long pc) + return true; + } + +-unsigned long __get_wchan(struct task_struct *task) ++unsigned long get_wchan(struct task_struct *task) + { + unsigned long pc = 0; + +- if (!try_get_task_stack(task)) +- return 0; +- walk_stackframe(task, NULL, save_wchan, &pc); +- put_task_stack(task); ++ if (likely(task && task != current && !task_is_running(task))) { ++ if (!try_get_task_stack(task)) ++ return 0; ++ walk_stackframe(task, NULL, save_wchan, &pc); ++ put_task_stack(task); ++ } + return pc; + } + +diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h +index f54c152bf2bf9..879b8e3f609cd 100644 +--- a/arch/s390/include/asm/processor.h ++++ b/arch/s390/include/asm/processor.h +@@ -192,7 +192,7 @@ static inline void release_thread(struct task_struct *tsk) { } + void guarded_storage_release(struct task_struct *tsk); + void gs_load_bc_cb(struct pt_regs *regs); + +-unsigned long __get_wchan(struct task_struct *p); ++unsigned long get_wchan(struct task_struct *p); + #define task_pt_regs(tsk) ((struct pt_regs *) \ + (task_stack_page(tsk) + THREAD_SIZE) - 1) + #define KSTK_EIP(tsk) (task_pt_regs(tsk)->psw.addr) +diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c +index e5dd46b1bff8c..350e94d0cac23 100644 +--- a/arch/s390/kernel/process.c ++++ b/arch/s390/kernel/process.c +@@ -181,12 +181,12 @@ void execve_tail(void) + asm volatile("sfpc %0" : : "d" (0)); + } + +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + struct unwind_state state; + unsigned long ip = 0; + +- if (!task_stack_page(p)) ++ if (!p || p == current || task_is_running(p) || !task_stack_page(p)) + return 0; + + if (!try_get_task_stack(p)) +diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h +index 45240ec6b85a4..aa92cc933889d 100644 +--- a/arch/sh/include/asm/processor_32.h ++++ b/arch/sh/include/asm/processor_32.h +@@ -180,7 +180,7 @@ static inline void show_code(struct pt_regs *regs) + } + #endif + +-extern unsigned long __get_wchan(struct task_struct *p); ++extern unsigned long get_wchan(struct task_struct *p); + + #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) + #define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[15]) +diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c +index 1c28e3cddb60d..717de05c81f49 100644 +--- a/arch/sh/kernel/process_32.c ++++ b/arch/sh/kernel/process_32.c +@@ -182,10 +182,13 @@ __switch_to(struct task_struct *prev, struct task_struct *next) + return prev; + } + +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + unsigned long pc; + ++ if (!p || p == current || task_is_running(p)) ++ return 0; ++ + /* + * The same comment as on the Alpha applies here, too ... + */ +diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h +index 647bf0ac7beb9..b6242f7771e9e 100644 +--- a/arch/sparc/include/asm/processor_32.h ++++ b/arch/sparc/include/asm/processor_32.h +@@ -89,7 +89,7 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc, + /* Free all resources held by a thread. */ + #define release_thread(tsk) do { } while(0) + +-unsigned long __get_wchan(struct task_struct *); ++unsigned long get_wchan(struct task_struct *); + + #define task_pt_regs(tsk) ((tsk)->thread.kregs) + #define KSTK_EIP(tsk) ((tsk)->thread.kregs->pc) +diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h +index ae851e8fce4c9..5cf145f18f36b 100644 +--- a/arch/sparc/include/asm/processor_64.h ++++ b/arch/sparc/include/asm/processor_64.h +@@ -183,7 +183,7 @@ do { \ + /* Free all resources held by a thread. */ + #define release_thread(tsk) do { } while (0) + +-unsigned long __get_wchan(struct task_struct *task); ++unsigned long get_wchan(struct task_struct *task); + + #define task_pt_regs(tsk) (task_thread_info(tsk)->kregs) + #define KSTK_EIP(tsk) (task_pt_regs(tsk)->tpc) +diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c +index 29a2f396f8601..93983d6d431de 100644 +--- a/arch/sparc/kernel/process_32.c ++++ b/arch/sparc/kernel/process_32.c +@@ -368,7 +368,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg, + return 0; + } + +-unsigned long __get_wchan(struct task_struct *task) ++unsigned long get_wchan(struct task_struct *task) + { + unsigned long pc, fp, bias = 0; + unsigned long task_base = (unsigned long) task; +@@ -376,6 +376,9 @@ unsigned long __get_wchan(struct task_struct *task) + struct reg_window32 *rw; + int count = 0; + ++ if (!task || task == current || task_is_running(task)) ++ goto out; ++ + fp = task_thread_info(task)->ksp + bias; + do { + /* Bogus frame pointer? */ +diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c +index fa8db86e561c7..d33c58a58d4ff 100644 +--- a/arch/sparc/kernel/process_64.c ++++ b/arch/sparc/kernel/process_64.c +@@ -666,7 +666,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) + return 0; + } + +-unsigned long __get_wchan(struct task_struct *task) ++unsigned long get_wchan(struct task_struct *task) + { + unsigned long pc, fp, bias = 0; + struct thread_info *tp; +@@ -674,6 +674,9 @@ unsigned long __get_wchan(struct task_struct *task) + unsigned long ret = 0; + int count = 0; + ++ if (!task || task == current || task_is_running(task)) ++ goto out; ++ + tp = task_thread_info(task); + bias = STACK_BIAS; + fp = task_thread_info(task)->ksp + bias; +diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h +index 579692a40a556..b5cf0ed116d9e 100644 +--- a/arch/um/include/asm/processor-generic.h ++++ b/arch/um/include/asm/processor-generic.h +@@ -106,6 +106,6 @@ extern struct cpuinfo_um boot_cpu_data; + #define cache_line_size() (boot_cpu_data.cache_alignment) + + #define KSTK_REG(tsk, reg) get_thread_reg(reg, &tsk->thread.switch_buf) +-extern unsigned long __get_wchan(struct task_struct *p); ++extern unsigned long get_wchan(struct task_struct *p); + + #endif +diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c +index 82107373ac7e9..457a38db368b7 100644 +--- a/arch/um/kernel/process.c ++++ b/arch/um/kernel/process.c +@@ -364,11 +364,14 @@ unsigned long arch_align_stack(unsigned long sp) + } + #endif + +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + unsigned long stack_page, sp, ip; + bool seen_sched = 0; + ++ if ((p == NULL) || (p == current) || task_is_running(p)) ++ return 0; ++ + stack_page = (unsigned long) task_stack_page(p); + /* Bail if the process has no kernel stack for some reason */ + if (stack_page == 0) +diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h +index 6f9ed2e800f21..d2c11378c7832 100644 +--- a/arch/x86/include/asm/processor.h ++++ b/arch/x86/include/asm/processor.h +@@ -588,7 +588,7 @@ static inline void load_sp0(unsigned long sp0) + /* Free all resources held by a thread. */ + extern void release_thread(struct task_struct *); + +-unsigned long __get_wchan(struct task_struct *p); ++unsigned long get_wchan(struct task_struct *p); + + /* + * Generic CPUID function +diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c +index 2fe1810e922a9..f2f733bcb2b95 100644 +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -43,7 +43,6 @@ + #include <asm/io_bitmap.h> + #include <asm/proto.h> + #include <asm/frame.h> +-#include <asm/unwind.h> + + #include "process.h" + +@@ -944,22 +943,60 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) + * because the task might wake up and we might look at a stack + * changing under us. + */ +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { +- struct unwind_state state; +- unsigned long addr = 0; ++ unsigned long start, bottom, top, sp, fp, ip, ret = 0; ++ int count = 0; + +- for (unwind_start(&state, p, NULL, NULL); !unwind_done(&state); +- unwind_next_frame(&state)) { +- addr = unwind_get_return_address(&state); +- if (!addr) +- break; +- if (in_sched_functions(addr)) +- continue; +- break; +- } ++ if (p == current || task_is_running(p)) ++ return 0; ++ ++ if (!try_get_task_stack(p)) ++ return 0; ++ ++ start = (unsigned long)task_stack_page(p); ++ if (!start) ++ goto out; ++ ++ /* ++ * Layout of the stack page: ++ * ++ * ----------- topmax = start + THREAD_SIZE - sizeof(unsigned long) ++ * PADDING ++ * ----------- top = topmax - TOP_OF_KERNEL_STACK_PADDING ++ * stack ++ * ----------- bottom = start ++ * ++ * The tasks stack pointer points at the location where the ++ * framepointer is stored. The data on the stack is: ++ * ... IP FP ... IP FP ++ * ++ * We need to read FP and IP, so we need to adjust the upper ++ * bound by another unsigned long. ++ */ ++ top = start + THREAD_SIZE - TOP_OF_KERNEL_STACK_PADDING; ++ top -= 2 * sizeof(unsigned long); ++ bottom = start; ++ ++ sp = READ_ONCE(p->thread.sp); ++ if (sp < bottom || sp > top) ++ goto out; ++ ++ fp = READ_ONCE_NOCHECK(((struct inactive_task_frame *)sp)->bp); ++ do { ++ if (fp < bottom || fp > top) ++ goto out; ++ ip = READ_ONCE_NOCHECK(*(unsigned long *)(fp + sizeof(unsigned long))); ++ if (!in_sched_functions(ip)) { ++ ret = ip; ++ goto out; ++ } ++ fp = READ_ONCE_NOCHECK(*(unsigned long *)fp); ++ } while (count++ < 16 && !task_is_running(p)); + +- return addr; ++out: ++ put_task_stack(p); ++ return ret; + } + + long do_arch_prctl_common(struct task_struct *task, int option, +diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h +index ad15fbc572838..7f63aca6a0d34 100644 +--- a/arch/xtensa/include/asm/processor.h ++++ b/arch/xtensa/include/asm/processor.h +@@ -215,7 +215,7 @@ struct mm_struct; + /* Free all resources held by a thread. */ + #define release_thread(thread) do { } while(0) + +-extern unsigned long __get_wchan(struct task_struct *p); ++extern unsigned long get_wchan(struct task_struct *p); + + #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) + #define KSTK_ESP(tsk) (task_pt_regs(tsk)->areg[1]) +diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c +index 47f933fed8700..0601653406123 100644 +--- a/arch/xtensa/kernel/process.c ++++ b/arch/xtensa/kernel/process.c +@@ -298,12 +298,15 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, + * These bracket the sleeping functions.. + */ + +-unsigned long __get_wchan(struct task_struct *p) ++unsigned long get_wchan(struct task_struct *p) + { + unsigned long sp, pc; + unsigned long stack_page = (unsigned long) task_stack_page(p); + int count = 0; + ++ if (!p || p == current || task_is_running(p)) ++ return 0; ++ + sp = p->thread.sp; + pc = MAKE_PC_FROM_RA(p->thread.ra, p->thread.sp); + +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 4ee118cf06971..8e10c7accdbcc 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -2030,7 +2030,6 @@ static inline void set_task_cpu(struct task_struct *p, unsigned int cpu) + #endif /* CONFIG_SMP */ + + extern bool sched_task_on_rq(struct task_struct *p); +-extern unsigned long get_wchan(struct task_struct *p); + + /* + * In order to reduce various lock holder preemption latencies provide an +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 5ea5b6d8b2a94..9289da7f0ac4a 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -1960,25 +1960,6 @@ bool sched_task_on_rq(struct task_struct *p) + return task_on_rq_queued(p); + } + +-unsigned long get_wchan(struct task_struct *p) +-{ +- unsigned long ip = 0; +- unsigned int state; +- +- if (!p || p == current) +- return 0; +- +- /* Only get wchan if task is blocked and we can keep it that way. */ +- raw_spin_lock_irq(&p->pi_lock); +- state = READ_ONCE(p->__state); +- smp_rmb(); /* see try_to_wake_up() */ +- if (state != TASK_RUNNING && state != TASK_WAKING && !p->on_rq) +- ip = __get_wchan(p); +- raw_spin_unlock_irq(&p->pi_lock); +- +- return ip; +-} +- + static inline void enqueue_task(struct rq *rq, struct task_struct *p, int flags) + { + if (!(flags & ENQUEUE_NOCLOCK))
