aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Martin <Dave.Martin@arm.com>2017-06-15 10:03:41 -0400
committerWill Deacon <will.deacon@arm.com>2017-06-20 07:42:59 -0400
commitbb4322f74340de578bc61ed0cfb9690ddeb9ef76 (patch)
tree6977efdb0f0aa4d2fc60fbc10604a9708ab5af91
parentbb4891a6c3551f27fa4d548b87a66c258bdb100b (diff)
arm64: signal: factor out signal frame record allocation
This patch factors out the allocator for signal frame optional records into a separate function, to ensure consistency and facilitate later expansion. No overrun checking is currently done, because the allocation is in user memory and anyway the kernel never tries to allocate enough space in the signal frame yet for an overrun to occur. This behaviour will be refined in future patches. The approach taken in this patch to allocation of the terminator record is not very clean: this will also be replaced in subsequent patches. For future extension, a comment is added in sigcontext.h documenting the current static allocations in __reserved[]. This will be important for determining under what circumstances userspace may or may not see an expanded signal frame. Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Dave Martin <Dave.Martin@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--arch/arm64/include/uapi/asm/sigcontext.h19
-rw-r--r--arch/arm64/kernel/signal.c43
2 files changed, 55 insertions, 7 deletions
diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h
index ee469be1ae1d..1328a2c14371 100644
--- a/arch/arm64/include/uapi/asm/sigcontext.h
+++ b/arch/arm64/include/uapi/asm/sigcontext.h
@@ -34,6 +34,25 @@ struct sigcontext {
34}; 34};
35 35
36/* 36/*
37 * Allocation of __reserved[]:
38 * (Note: records do not necessarily occur in the order shown here.)
39 *
40 * size description
41 *
42 * 0x210 fpsimd_context
43 * 0x10 esr_context
44 * 0x10 terminator (null _aarch64_ctx)
45 *
46 * 0xdd0 (reserved for future allocation)
47 *
48 * New records that can exceed this space need to be opt-in for userspace, so
49 * that an expanded signal frame is not generated unexpectedly. The mechanism
50 * for opting in will depend on the extension that generates each new record.
51 * The above table documents the maximum set and sizes of records than can be
52 * generated when userspace does not opt in for any such extension.
53 */
54
55/*
37 * Header to be used at the beginning of structures extending the user 56 * Header to be used at the beginning of structures extending the user
38 * context. Such structures must be placed after the rt_sigframe on the stack 57 * context. Such structures must be placed after the rt_sigframe on the stack
39 * and be 16-byte aligned. The last structure must be a dummy one with the 58 * and be 16-byte aligned. The last structure must be a dummy one with the
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index eaef530579f8..fa787e6ac7c2 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -79,6 +79,22 @@ static size_t sigframe_size(struct rt_sigframe_user_layout const *user)
79 return round_up(max(user->size, sizeof(struct rt_sigframe)), 16); 79 return round_up(max(user->size, sizeof(struct rt_sigframe)), 16);
80} 80}
81 81
82/*
83 * Allocate space for an optional record of <size> bytes in the user
84 * signal frame. The offset from the signal frame base address to the
85 * allocated block is assigned to *offset.
86 */
87static int sigframe_alloc(struct rt_sigframe_user_layout *user,
88 unsigned long *offset, size_t size)
89{
90 size_t padded_size = round_up(size, 16);
91
92 *offset = user->size;
93 user->size += padded_size;
94
95 return 0;
96}
97
82static void __user *apply_user_offset( 98static void __user *apply_user_offset(
83 struct rt_sigframe_user_layout const *user, unsigned long offset) 99 struct rt_sigframe_user_layout const *user, unsigned long offset)
84{ 100{
@@ -287,19 +303,32 @@ badframe:
287/* Determine the layout of optional records in the signal frame */ 303/* Determine the layout of optional records in the signal frame */
288static int setup_sigframe_layout(struct rt_sigframe_user_layout *user) 304static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
289{ 305{
290 user->fpsimd_offset = user->size; 306 int err;
291 user->size += round_up(sizeof(struct fpsimd_context), 16); 307
308 err = sigframe_alloc(user, &user->fpsimd_offset,
309 sizeof(struct fpsimd_context));
310 if (err)
311 return err;
292 312
293 /* fault information, if valid */ 313 /* fault information, if valid */
294 if (current->thread.fault_code) { 314 if (current->thread.fault_code) {
295 user->esr_offset = user->size; 315 err = sigframe_alloc(user, &user->esr_offset,
296 user->size += round_up(sizeof(struct esr_context), 16); 316 sizeof(struct esr_context));
317 if (err)
318 return err;
297 } 319 }
298 320
299 /* set the "end" magic */ 321 /*
300 user->end_offset = user->size; 322 * Allocate space for the terminator record.
323 * HACK: here we undo the reservation of space for the end record.
324 * This bodge should be replaced with a cleaner approach later on.
325 */
326 user->limit = offsetof(struct rt_sigframe, uc.uc_mcontext.__reserved) +
327 sizeof(user->sigframe->uc.uc_mcontext.__reserved);
301 328
302 return 0; 329 err = sigframe_alloc(user, &user->end_offset,
330 sizeof(struct _aarch64_ctx));
331 return err;
303} 332}
304 333
305 334