From: Andrey Ryabinin <aryabi...@virtuozzo.com> We are using cpuid faults to emulate cpuid in containers. This conflicts with arch_prctl(ARCH_SET_CPUID, 0) which allows to enable cpuid faulting so that cpuid instruction causes SIGSEGV.
Add TIF_CPUID_OVERRIDE thread info flag which is added on all !ve0 tasks. And check this flag along with TIF_NOCPUID to decide whether we need to enable/disable cpuid faults or not. https://jira.sw.ru/browse/PSBM-121823 Signed-off-by: Andrey Ryabinin <aryabi...@virtuozzo.com> Reviewed-by: Kirill Tkhai <ktk...@virtuozzo.com> (cherry-picked from vz8 commit f7458a78593c ("x86: make ARCH_[SET|GET]_CPUID friends with /proc/vz/cpuid_override")) Signed-off-by: Nikita Yushchenko <nikita.yushche...@virtuozzo.com> --- arch/x86/include/asm/thread_info.h | 4 +++- arch/x86/kernel/process.c | 13 +++++++++---- arch/x86/kernel/traps.c | 3 +++ kernel/ve/ve.c | 3 +++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index de406d93b515..850827fc0123 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -95,6 +95,7 @@ struct thread_info { #define TIF_IO_BITMAP 22 /* uses I/O bitmap */ #define TIF_FORCED_TF 24 /* true if TF in eflags artificially */ #define TIF_BLOCKSTEP 25 /* set when we want DEBUGCTLMSR_BTF */ +#define TIF_CPUID_OVERRIDE 26 /* CPUID emulation enabled */ #define TIF_LAZY_MMU_UPDATES 27 /* task is updating the mmu lazily */ #define TIF_ADDR32 29 /* 32-bit address space on 64 bits */ @@ -117,13 +118,14 @@ struct thread_info { #define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP) #define _TIF_FORCED_TF (1 << TIF_FORCED_TF) #define _TIF_BLOCKSTEP (1 << TIF_BLOCKSTEP) +#define _TIF_CPUID_OVERRIDE (1 << TIF_CPUID_OVERRIDE) #define _TIF_LAZY_MMU_UPDATES (1 << TIF_LAZY_MMU_UPDATES) #define _TIF_ADDR32 (1 << TIF_ADDR32) /* flags to check in __switch_to() */ #define _TIF_WORK_CTXSW_BASE \ (_TIF_NOCPUID | _TIF_NOTSC | _TIF_BLOCKSTEP | \ - _TIF_SSBD | _TIF_SPEC_FORCE_UPDATE | _TIF_SLD) + _TIF_SSBD | _TIF_SPEC_FORCE_UPDATE | _TIF_SLD | _TIF_CPUID_OVERRIDE) /* * Avoid calls to __switch_to_xtra() on UP as STIBP is not evaluated. diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index ac178b578637..14fd45ae4a25 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -290,7 +290,8 @@ static void set_cpuid_faulting(bool on) static void disable_cpuid(void) { preempt_disable(); - if (!test_and_set_thread_flag(TIF_NOCPUID)) { + if (!test_and_set_thread_flag(TIF_NOCPUID) || + test_thread_flag(TIF_CPUID_OVERRIDE)) { /* * Must flip the CPU state synchronously with * TIF_NOCPUID in the current running context. @@ -303,7 +304,8 @@ static void disable_cpuid(void) static void enable_cpuid(void) { preempt_disable(); - if (test_and_clear_thread_flag(TIF_NOCPUID)) { + if (test_and_clear_thread_flag(TIF_NOCPUID) && + !test_thread_flag(TIF_CPUID_OVERRIDE)) { /* * Must flip the CPU state synchronously with * TIF_NOCPUID in the current running context. @@ -636,6 +638,7 @@ static inline void cr4_toggle_bits_irqsoff(unsigned long mask) void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p) { unsigned long tifp, tifn; + bool prev_cpuid, next_cpuid; tifn = READ_ONCE(task_thread_info(next_p)->flags); tifp = READ_ONCE(task_thread_info(prev_p)->flags); @@ -658,8 +661,10 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p) if ((tifp ^ tifn) & _TIF_NOTSC) cr4_toggle_bits_irqsoff(X86_CR4_TSD); - if ((tifp ^ tifn) & _TIF_NOCPUID) - set_cpuid_faulting(!!(tifn & _TIF_NOCPUID)); + prev_cpuid = (tifp & _TIF_NOCPUID) || (tifp & _TIF_CPUID_OVERRIDE); + next_cpuid = (tifn & _TIF_NOCPUID) || (tifn & _TIF_CPUID_OVERRIDE); + if (prev_cpuid != next_cpuid) + set_cpuid_faulting(next_cpuid); if (likely(!((tifp | tifn) & _TIF_SPEC_FORCE_UPDATE))) { __speculation_ctrl_update(tifp, tifn); diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index b56deed1702c..20882bb12518 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -534,6 +534,9 @@ static int check_cpuid_fault(struct pt_regs *regs, long error_code) if (error_code != 0) return 0; + if (test_thread_flag(TIF_NOCPUID)) + return 0; + addr = convert_ip_to_linear(current, regs); if (get_user(opcode, (unsigned short __user *)addr)) return 0; diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c index 4caa8a1f27ca..9dabec194988 100644 --- a/kernel/ve/ve.c +++ b/kernel/ve/ve.c @@ -875,6 +875,9 @@ static void ve_attach(struct cgroup_taskset *tset) task->parent_exec_id--; ve_set_task_start_time(ve, task); + + set_tsk_thread_flag(task, TIF_CPUID_OVERRIDE); + task->task_ve = ve; } } -- 2.30.2 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel