X-Git-Url: https://git.codelabs.ch/?p=muen%2Flinux.git;a=blobdiff_plain;f=arch%2Farm64%2Finclude%2Fasm%2Fprocessor.h;h=7675989325494816a251ee20774bb5987973c13c;hp=63d3850db224a0f630d6328637edd11410cc476f;hb=65896545b69ffaac947c12e11d3dcc57fd1fb772;hpb=20b8547277a6e8ee1d928792c1b2782c9a2a6cf5 diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 63d3850db224..767598932549 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -34,6 +34,8 @@ #ifdef __KERNEL__ +#include +#include #include #include @@ -103,11 +105,18 @@ struct cpu_context { struct thread_struct { struct cpu_context cpu_context; /* cpu context */ - unsigned long tp_value; /* TLS register */ -#ifdef CONFIG_COMPAT - unsigned long tp2_value; -#endif - struct user_fpsimd_state fpsimd_state; + + /* + * Whitelisted fields for hardened usercopy: + * Maintainers must ensure manually that this contains no + * implicit padding. + */ + struct { + unsigned long tp_value; /* TLS register */ + unsigned long tp2_value; + struct user_fpsimd_state fpsimd_state; + } uw; + unsigned int fpsimd_cpu; void *sve_state; /* SVE registers, if any */ unsigned int sve_vl; /* SVE vector length */ @@ -117,14 +126,17 @@ struct thread_struct { struct debug_info debug; /* debugging */ }; -/* - * Everything usercopied to/from thread_struct is statically-sized, so - * no hardened usercopy whitelist is needed. - */ static inline void arch_thread_struct_whitelist(unsigned long *offset, unsigned long *size) { - *offset = *size = 0; + /* Verify that there is no padding among the whitelisted fields: */ + BUILD_BUG_ON(sizeof_field(struct thread_struct, uw) != + sizeof_field(struct thread_struct, uw.tp_value) + + sizeof_field(struct thread_struct, uw.tp2_value) + + sizeof_field(struct thread_struct, uw.fpsimd_state)); + + *offset = offsetof(struct thread_struct, uw); + *size = sizeof_field(struct thread_struct, uw); } #ifdef CONFIG_COMPAT @@ -132,13 +144,13 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset, ({ \ unsigned long *__tls; \ if (is_compat_thread(task_thread_info(t))) \ - __tls = &(t)->thread.tp2_value; \ + __tls = &(t)->thread.uw.tp2_value; \ else \ - __tls = &(t)->thread.tp_value; \ + __tls = &(t)->thread.uw.tp_value; \ __tls; \ }) #else -#define task_user_tls(t) (&(t)->thread.tp_value) +#define task_user_tls(t) (&(t)->thread.uw.tp_value) #endif /* Sync TPIDR_EL0 back to thread_struct for current */