Commit 2896b2df authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman

powerpc/signal: Report minimum signal frame size to userspace via AT_MINSIGSTKSZ

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: default avatarTulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
References: 94b07c1f ("arm64: signal: Report signal frame size to userspace via auxv")
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220307182734.289289-2-npiggin@gmail.com
parent 2f82ec19
......@@ -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);
......
......@@ -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 */
......@@ -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
......@@ -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
*/
......
......@@ -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
......
......@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment