The glibc tst-minsigstksz-5 test fails with a protection id trap.
tst-minsigstksz (pid 19958): Protection id trap (code 7) at 00000000f5b00497
The problem seems to be that the signal return trampoline is placed on the alternate stack
but the alternate is not executable. It is allocated by malloc.
dave@mx3210:~/gnu/glibc/objdir$ gdb tst-minsigstksz-5 GNU gdb (Debian 10.1-2) 10.1.90.20210103-git
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "hppa-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from tst-minsigstksz-5...
(gdb) break handler
Breakpoint 1 at 0x1079c: file tst-minsigstksz-5.c, line 43.
(gdb) r
Starting program: /home/dave/gnu/glibc/objdir/tst-minsigstksz-5
Program received signal SIGUSR1, User defined signal 1.
getpid () at ../sysdeps/unix/syscall-template.S:91
91 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) c
Continuing.
Breakpoint 1, handler (signo=16) at tst-minsigstksz-5.c:43
warning: Source file is more recent than executable.
43
(gdb) p/x $sp
$1 = 0xf5b00900
(gdb) p/x $rp
$2 = 0xf5b00494
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
<signal handler called>
(gdb) disass $pc-16,$pc+16
Dump of assembler code from 0xf5b00484 to 0xf5b004a4:
0xf5b00484: movib,>= 6,r6,0xf5b01af0
0xf5b00488: movib,>= 6,r6,0xf5b01af4
0xf5b0048c: movib,>= 6,r6,0xf5b01af8
0xf5b00490: movib,>= 6,r6,0xf5b01afc
=> 0xf5b00494: ldi 1,r25
0xf5b00498: ldi ad,r20
0xf5b0049c: be,l 100(sr2,r0),sr0,r31
0xf5b004a0: nop
End of assembler dump.
tst-minsigstksz (pid 8032): Protection id trap (code 7) at 00000000f5b00497
dave@mx3210:/proc/8032$ cat maps
00010000-00012000 r-xp 00000000 08:11 6958050 /home/dave/gnu/glibc/objdir/tst-minsigstksz-5
00012000-00013000 rwxp 00002000 08:11 6958050 /home/dave/gnu/glibc/objdir/tst-minsigstksz-5
00013000-00034000 rwxp 00000000 00:00 0 [heap]
f3b00000-f7b01000 rw-p 00000000 00:00 0
f7b01000-f7b23000 rwxp 00000000 00:00 0 [stack]
f90b8000-f9239000 r-xp 00000000 08:25 38369008 /lib/hppa-linux-gnu/libc-2.32.so
f9239000-f923b000 r--p 00181000 08:25 38369008 /lib/hppa-linux-gnu/libc-2.32.so
f923b000-f9240000 rwxp 00183000 08:25 38369008 /lib/hppa-linux-gnu/libc-2.32.so
f9240000-f9242000 rwxp 00000000 00:00 0
f98b8000-f98e2000 r-xp 00000000 08:25 38368971 /lib/hppa-linux-gnu/ld-2.32.so
f98e2000-f98e3000 r--p 0002a000 08:25 38368971 /lib/hppa-linux-gnu/ld-2.32.so
f98e3000-f98e7000 rwxp 0002b000 08:25 38368971 /lib/hppa-linux-gnu/ld-2.32.so
f9afb000-f9b00000 rw-p 00000000 00:00 0
Stacks are normally executable on hppa so the trampoline works. But user code wouldn't normally make an alternate
stack executable.
Dave
--
John David Anglin dave.anglin@xxxxxxxx
/* Test of signal delivery on an alternate stack with MINSIGSTKSZ size.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#define FAIL_RET(s,...) \
do { \
printf (s, errno); \
return 1; \
} while (0)
static volatile sig_atomic_t handler_run;
static void
handler (int signo)
{
/* Clear a bit of on-stack memory. */
volatile char buffer[256];
for (size_t i = 0; i < sizeof (buffer); ++i)
buffer[i] = 0;
handler_run = 1;
}
int
do_test (void)
{
size_t stack_buffer_size = 64 * 1024 * 1024;
void *stack_buffer = malloc (stack_buffer_size);
void *stack_end = stack_buffer + stack_buffer_size;
memset (stack_buffer, 0xCC, stack_buffer_size);
void *stack_bottom = stack_buffer + (stack_buffer_size + MINSIGSTKSZ) / 2;
void *stack_top = stack_bottom + MINSIGSTKSZ;
stack_t stack =
{
.ss_sp = stack_bottom,
.ss_size = MINSIGSTKSZ,
};
if (sigaltstack (&stack, NULL) < 0)
FAIL_RET ("sigaltstack: %m\n");
struct sigaction act =
{
.sa_handler = handler,
.sa_flags = SA_ONSTACK,
};
if (sigaction (SIGUSR1, &act, NULL) < 0)
FAIL_RET ("sigaction: %m\n");
if (kill (getpid (), SIGUSR1) < 0)
FAIL_RET ("kill: %m\n");
if (handler_run != 1)
FAIL_RET ("handler did not run\n");
for (void *p = stack_buffer; p < stack_bottom; ++p)
if (*(unsigned char *) p != 0xCC)
FAIL_RET ("changed byte %ld bytes below configured stack\n",
(long) (stack_bottom - p));
for (void *p = stack_top; p < stack_end; ++p)
if (*(unsigned char *) p != 0xCC)
FAIL_RET ("changed byte %ld bytes above configured stack\n",
(long) (p - stack_top));
free (stack_buffer);
return 0;
}
int
main (void)
{
return do_test();
}