"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-bad-altstack.c" (15 Mar 2019, 4877 Bytes) of package /linux/privat/stress-ng-0.09.56.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stress-bad-altstack.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.52_vs_0.09.54.

    1 /*
    2  * Copyright (C) 2013-2019 Canonical, Ltd.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   17  *
   18  * This code is a complete clean re-write of the stress tool by
   19  * Colin Ian King <colin.king@canonical.com> and attempts to be
   20  * backwardly compatible with the stress tool by Amos Waterland
   21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   22  * functionality.
   23  *
   24  */
   25 #include "stress-ng.h"
   26 
   27 #if defined(HAVE_SIGALTSTACK)
   28 
   29 static void *stack;
   30 static const size_t stack_sz = MINSIGSTKSZ;
   31 
   32 static void MLOCKED_TEXT stress_segv_handler(int signum)
   33 {
   34     uint8_t data[32];
   35 
   36     (void)signum;
   37     (void)munmap(stack, stack_sz);
   38     (void)memset(data, 0, sizeof(data));
   39     _exit(EXIT_SUCCESS);
   40 }
   41 
   42 /*
   43  *  stress_bad_altstack()
   44  *  create bad alternative signal stacks and cause
   45  *  a SIGSEGV when handling SIGSEGVs. The kernel
   46  *  should kill these.
   47  */
   48 static int stress_bad_altstack(const args_t *args)
   49 {
   50     set_oom_adjustment(args->name, true);
   51 
   52     stack = mmap(NULL, stack_sz, PROT_READ | PROT_WRITE,
   53             MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
   54     if (stack == MAP_FAILED) {
   55         pr_err("%s: cannot mmap signal handler stack, errno=%d (%s)\n",
   56             args->name, errno, strerror(errno));
   57         return EXIT_NO_RESOURCE;
   58     }
   59 
   60     if (stress_sighandler(args->name, SIGSEGV, stress_segv_handler, NULL) < 0)
   61         return EXIT_FAILURE;
   62 
   63     do {
   64         pid_t pid;
   65 
   66         (void)mwc32();
   67 again:
   68         if (!g_keep_stressing_flag)
   69             return EXIT_SUCCESS;
   70         pid = fork();
   71         if (pid < 0) {
   72             if ((errno == EAGAIN) || (errno == EINTR) || (errno == ENOMEM))
   73                 goto again;
   74             pr_err("%s: fork failed: errno=%d: (%s)\n",
   75                 args->name, errno, strerror(errno));
   76             return EXIT_NO_RESOURCE;
   77         } else if (pid > 0) {
   78             int status, ret;
   79 
   80             (void)setpgid(pid, g_pgrp);
   81             /* Parent, wait for child */
   82             ret = waitpid(pid, &status, 0);
   83             if (ret < 0) {
   84                 if (errno != EINTR)
   85                     pr_dbg("%s: waitpid(): errno=%d (%s)\n",
   86                         args->name, errno, strerror(errno));
   87                 (void)kill(pid, SIGTERM);
   88                 (void)kill(pid, SIGKILL);
   89                 (void)waitpid(pid, &status, 0);
   90             } else if (WIFSIGNALED(status)) {
   91                 /* If we got killed by OOM killer, re-start */
   92                 if (WTERMSIG(status) == SIGKILL) {
   93                     if (g_opt_flags & OPT_FLAGS_OOMABLE) {
   94                         log_system_mem_info();
   95                         pr_dbg("%s: assuming killed by OOM "
   96                             "killer, bailing out "
   97                             "(instance %d)\n",
   98                             args->name, args->instance);
   99                         _exit(0);
  100                     } else {
  101                         log_system_mem_info();
  102                         pr_dbg("%s: assuming killed by OOM "
  103                             "killer, restarting again "
  104                             "(instance %d)\n",
  105                             args->name, args->instance);
  106                         goto again;
  107                     }
  108                 }
  109                 /* expected: child killed itself with SIGSEGV */
  110                 if (WTERMSIG(status) == SIGSEGV) {
  111                     inc_counter(args);
  112                     continue;
  113                 }
  114             }
  115         } else if (pid == 0) {
  116             uint32_t rnd;
  117             int ret;
  118             volatile uint8_t *vol_stack = stack;
  119 
  120             /* Child */
  121             mwc_reseed();
  122             rnd = mwc32() % 7;
  123 
  124             set_oom_adjustment(args->name, true);
  125             stress_process_dumpable(false);
  126 
  127             if (stress_sigaltstack(stack, stack_sz) < 0)
  128                 return EXIT_FAILURE;
  129 
  130             switch (rnd) {
  131 #if defined(HAVE_MPROTECT)
  132             case 1:
  133                 ret = mprotect(stack, stack_sz, PROT_NONE);
  134                 if (ret == 0)
  135                     break;
  136                 CASE_FALLTHROUGH;
  137             case 2:
  138                 ret = mprotect(stack, stack_sz, PROT_READ);
  139                 if (ret == 0)
  140                     break;
  141                 CASE_FALLTHROUGH;
  142             case 3:
  143                 ret = mprotect(stack, stack_sz, PROT_EXEC);
  144                 if (ret == 0)
  145                     break;
  146                 CASE_FALLTHROUGH;
  147 #endif
  148             case 4:
  149                 ret = stress_sigaltstack(NULL, SIGSTKSZ);
  150                 if (ret == 0)
  151                     break;
  152                 CASE_FALLTHROUGH;
  153             case 5:
  154                 ret = stress_sigaltstack(stress_segv_handler, SIGSTKSZ);
  155                 if (ret == 0)
  156                     break;
  157                 CASE_FALLTHROUGH;
  158             case 6:
  159                 vol_stack = NULL;
  160                 break;
  161             default:
  162             case 0:
  163                 (void)munmap(stack, stack_sz);
  164                 break;
  165             }
  166 
  167             /* trigger segfault */
  168             uint8_put(*vol_stack);
  169             *vol_stack = 0;
  170 
  171             /* No luck, well that's unexpected.. */
  172             _exit(EXIT_FAILURE);
  173         }
  174     } while (keep_stressing());
  175 
  176     return EXIT_SUCCESS;
  177 }
  178 
  179 stressor_info_t stress_bad_altstack_info = {
  180     .stressor = stress_bad_altstack,
  181     .class = CLASS_VM | CLASS_MEMORY | CLASS_OS
  182 };
  183 #else
  184 stressor_info_t stress_bad_altstack_info = {
  185     .stressor = stress_not_implemented,
  186     .class = CLASS_VM | CLASS_MEMORY | CLASS_OS
  187 };
  188 #endif