]> git.baikalelectronics.ru Git - kernel.git/commitdiff
powerpc/signal: Report minimum signal frame size to userspace via AT_MINSIGSTKSZ
authorNicholas Piggin <npiggin@gmail.com>
Mon, 7 Mar 2022 18:27:34 +0000 (04:27 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 19 May 2022 13:11:26 +0000 (23:11 +1000)
Implement the AT_MINSIGSTKSZ AUXV entry, allowing userspace to
dynamically size stack allocations in a manner forward-compatible with
new processor state saved in the signal frame

For now these statically find the maximum signal frame size rather than
doing any runtime testing of features to minimise the size.

glibc 2.34 will take advantage of this, as will applications that use
use _SC_MINSIGSTKSZ and _SC_SIGSTKSZ.

Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
References: 9c59c095080b ("arm64: signal: Report signal frame size to userspace via auxv")
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220307182734.289289-2-npiggin@gmail.com
arch/powerpc/include/asm/elf.h
arch/powerpc/include/asm/signal.h
arch/powerpc/include/uapi/asm/auxvec.h
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c

index 971589a21bc033ee95857817f563b123bb10d90c..79f1c480b5eb2fe6e3266c46fe8c232226693ddd 100644 (file)
@@ -160,7 +160,7 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
  *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
  * update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes
  */
-#define ARCH_DLINFO                                                    \
+#define COMMON_ARCH_DLINFO                                             \
 do {                                                                   \
        /* Handle glibc compatibility. */                               \
        NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);                        \
@@ -173,6 +173,18 @@ do {                                                                       \
        ARCH_DLINFO_CACHE_GEOMETRY;                                     \
 } while (0)
 
+#define ARCH_DLINFO                                                    \
+do {                                                                   \
+       COMMON_ARCH_DLINFO;                                             \
+       NEW_AUX_ENT(AT_MINSIGSTKSZ, get_min_sigframe_size());           \
+} while (0)
+
+#define COMPAT_ARCH_DLINFO                                             \
+do {                                                                   \
+       COMMON_ARCH_DLINFO;                                             \
+       NEW_AUX_ENT(AT_MINSIGSTKSZ, get_min_sigframe_size_compat());    \
+} while (0)
+
 /* Relocate the kernel image to @final_address */
 void relocate(unsigned long final_address);
 
index 99e1c6de27bc167d01b57d24588ac6eefcdeac4d..922d43700fb41f05ec58721090d2187165891108 100644 (file)
@@ -9,4 +9,9 @@
 struct pt_regs;
 void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
 
+unsigned long get_min_sigframe_size_32(void);
+unsigned long get_min_sigframe_size_64(void);
+unsigned long get_min_sigframe_size(void);
+unsigned long get_min_sigframe_size_compat(void);
+
 #endif /* _ASM_POWERPC_SIGNAL_H */
index 7af21dc0e32094a05a07481891835c4f43f74b2e..aa7c162154538e3b897ad29a337d3423a7a0c3e0 100644 (file)
@@ -48,6 +48,8 @@
 #define AT_L3_CACHESIZE                46
 #define AT_L3_CACHEGEOMETRY    47
 
-#define AT_VECTOR_SIZE_ARCH    14 /* entries in ARCH_DLINFO */
+#define AT_MINSIGSTKSZ         51      /* stack needed for signal delivery */
+
+#define AT_VECTOR_SIZE_ARCH    15 /* entries in ARCH_DLINFO */
 
 #endif
index f7f8620663c70fd523e1512dd1007e34330ec2ea..68a91e553e14cea211f3b7b7001842097bf227fc 100644 (file)
@@ -141,6 +141,21 @@ unsigned long copy_ckvsx_from_user(struct task_struct *task,
 
 int show_unhandled_signals = 1;
 
+unsigned long get_min_sigframe_size(void)
+{
+       if (IS_ENABLED(CONFIG_PPC64))
+               return get_min_sigframe_size_64();
+       else
+               return get_min_sigframe_size_32();
+}
+
+#ifdef CONFIG_COMPAT
+unsigned long get_min_sigframe_size_compat(void)
+{
+       return get_min_sigframe_size_32();
+}
+#endif
+
 /*
  * Allocate space for the signal frame
  */
index d84c434b2b78edf9988ba14ec4ffc7b9b143aaa1..157a7403e3eb3e3f39002c2f23e0927323fef6f9 100644 (file)
@@ -233,6 +233,12 @@ struct rt_sigframe {
        int                     abigap[56];
 };
 
+unsigned long get_min_sigframe_size_32(void)
+{
+       return max(sizeof(struct rt_sigframe) + __SIGNAL_FRAMESIZE + 16,
+                  sizeof(struct sigframe) + __SIGNAL_FRAMESIZE);
+}
+
 /*
  * Save the current user registers on the user stack.
  * We only save the altivec/spe registers if the process has used
index 858fc13b8c5196a0ca6df202b655e096cd5e69cc..472596a109e2d592d628f21b000258bfe60791be 100644 (file)
@@ -66,6 +66,11 @@ struct rt_sigframe {
        char abigap[USER_REDZONE_SIZE];
 } __attribute__ ((aligned (16)));
 
+unsigned long get_min_sigframe_size_64(void)
+{
+       return sizeof(struct rt_sigframe) + __SIGNAL_FRAMESIZE;
+}
+
 /*
  * This computes a quad word aligned pointer inside the vmx_reserve array
  * element. For historical reasons sigcontext might not be quad word aligned,