The rseq rseq_cs.ptr.{ptr32,padding} uapi endianness handling is entirely wrong on 32-bit little endian: a preprocessor logic mistake wrongly uses the big endian field layout on 32-bit little endian architectures. Fortunately, those ptr32 accessors were never used within the kernel, and only meant as a convenience for user-space. While working on fixing the ppc32 support in librseq [1], I made sure all 32-bit little endian architectures stopped depending on little endian byte ordering by using the ptr32 field. It led me to discover this wrong ptr32 field ordering on little endian. Because it is already exposed as a UAPI, all we can do for the existing fields is document the wrong behavior and encourage users to use alternative mechanisms. Introduce a new rseq_cs.arch field with correct field ordering. Use this opportunity to improve the layout so accesses to architecture fields on both 32-bit and 64-bit architectures are done through the same field hierarchy, which is much nicer than the previous scheme. The intended use is now: * rseq_thread_area->rseq_cs.ptr64: Access the 64-bit value of the rseq_cs pointer. Available on all architectures (unchanged). * rseq_thread_area->rseq_cs.arch.ptr: Access the architecture specific layout of the rseq_cs pointer. This is a 32-bit field on 32-bit architectures, and a 64-bit field on 64-bit architectures. Link: https://git.kernel.org/pub/scm/libs/librseq/librseq.git/ [1] Fixes: ec9c82e03a74 ("rseq: uapi: Declare rseq_cs field as union, update includes") Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@xxxxxxxxxxxx> Cc: Florian Weimer <fw@xxxxxxxxxxxxx> Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Cc: linux-api@xxxxxxxxxxxxxxx Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx> Cc: Boqun Feng <boqun.feng@xxxxxxxxx> Cc: Andy Lutomirski <luto@xxxxxxxxxxxxxx> Cc: Dave Watson <davejwatson@xxxxxx> Cc: Paul Turner <pjt@xxxxxxxxxx> Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> Cc: Russell King <linux@xxxxxxxxxxxxxxxx> Cc: "H . Peter Anvin" <hpa@xxxxxxxxx> Cc: Andi Kleen <andi@xxxxxxxxxxxxxx> Cc: Christian Brauner <christian.brauner@xxxxxxxxxx> Cc: Ben Maurer <bmaurer@xxxxxx> Cc: Steven Rostedt <rostedt@xxxxxxxxxxx> Cc: Josh Triplett <josh@xxxxxxxxxxxxxxxx> Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> Cc: Catalin Marinas <catalin.marinas@xxxxxxx> Cc: Will Deacon <will.deacon@xxxxxxx> Cc: Michael Kerrisk <mtk.manpages@xxxxxxxxx> Cc: Joel Fernandes <joelaf@xxxxxxxxxx> Cc: Paul E. McKenney <paulmck@xxxxxxxxxx> --- include/uapi/linux/rseq.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/uapi/linux/rseq.h b/include/uapi/linux/rseq.h index 9a402fdb60e9..68f61cdb45db 100644 --- a/include/uapi/linux/rseq.h +++ b/include/uapi/linux/rseq.h @@ -108,6 +108,12 @@ struct rseq { */ union { __u64 ptr64; + + /* + * The "ptr" field layout is broken on little-endian + * 32-bit architectures due to wrong preprocessor logic. + * DO NOT USE. + */ #ifdef __LP64__ __u64 ptr; #else @@ -121,6 +127,23 @@ struct rseq { #endif /* ENDIAN */ } ptr; #endif + + /* + * The "arch" field provides architecture accessor for + * the ptr field based on architecture pointer size and + * endianness. + */ + struct { +#ifdef __LP64__ + __u64 ptr; +#elif defined(__BYTE_ORDER) ? (__BYTE_ORDER == __BIG_ENDIAN) : defined(__BIG_ENDIAN) + __u32 padding; /* Initialized to zero. */ + __u32 ptr; +#else + __u32 ptr; + __u32 padding; /* Initialized to zero. */ +#endif + } arch; } rseq_cs; /* -- 2.17.1