1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (c) 2015 Author: Oleg Nesterov <oleg@redhat.com> 3f08c3bdfSopenharmony_ci * Modify: Li Wang <liwang@redhat.com> 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify it 6f08c3bdfSopenharmony_ci * under the terms of version 2 of the GNU General Public License as 7f08c3bdfSopenharmony_ci * published by the Free Software Foundation. 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, but 10f08c3bdfSopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 11f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * you should have received a copy of the GNU General Public License along 14f08c3bdfSopenharmony_ci * with this program; if not, write the Free Software Foundation, Inc., 15f08c3bdfSopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16f08c3bdfSopenharmony_ci */ 17f08c3bdfSopenharmony_ci 18f08c3bdfSopenharmony_ci/* 19f08c3bdfSopenharmony_ci * Description: 20f08c3bdfSopenharmony_ci * 21f08c3bdfSopenharmony_ci * save_xstate_sig()->drop_init_fpu() doesn't look right. setup_rt_frame() 22f08c3bdfSopenharmony_ci * can fail after that, in this case the next setup_rt_frame() triggered 23f08c3bdfSopenharmony_ci * by SIGSEGV won't save fpu simply because the old state was lost. This 24f08c3bdfSopenharmony_ci * obviously mean that fpu won't be restored after sys_rt_sigreturn() from 25f08c3bdfSopenharmony_ci * SIGSEGV handler. 26f08c3bdfSopenharmony_ci * 27f08c3bdfSopenharmony_ci * These commits fix the issue on v3.17-rc3-3 stable kernel: 28f08c3bdfSopenharmony_ci * 29f08c3bdfSopenharmony_ci * commit df24fb859a4e200d9324e2974229fbb7adf00aef 30f08c3bdfSopenharmony_ci * Author: Oleg Nesterov <oleg@redhat.com> 31f08c3bdfSopenharmony_ci * Date: Tue Sep 2 19:57:17 2014 +0200 32f08c3bdfSopenharmony_ci * 33f08c3bdfSopenharmony_ci * commit 66463db4fc5605d51c7bb81d009d5bf30a783a2c 34f08c3bdfSopenharmony_ci * Author: Oleg Nesterov <oleg@redhat.com> 35f08c3bdfSopenharmony_ci * Date: Tue Sep 2 19:57:13 2014 +0200 36f08c3bdfSopenharmony_ci * 37f08c3bdfSopenharmony_ci * Reproduce: 38f08c3bdfSopenharmony_ci * Test-case (needs -O2). 39f08c3bdfSopenharmony_ci */ 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ci#include <stdio.h> 42f08c3bdfSopenharmony_ci#include <signal.h> 43f08c3bdfSopenharmony_ci#include <unistd.h> 44f08c3bdfSopenharmony_ci#include <sys/syscall.h> 45f08c3bdfSopenharmony_ci#include <sys/mman.h> 46f08c3bdfSopenharmony_ci#include <pthread.h> 47f08c3bdfSopenharmony_ci#include <assert.h> 48f08c3bdfSopenharmony_ci#include <errno.h> 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_ci#include "test.h" 51f08c3bdfSopenharmony_ci#include "lapi/syscalls.h" 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_cichar *TCID = "signal06"; 54f08c3bdfSopenharmony_ciint TST_TOTAL = 5; 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ci#if __x86_64__ 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ci#define LOOPS 30000 59f08c3bdfSopenharmony_ci#define VALUE 123.456 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_civolatile double D; 62f08c3bdfSopenharmony_civolatile int FLAGE; 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_cichar altstack[4096 * 10] __attribute__((aligned(4096))); 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_civoid test(void) 67f08c3bdfSopenharmony_ci{ 68f08c3bdfSopenharmony_ci int loop = 0; 69f08c3bdfSopenharmony_ci int pid = getpid(); 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci D = VALUE; 72f08c3bdfSopenharmony_ci while (D == VALUE && loop < LOOPS) { 73f08c3bdfSopenharmony_ci /* sys_tkill(pid, SIGHUP); asm to avoid save/reload 74f08c3bdfSopenharmony_ci * fp regs around c call */ 75f08c3bdfSopenharmony_ci int unused; 76f08c3bdfSopenharmony_ci asm volatile ("syscall" : "=a"(unused) : "a"(__NR_tkill), "D"(pid), "S"(SIGHUP) : "rcx", "r11"); 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ci loop++; 79f08c3bdfSopenharmony_ci } 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci FLAGE = 1; 82f08c3bdfSopenharmony_ci tst_resm(TINFO, "loop = %d", loop); 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci if (loop == LOOPS) { 85f08c3bdfSopenharmony_ci tst_resm(TPASS, "%s call succeeded", TCID); 86f08c3bdfSopenharmony_ci } else { 87f08c3bdfSopenharmony_ci tst_resm(TFAIL, "Bug Reproduced!"); 88f08c3bdfSopenharmony_ci tst_exit(); 89f08c3bdfSopenharmony_ci } 90f08c3bdfSopenharmony_ci} 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_civoid sigh(int sig LTP_ATTRIBUTE_UNUSED) 93f08c3bdfSopenharmony_ci{ 94f08c3bdfSopenharmony_ci} 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_civoid *tfunc(void *arg LTP_ATTRIBUTE_UNUSED) 97f08c3bdfSopenharmony_ci{ 98f08c3bdfSopenharmony_ci int i; 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ci for (i = -1; ; i *= -1) { 101f08c3bdfSopenharmony_ci if (i == -1) { 102f08c3bdfSopenharmony_ci TEST(mprotect(altstack, sizeof(altstack), PROT_READ)); 103f08c3bdfSopenharmony_ci if (TEST_RETURN == -1) 104f08c3bdfSopenharmony_ci tst_brkm(TBROK | TTERRNO, NULL, "mprotect failed"); 105f08c3bdfSopenharmony_ci } 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci TEST(mprotect(altstack, sizeof(altstack), PROT_READ | PROT_WRITE)); 108f08c3bdfSopenharmony_ci if (TEST_RETURN == -1) 109f08c3bdfSopenharmony_ci tst_brkm(TBROK | TTERRNO, NULL, "mprotect failed"); 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci if (FLAGE == 1) 112f08c3bdfSopenharmony_ci return NULL; 113f08c3bdfSopenharmony_ci } 114f08c3bdfSopenharmony_ci} 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ciint main(int ac, char **av) 117f08c3bdfSopenharmony_ci{ 118f08c3bdfSopenharmony_ci int i, lc; 119f08c3bdfSopenharmony_ci pthread_t pt; 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci tst_parse_opts(ac, av, NULL, NULL); 122f08c3bdfSopenharmony_ci 123f08c3bdfSopenharmony_ci stack_t st = { 124f08c3bdfSopenharmony_ci .ss_sp = altstack, 125f08c3bdfSopenharmony_ci .ss_size = sizeof(altstack), 126f08c3bdfSopenharmony_ci .ss_flags = SS_ONSTACK, 127f08c3bdfSopenharmony_ci }; 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci struct sigaction sa = { 130f08c3bdfSopenharmony_ci .sa_handler = sigh, 131f08c3bdfSopenharmony_ci }; 132f08c3bdfSopenharmony_ci 133f08c3bdfSopenharmony_ci TEST(sigaction(SIGSEGV, &sa, NULL)); 134f08c3bdfSopenharmony_ci if (TEST_RETURN == -1) 135f08c3bdfSopenharmony_ci tst_brkm(TBROK | TTERRNO, NULL, 136f08c3bdfSopenharmony_ci "SIGSEGV signal setup failed"); 137f08c3bdfSopenharmony_ci sigaltstack(&st, NULL); 138f08c3bdfSopenharmony_ci sa.sa_flags = SA_ONSTACK; 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci TEST(sigaction(SIGHUP, &sa, NULL)); 141f08c3bdfSopenharmony_ci if (TEST_RETURN == -1) 142f08c3bdfSopenharmony_ci tst_brkm(TBROK | TTERRNO, NULL, 143f08c3bdfSopenharmony_ci "SIGHUP signal setup failed"); 144f08c3bdfSopenharmony_ci 145f08c3bdfSopenharmony_ci for (lc = 0; TEST_LOOPING(lc); lc++) { 146f08c3bdfSopenharmony_ci tst_count = 0; 147f08c3bdfSopenharmony_ci 148f08c3bdfSopenharmony_ci for (i = 0; i < TST_TOTAL; i++) { 149f08c3bdfSopenharmony_ci FLAGE = 0; 150f08c3bdfSopenharmony_ci 151f08c3bdfSopenharmony_ci TEST(pthread_create(&pt, NULL, tfunc, NULL)); 152f08c3bdfSopenharmony_ci if (TEST_RETURN) 153f08c3bdfSopenharmony_ci tst_brkm(TBROK | TRERRNO, NULL, 154f08c3bdfSopenharmony_ci "pthread_create failed"); 155f08c3bdfSopenharmony_ci 156f08c3bdfSopenharmony_ci test(); 157f08c3bdfSopenharmony_ci 158f08c3bdfSopenharmony_ci TEST(pthread_join(pt, NULL)); 159f08c3bdfSopenharmony_ci if (TEST_RETURN) 160f08c3bdfSopenharmony_ci tst_brkm(TBROK | TRERRNO, NULL, 161f08c3bdfSopenharmony_ci "pthread_join failed"); 162f08c3bdfSopenharmony_ci } 163f08c3bdfSopenharmony_ci } 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_ci tst_exit(); 166f08c3bdfSopenharmony_ci} 167f08c3bdfSopenharmony_ci 168f08c3bdfSopenharmony_ci#else 169f08c3bdfSopenharmony_ciint main(void) 170f08c3bdfSopenharmony_ci{ 171f08c3bdfSopenharmony_ci tst_brkm(TCONF, NULL, "Only test on x86_64."); 172f08c3bdfSopenharmony_ci} 173f08c3bdfSopenharmony_ci#endif 174