Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

x86/pkeys: Add helper functions to update PKRU on the sigframe

In the case where a user thread sets up an alternate signal stack protected
by the default PKEY (i.e. PKEY 0), while the thread's stack is protected by
a non-zero PKEY, both these PKEYS have to be enabled in the PKRU register
for the signal to be delivered to the application correctly. However, the
PKRU value restored after handling the signal must not enable this extra
PKEY (i.e. PKEY 0) - i.e., the PKRU value in the sigframe has to be
overwritten with the user-defined value.

Add helper functions that will update PKRU value in the sigframe after
XSAVE.

Note that sig_prepare_pkru() makes no assumption about which PKEY could
be used to protect the altstack (i.e. it may not be part of init_pkru),
and so enables all PKEYS.

No functional change.

Signed-off-by: Aruna Ramakrishna <aruna.ramakrishna@oracle.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20240802061318.2140081-3-aruna.ramakrishna@oracle.com

authored by

Aruna Ramakrishna and committed by
Thomas Gleixner
84ee6e8d 24cf2bc9

+43
+10
arch/x86/kernel/fpu/signal.c
··· 64 64 } 65 65 66 66 /* 67 + * Update the value of PKRU register that was already pushed onto the signal frame. 68 + */ 69 + static inline int update_pkru_in_sigframe(struct xregs_state __user *buf, u32 pkru) 70 + { 71 + if (unlikely(!cpu_feature_enabled(X86_FEATURE_OSPKE))) 72 + return 0; 73 + return __put_user(pkru, (unsigned int __user *)get_xsave_addr_user(buf, XFEATURE_PKRU)); 74 + } 75 + 76 + /* 67 77 * Signal frame handlers. 68 78 */ 69 79 static inline bool save_fsave_header(struct task_struct *tsk, void __user *buf)
+13
arch/x86/kernel/fpu/xstate.c
··· 993 993 } 994 994 EXPORT_SYMBOL_GPL(get_xsave_addr); 995 995 996 + /* 997 + * Given an xstate feature nr, calculate where in the xsave buffer the state is. 998 + * The xsave buffer should be in standard format, not compacted (e.g. user mode 999 + * signal frames). 1000 + */ 1001 + void __user *get_xsave_addr_user(struct xregs_state __user *xsave, int xfeature_nr) 1002 + { 1003 + if (WARN_ON_ONCE(!xfeature_enabled(xfeature_nr))) 1004 + return NULL; 1005 + 1006 + return (void __user *)xsave + xstate_offsets[xfeature_nr]; 1007 + } 1008 + 996 1009 #ifdef CONFIG_ARCH_HAS_PKEYS 997 1010 998 1011 /*
+2
arch/x86/kernel/fpu/xstate.h
··· 54 54 extern void fpu__init_cpu_xstate(void); 55 55 extern void fpu__init_system_xstate(unsigned int legacy_size); 56 56 57 + extern void __user *get_xsave_addr_user(struct xregs_state __user *xsave, int xfeature_nr); 58 + 57 59 static inline u64 xfeatures_mask_supervisor(void) 58 60 { 59 61 return fpu_kernel_cfg.max_features & XFEATURE_MASK_SUPERVISOR_SUPPORTED;
+18
arch/x86/kernel/signal.c
··· 61 61 } 62 62 63 63 /* 64 + * Enable all pkeys temporarily, so as to ensure that both the current 65 + * execution stack as well as the alternate signal stack are writeable. 66 + * The application can use any of the available pkeys to protect the 67 + * alternate signal stack, and we don't know which one it is, so enable 68 + * all. The PKRU register will be reset to init_pkru later in the flow, 69 + * in fpu__clear_user_states(), and it is the application's responsibility 70 + * to enable the appropriate pkey as the first step in the signal handler 71 + * so that the handler does not segfault. 72 + */ 73 + static inline u32 sig_prepare_pkru(void) 74 + { 75 + u32 orig_pkru = read_pkru(); 76 + 77 + write_pkru(0); 78 + return orig_pkru; 79 + } 80 + 81 + /* 64 82 * Set up a signal frame. 65 83 */ 66 84