lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <f5dab282-ed95-2161-2367-4a1f7b70e5a8@loongson.cn>
Date: Wed, 26 Nov 2025 17:56:24 +0800
From: Bibo Mao <maobibo@...ngson.cn>
To: Tiezhu Yang <yangtiezhu@...ngson.cn>, Jinyang He <hejinyang@...ngson.cn>
Cc: Huacai Chen <chenhuacai@...nel.org>, Xi Zhang <zhangxi@...inos.cn>,
 Xianglai Li <lixianglai@...ngson.cn>, loongarch@...ts.linux.dev,
 linux-kernel@...r.kernel.org
Subject: Re: [PATCH v1] LoongArch: Handle special PC in unwind_next_frame()



On 2025/11/26 下午5:09, Tiezhu Yang wrote:
> Cc: Bibo Mao <maobibo@...ngson.cn>
> 
> On 2025/11/26 下午2:28, Tiezhu Yang wrote:
>> On 2025/11/26 下午2:08, Tiezhu Yang wrote:
>>> On 2025/11/25 下午6:52, Jinyang He wrote:
>>>> On 2025-11-25 14:33, Tiezhu Yang wrote:
>>>>
>>>>> When running virtual machine before testing the kernel live 
>>>>> patching with
>>>>> "modprobe livepatch-sample", there is a timeout over 15 seconds, 
>>>>> the dmesg
>>>>> command shows "unreliable stack" for user tasks in debug mode.
>>>>>
>>>>> The "unreliable stack" is because it can not unwind from 
>>>>> kvm_handle_exit()
>>>>> to its previous frame kvm_exc_entry() due to the PC is not a valid 
>>>>> kernel
>>>>> address, the root cause is that the code of kvm_exc_entry() was 
>>>>> copied to
>>>>> the DMW area in kvm_loongarch_env_init(), so it should check the PC 
>>>>> range
>>>>> and then finish unwinding for this special case.
>>>>
>>>> Hi, Tiezhu,
>>>>
>>>> Since kvm_loongarch_env_init copies kvm_exc_entry which similar to how
>>>> trap_init copies the exception handler. We should apply the same
>>>> offset-based adjustment to compute the shadow PC address:
>>>>   shadow_pc = kvm_exc_entry + (cur_pc − copied_base_address)
>>>> This allows the ORC unwinder to correctly locate the corresponding 
>>>> unwind info.
>>>
>>> Thank you. I did some tests, it can unwind from kvm_handle_exit()
>>> to its previous frame kvm_exc_entry() only when CONFIG_KVM=y,
>>> but it can not unwind from kvm_handle_exit() to its previous frame 
>>> kvm_exc_entry() when CONFIG_KVM=m because we can not get the two
>>> kvm address (unsigned long)kvm_exc_entry and
>>> (unsigned long)kvm_loongarch_ops->exc_entry
>>> in arch/loongarch/kernel/unwind_orc.c.
>>
>> Use function pointer can get get the two kvm address
>> (unsigned long)kvm_exc_entry and
>> (unsigned long)kvm_loongarch_ops->exc_entry
>> in arch/loongarch/kernel/unwind_orc.c.
>>
>> I will do more test and send v2 later.
> 
> Here are the draft changes:
> 
> ----->8-----
> diff --git a/arch/loongarch/kernel/unwind_guess.c 
> b/arch/loongarch/kernel/unwind_guess.c
> index 08d7951b2f60..64c50c483cbb 100644
> --- a/arch/loongarch/kernel/unwind_guess.c
> +++ b/arch/loongarch/kernel/unwind_guess.c
> @@ -5,6 +5,11 @@
>   #include <asm/unwind.h>
>   #include <linux/export.h>
> 
> +#if IS_ENABLED(CONFIG_KVM)
> +void (*get_kvm_entry_info)(unsigned long *old, unsigned long *new, 
> unsigned long *size);
> +EXPORT_SYMBOL_GPL(get_kvm_entry_info);
> +#endif
> +
>   unsigned long unwind_get_return_address(struct unwind_state *state)
>   {
>          return __unwind_get_return_address(state);
> diff --git a/arch/loongarch/kernel/unwind_orc.c 
> b/arch/loongarch/kernel/unwind_orc.c
> index 1d60a593479a..ef8bb6cd7af8 100644
> --- a/arch/loongarch/kernel/unwind_orc.c
> +++ b/arch/loongarch/kernel/unwind_orc.c
> @@ -356,6 +356,11 @@ static bool is_entry_func(unsigned long addr)
>          return addr >= (unsigned long)&kernel_entry && addr < (unsigned 
> long)&kernel_entry_end;
>   }
> 
> +#if IS_ENABLED(CONFIG_KVM)
> +void (*get_kvm_entry_info)(unsigned long *old, unsigned long *new, 
> unsigned long *size);
> +EXPORT_SYMBOL_GPL(get_kvm_entry_info);
> +#endif
this method mixes kvm and unwind components and it is obvious hack 
method. If there are other modules which have the similar problem, how 
to handle it? Add get_MODULE_1_entry_info/get_MODULE_2_entry_info API :)

KVM module copy exception function to allocated memory, it breaks unwind 
rules. KVM can compile exception function in kernel and do not copy the 
exception functions or LoongArch kernel provides unwind hint APIs to 
handle it.

> +
>   static inline unsigned long bt_address(unsigned long ra)
>   {
>          extern unsigned long eentry;
> @@ -386,6 +391,16 @@ static inline unsigned long bt_address(unsigned 
> long ra)
>                  return func + offset;
>          }
> 
> +#if IS_ENABLED(CONFIG_KVM)
> +       unsigned long old, new, size;
> +
> +       if (get_kvm_entry_info) {
> +               get_kvm_entry_info(&old, &new, &size);
> +               if (ra >= new && ra < new + size)
> +                       return old + (ra - new);
> +       }
> +#endif
> +
>          return ra;
>   }
> 
> diff --git a/arch/loongarch/kernel/unwind_prologue.c 
> b/arch/loongarch/kernel/unwind_prologue.c
> index 729e775bd40d..42c210b0a378 100644
> --- a/arch/loongarch/kernel/unwind_prologue.c
> +++ b/arch/loongarch/kernel/unwind_prologue.c
> @@ -28,6 +28,11 @@ extern unsigned long eentry;
>   extern unsigned long pcpu_handlers[NR_CPUS];
>   #endif
> 
> +#if IS_ENABLED(CONFIG_KVM)
> +void (*get_kvm_entry_info)(unsigned long *old, unsigned long *new, 
> unsigned long *size);
> +EXPORT_SYMBOL_GPL(get_kvm_entry_info);
> +#endif
> +
>   static inline bool scan_handlers(unsigned long entry_offset)
>   {
>          int idx, offset;
> diff --git a/arch/loongarch/kvm/main.c b/arch/loongarch/kvm/main.c
> index 80ea63d465b8..3606554e43e0 100644
> --- a/arch/loongarch/kvm/main.c
> +++ b/arch/loongarch/kvm/main.c
> @@ -338,6 +338,13 @@ void kvm_arch_disable_virtualization_cpu(void)
>          kvm_flush_tlb_all();
>   }
> 
> +static void kvm_entry_info(unsigned long *old, unsigned long *new, 
> unsigned long *size)
> +{
> +       *old = (unsigned long)kvm_exc_entry;
> +       *new = (unsigned long)kvm_loongarch_ops->exc_entry;
> +       *size = kvm_exception_size;
> +}
> +
>   static int kvm_loongarch_env_init(void)
>   {
>          int cpu, order, ret;
> @@ -430,6 +437,7 @@ static void kvm_loongarch_env_exit(void)
>          kvm_unregister_perf_callbacks();
>   }
> 
> +extern void (*get_kvm_entry_info)(unsigned long *old, unsigned long 
> *new, unsigned long *size);
>   static int kvm_loongarch_init(void)
>   {
>          int r;
> @@ -442,6 +450,8 @@ static int kvm_loongarch_init(void)
>          if (r)
>                  return r;
> 
> +       get_kvm_entry_info = kvm_entry_info;
Is this API get_kvm_entry_info() general for all modules or kernel 
components?

Regards
Bibo Mao
> +
>          return kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE);
>   }
> 
> diff --git a/arch/loongarch/kvm/switch.S b/arch/loongarch/kvm/switch.S
> index f1768b7a6194..9eaad5dbed91 100644
> --- a/arch/loongarch/kvm/switch.S
> +++ b/arch/loongarch/kvm/switch.S
> @@ -104,7 +104,7 @@
>          .text
>          .cfi_sections   .debug_frame
>   SYM_CODE_START(kvm_exc_entry)
> -       UNWIND_HINT_UNDEFINED
> +       UNWIND_HINT_END_OF_STACK
>          csrwr   a2,   KVM_TEMP_KS
>          csrrd   a2,   KVM_VCPU_KS
>          addi.d  a2,   a2, KVM_VCPU_ARCH
> ----->8-----
> 
> I tested with config UNWINDER_ORC, it can unwind from kvm_handle_exit()
> to its previous frame kvm_exc_entry() which is the end of stack, there
> is no "unreliable stack" in debug mode and also no timeout for kernel
> livepatching.
> 
> I also tested with config UNWINDER_PROLOGUE and config UNWINDER_GUESS,
> no build errors and the virtual machine can boot normally.
> 
> I would like to receive comments for the draft changes first and then
> send the formal v2, the function and variable name may be not proper,
> so any comments are welcome.
> 
> Since the merge window is coming soon and I am busy with the other
> higher priority stuff, so maybe I will send v2 after the merge window.
> 
> Thanks,
> Tiezhu
> 


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ