"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-sysbadaddr.c" (15 Mar 2019, 12894 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-sysbadaddr.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.50_vs_0.09.51.

    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 typedef void *(*bad_addr_t)(const args_t *args);
   28 typedef int (*bad_syscall_t)(void *addr);
   29 
   30 static void *ro_page;
   31 static void *rw_page;
   32 
   33 static const int sigs[] = {
   34 #if defined(SIGILL)
   35     SIGILL,
   36 #endif
   37 #if defined(SIGTRAP)
   38     SIGTRAP,
   39 #endif
   40 #if defined(SIGFPE)
   41     SIGFPE,
   42 #endif
   43 #if defined(SIGBUS)
   44     SIGBUS,
   45 #endif
   46 #if defined(SIGSEGV)
   47     SIGSEGV,
   48 #endif
   49 #if defined(SIGIOT)
   50     SIGIOT,
   51 #endif
   52 #if defined(SIGEMT)
   53     SIGEMT,
   54 #endif
   55 #if defined(SIGALRM)
   56     SIGALRM,
   57 #endif
   58 #if defined(SIGINT)
   59     SIGINT,
   60 #endif
   61 #if defined(SIGHUP)
   62     SIGHUP
   63 #endif
   64 };
   65 
   66 /*
   67  *  limit_procs()
   68  *  try to limit child resources
   69  */
   70 static void limit_procs(const int procs)
   71 {
   72 #if defined(RLIMIT_CPU) || defined(RLIMIT_NPROC)
   73     struct rlimit lim;
   74 #endif
   75 
   76 #if defined(RLIMIT_CPU)
   77     lim.rlim_cur = 1;
   78     lim.rlim_max = 1;
   79     (void)setrlimit(RLIMIT_CPU, &lim);
   80 #endif
   81 #if defined(RLIMIT_NPROC)
   82     lim.rlim_cur = procs;
   83     lim.rlim_max = procs;
   84     (void)setrlimit(RLIMIT_NPROC, &lim);
   85 #else
   86     (void)procs;
   87 #endif
   88 }
   89 
   90 static void MLOCKED_TEXT stress_badhandler(int signum)
   91 {
   92     (void)signum;
   93 
   94     _exit(1);
   95 }
   96 
   97 static void *unaligned_addr(const args_t *args)
   98 {
   99     static uint64_t data[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
  100     uint8_t *ptr = (uint8_t *)data;
  101 
  102     (void)args;
  103 
  104     return ptr + 1;
  105 }
  106 
  107 static void *readonly_addr(const args_t *args)
  108 {
  109     (void)args;
  110 
  111     return ro_page;
  112 }
  113 
  114 static void *null_addr(const args_t *args)
  115 {
  116     (void)args;
  117 
  118     return NULL;
  119 }
  120 
  121 static void *text_addr(const args_t *args)
  122 {
  123     (void)args;
  124 
  125     return (void *)&write;
  126 }
  127 
  128 static void *bad_end_addr(const args_t *args)
  129 {
  130     return rw_page + args->page_size - 1;
  131 }
  132 
  133 static void *bad_max_addr(const args_t *args)
  134 {
  135     (void)args;
  136 
  137     return (void *)~(uintptr_t)0;
  138 }
  139 
  140 static void *unmapped_addr(const args_t *args)
  141 {
  142     return rw_page + args->page_size;
  143 }
  144 
  145 static bad_addr_t bad_addrs[] = {
  146     unaligned_addr,
  147     readonly_addr,
  148     null_addr,
  149     text_addr,
  150     bad_end_addr,
  151     bad_max_addr,
  152     unmapped_addr,
  153 };
  154 
  155 static int bad_access(void *addr)
  156 {
  157     return access(addr, R_OK);
  158 }
  159 
  160 #if defined(HAVE_CLOCK_GETTIME) &&  \
  161     defined(CLOCK_REALTIME)
  162 static int bad_clock_gettime(void *addr)
  163 {
  164     return clock_gettime(CLOCK_REALTIME, addr);
  165 }
  166 #endif
  167 
  168 static int bad_execve(void *addr)
  169 {
  170     return execve(addr, addr, addr);
  171 }
  172 
  173 
  174 static int bad_getcwd(void *addr)
  175 {
  176     if (getcwd(addr, 1024) == NULL)
  177         return -1;
  178 
  179     return 0;
  180 }
  181 
  182 static int bad_get_mempolicy(void *addr)
  183 {
  184     return shim_get_mempolicy(addr, addr, 1, (unsigned long)addr, 0);
  185 }
  186 
  187 static int bad_getrandom(void *addr)
  188 {
  189     return shim_getrandom(addr, 1024, 0);
  190 }
  191 
  192 #if defined(HAVE_GETRESGID)
  193 static int bad_getresgid(void *addr)
  194 {
  195     return getresgid(addr, addr, addr);
  196 }
  197 #endif
  198 
  199 #if defined(HAVE_GETRESUID)
  200 static int bad_getresuid(void *addr)
  201 {
  202     return getresuid(addr, addr, addr);
  203 }
  204 #endif
  205 
  206 static int bad_getrlimit(void *addr)
  207 {
  208     return getrlimit(RLIMIT_CPU, addr);
  209 }
  210 
  211 static int bad_getrusage(void *addr)
  212 {
  213     return getrusage(RUSAGE_SELF, addr);
  214 }
  215 
  216 static int bad_gettimeofday(void *addr)
  217 {
  218     struct timezone *tz = ((struct timezone *)addr) + 1;
  219     return gettimeofday(addr, tz);
  220 }
  221 
  222 #if defined(HAVE_GETXATTR) &&   \
  223     (defined(HAVE_SYS_XATTR_H) || defined(HAVE_ATTR_XATTR_H))
  224 static int bad_getxattr(void *addr)
  225 {
  226     return shim_getxattr(addr, addr, addr, 32);
  227 }
  228 #endif
  229 
  230 #if defined(TCGETS)
  231 static int bad_ioctl(void *addr)
  232 {
  233     return ioctl(0, TCGETS, addr);
  234 }
  235 #endif
  236 
  237 static int bad_migrate_pages(void *addr)
  238 {
  239     return shim_migrate_pages(getpid(), 1, addr, addr);
  240 }
  241 
  242 static int bad_mincore(void *addr)
  243 {
  244     return shim_mincore(ro_page, 1, addr);
  245 }
  246 
  247 static int bad_move_pages(void *addr)
  248 {
  249     return shim_move_pages(getpid(), 1, addr, addr, addr, 0);
  250 }
  251 
  252 #if defined(HAVE_NANOSLEEP)
  253 static int bad_nanosleep(void *addr)
  254 {
  255     return nanosleep(addr, addr);
  256 }
  257 #endif
  258 
  259 static int bad_open(void *addr)
  260 {
  261     int fd;
  262 
  263     fd = open(addr, O_RDONLY);
  264     if (fd != -1)
  265         (void)close(fd);
  266 
  267     return fd;
  268 }
  269 
  270 static int bad_pipe(void *addr)
  271 {
  272     return pipe(addr);
  273 }
  274 
  275 #if defined(HAVE_PTRACE) &&     \
  276     defined(PTRACE_GETREGS)
  277 static int bad_ptrace(void *addr)
  278 {
  279     return ptrace(PTRACE_GETREGS, getpid(), addr, addr);
  280 }
  281 #endif
  282 
  283 #if defined(HAVE_POLL_H)
  284 static int bad_poll(void *addr)
  285 {
  286     return poll(addr, 16, 1);
  287 }
  288 #endif
  289 
  290 static int bad_read(void *addr)
  291 {
  292     int fd, ret = 0;
  293 
  294     fd = open("/dev/zero", O_RDONLY);
  295     if (fd > -1) {
  296         ret = read(fd, addr, 1024);
  297         (void)close(fd);
  298     }
  299     return ret;
  300 }
  301 
  302 static int bad_readv(void *addr)
  303 {
  304     int fd, ret = 0;
  305 
  306     fd = open("/dev/zero", O_RDONLY);
  307     if (fd > -1) {
  308         ret = readv(fd, addr, 32);
  309         (void)close(fd);
  310     }
  311     return ret;
  312 }
  313 
  314 static int bad_select(void *addr)
  315 {
  316     int fd, ret = 0;
  317     fd_set *readfds = addr;
  318     fd_set *writefds = readfds + 1;
  319     fd_set *exceptfds = writefds + 1;
  320 
  321     fd = open("/dev/zero", O_RDONLY);
  322     if (fd > -1) {
  323         ret = select(fd, readfds, writefds, exceptfds, addr);
  324         (void)close(fd);
  325     }
  326     return ret;
  327 }
  328 
  329 static int bad_stat(void *addr)
  330 {
  331     return stat(".", addr);
  332 }
  333 
  334 #if defined(HAVE_STATFS)
  335 static int bad_statfs(void *addr)
  336 {
  337     return statfs(".", addr);
  338 }
  339 #endif
  340 
  341 #if defined(HAVE_SYS_SYSINFO_H) &&  \
  342     defined(HAVE_SYSINFO)
  343 static int bad_sysinfo(void *addr)
  344 {
  345     return sysinfo(addr);
  346 }
  347 #endif
  348 
  349 static int bad_time(void *addr)
  350 {
  351     return time(addr);
  352 }
  353 
  354 #if defined(HAVE_LIB_RT) && \
  355     defined(HAVE_TIMER_CREATE)
  356 static int bad_timer_create(void *addr)
  357 {
  358     timer_t *timerid = (timer_t *)addr;
  359 
  360     timerid++;
  361     return timer_create(CLOCK_MONOTONIC, addr, timerid);
  362 }
  363 #endif
  364 
  365 static int bad_times(void *addr)
  366 {
  367     return times(addr);
  368 }
  369 
  370 #if defined(HAVE_USTAT)
  371 static int bad_ustat(void *addr)
  372 {
  373     dev_t dev = { 0 };
  374 
  375     return ustat(dev, addr);
  376 }
  377 #endif
  378 
  379 #if defined(HAVE_UTIME_H)
  380 static int bad_utime(void *addr)
  381 {
  382     return utime(addr, addr);
  383 }
  384 #endif
  385 
  386 static int bad_wait(void *addr)
  387 {
  388     return wait(addr);
  389 }
  390 
  391 static int bad_waitpid(void *addr)
  392 {
  393     return waitpid(getpid(), addr, 0);
  394 }
  395 
  396 #if defined(HAVE_WAITID)
  397 static int bad_waitid(void *addr)
  398 {
  399     return waitid(P_PID, getpid(), addr, 0);
  400 }
  401 #endif
  402 
  403 static int bad_write(void *addr)
  404 {
  405     int fd, ret = 0;
  406 
  407     fd = open("/dev/null", O_WRONLY);
  408     if (fd > -1) {
  409         ret = write(fd, addr, 1024);
  410         (void)close(fd);
  411     }
  412     return ret;
  413 }
  414 
  415 static int bad_writev(void *addr)
  416 {
  417     int fd, ret = 0;
  418 
  419     fd = open("/dev/zero", O_RDONLY);
  420     if (fd > -1) {
  421         ret = writev(fd, addr, 32);
  422         (void)close(fd);
  423     }
  424     return ret;
  425 }
  426 
  427 static bad_syscall_t bad_syscalls[] = {
  428     bad_access,
  429 #if defined(HAVE_CLOCK_GETTIME) &&  \
  430     defined(CLOCK_REALTIME)
  431     bad_clock_gettime,
  432 #endif
  433     bad_execve,
  434     bad_getcwd,
  435     bad_get_mempolicy,
  436     bad_getrandom,
  437 #if defined(HAVE_GETRESGID)
  438     bad_getresgid,
  439 #endif
  440 #if defined(HAVE_GETRESUID)
  441     bad_getresuid,
  442 #endif
  443     bad_getrlimit,
  444     bad_getrusage,
  445     bad_gettimeofday,
  446 #if defined(HAVE_GETXATTR) &&   \
  447     (defined(HAVE_SYS_XATTR_H) || defined(HAVE_ATTR_XATTR_H))
  448     bad_getxattr,
  449 #endif
  450 #if defined(TCGETS)
  451     bad_ioctl,
  452 #endif
  453     bad_migrate_pages,
  454     bad_mincore,
  455     bad_move_pages,
  456 #if defined(HAVE_NANOSLEEP)
  457     bad_nanosleep,
  458 #endif
  459     bad_open,
  460     bad_pipe,
  461 #if defined(HAVE_POLL_H)
  462     bad_poll,
  463 #endif
  464 #if defined(HAVE_PTRACE) && \
  465     defined(PTRACE_GETREGS)
  466     bad_ptrace,
  467 #endif
  468     bad_read,
  469     bad_readv,
  470     bad_select,
  471     bad_stat,
  472 #if defined(HAVE_STATFS)
  473     bad_statfs,
  474 #endif
  475 #if defined(HAVE_SYS_SYSINFO_H) &&  \
  476     defined(HAVE_SYSINFO)
  477     bad_sysinfo,
  478 #endif
  479     bad_time,
  480 #if defined(HAVE_LIB_RT) && \
  481     defined(HAVE_TIMER_CREATE)
  482     bad_timer_create,
  483 #endif
  484     bad_times,
  485 #if defined(HAVE_USTAT)
  486     bad_ustat,
  487 #endif
  488 #if defined(HAVE_UTIME_H)
  489     bad_utime,
  490 #endif
  491     bad_wait,
  492     bad_waitpid,
  493 #if defined(HAVE_WAITID)
  494     bad_waitid,
  495 #endif
  496     bad_write,
  497     bad_writev,
  498 };
  499 
  500 
  501 /*
  502  *  Call a system call in a child context so we don't clobber
  503  *  the parent
  504  */
  505 static inline int stress_do_syscall(
  506     const args_t *args,
  507     bad_syscall_t bad_syscall,
  508     void *addr)
  509 {
  510     pid_t pid;
  511     int rc = 0;
  512 
  513     if (!keep_stressing())
  514         return 0;
  515     pid = fork();
  516     if (pid < 0) {
  517         _exit(EXIT_NO_RESOURCE);
  518     } else if (pid == 0) {
  519         struct itimerval it;
  520         size_t i;
  521         int ret;
  522 
  523         /* Try to limit child from spawning */
  524         limit_procs(2);
  525 
  526         /* We don't want bad ops clobbering this region */
  527         stress_unmap_shared();
  528 
  529         /* Drop all capabilities */
  530         if (stress_drop_capabilities(args->name) < 0) {
  531             _exit(EXIT_NO_RESOURCE);
  532         }
  533         for (i = 0; i < SIZEOF_ARRAY(sigs); i++) {
  534             if (stress_sighandler(args->name, sigs[i], stress_badhandler, NULL) < 0)
  535                 _exit(EXIT_FAILURE);
  536         }
  537 
  538         (void)setpgid(0, g_pgrp);
  539         stress_parent_died_alarm();
  540 
  541         /*
  542          * Force abort if we take too long
  543          */
  544         it.it_interval.tv_sec = 0;
  545         it.it_interval.tv_usec = 100000;
  546         it.it_value.tv_sec = 0;
  547         it.it_value.tv_usec = 100000;
  548         if (setitimer(ITIMER_REAL, &it, NULL) < 0) {
  549             pr_fail_dbg("setitimer");
  550             _exit(EXIT_NO_RESOURCE);
  551         }
  552 
  553         ret = bad_syscall(addr);
  554         if (ret < 0)
  555             ret = errno;
  556         _exit(ret);
  557     } else {
  558         int ret, status;
  559 
  560         ret = waitpid(pid, &status, 0);
  561         if (ret < 0) {
  562             if (errno != EINTR)
  563                 pr_dbg("%s: waitpid(): errno=%d (%s)\n",
  564                     args->name, errno, strerror(errno));
  565             (void)kill(pid, SIGKILL);
  566             (void)waitpid(pid, &status, 0);
  567 
  568         }
  569         rc = WEXITSTATUS(status);
  570 
  571         inc_counter(args);
  572     }
  573     return rc;
  574 }
  575 
  576 /*
  577  *  stress_sysbadaddr
  578  *  stress system calls with bad addresses
  579  */
  580 static int stress_sysbadaddr(const args_t *args)
  581 {
  582     pid_t pid;
  583     size_t page_size = args->page_size;
  584 
  585     ro_page = mmap(NULL, page_size, PROT_READ,
  586         MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  587     if (ro_page == MAP_FAILED) {
  588         pr_inf("%s: cannot mmap anonymous read-only page: "
  589                "errno=%d (%s)\n", args->name,errno, strerror(errno));
  590         return EXIT_NO_RESOURCE;
  591     }
  592     rw_page = mmap(NULL, page_size << 1, PROT_READ,
  593         MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  594     if (rw_page == MAP_FAILED) {
  595         (void)munmap(ro_page, page_size);
  596         pr_inf("%s: cannot mmap anonymous read-write page: "
  597                "errno=%d (%s)\n", args->name,errno, strerror(errno));
  598         return EXIT_NO_RESOURCE;
  599     }
  600     /*
  601      * Unmap last page, so we know we have an unmapped
  602      * page following the r/w page
  603      */
  604     (void)munmap(rw_page + page_size, page_size);
  605 
  606 again:
  607     if (!keep_stressing())
  608         return EXIT_SUCCESS;
  609     pid = fork();
  610     if (pid < 0) {
  611         if (errno == EAGAIN)
  612             goto again;
  613         pr_err("%s: fork failed: errno=%d: (%s)\n",
  614             args->name, errno, strerror(errno));
  615     } else if (pid > 0) {
  616         int status, ret;
  617 
  618         (void)setpgid(pid, g_pgrp);
  619         /* Parent, wait for child */
  620         ret = waitpid(pid, &status, 0);
  621         if (ret < 0) {
  622             if (errno != EINTR)
  623                 pr_dbg("%s: waitpid(): errno=%d (%s)\n",
  624                     args->name, errno, strerror(errno));
  625             (void)kill(pid, SIGTERM);
  626             (void)kill(pid, SIGKILL);
  627             (void)waitpid(pid, &status, 0);
  628         } else if (WIFSIGNALED(status)) {
  629             pr_dbg("%s: child died: %s (instance %d)\n",
  630                 args->name, stress_strsignal(WTERMSIG(status)),
  631                 args->instance);
  632             /* If we got killed by OOM killer, re-start */
  633             if (WTERMSIG(status) == SIGKILL) {
  634                 if (g_opt_flags & OPT_FLAGS_OOMABLE) {
  635                     log_system_mem_info();
  636                     pr_dbg("%s: assuming killed by OOM "
  637                         "killer, bailing out "
  638                         "(instance %d)\n",
  639                         args->name, args->instance);
  640                     _exit(0);
  641                 } else {
  642                     log_system_mem_info();
  643                     pr_dbg("%s: assuming killed by OOM "
  644                         "killer, restarting again "
  645                         "(instance %d)\n",
  646                         args->name, args->instance);
  647                     goto again;
  648                 }
  649             }
  650         }
  651     } else if (pid == 0) {
  652         /* Child, wrapped to catch OOMs */
  653         if (!keep_stressing())
  654             _exit(0);
  655 
  656         (void)setpgid(0, g_pgrp);
  657         stress_parent_died_alarm();
  658 
  659         /* Make sure this is killable by OOM killer */
  660         set_oom_adjustment(args->name, true);
  661 
  662         do {
  663             size_t i;
  664 
  665             for (i = 0; i < SIZEOF_ARRAY(bad_syscalls); i++) {
  666                 size_t j;
  667 
  668                 for (j = 0; j < SIZEOF_ARRAY(bad_addrs); j++) {
  669                     int ret;
  670                     void *addr = bad_addrs[j](args);
  671 
  672                     ret = stress_do_syscall(args, bad_syscalls[i], addr);
  673                     (void)ret;
  674                 }
  675             }
  676         } while (keep_stressing());
  677         _exit(EXIT_SUCCESS);
  678     }
  679 
  680     (void)munmap(rw_page, page_size);
  681     (void)munmap(ro_page, page_size);
  682 
  683     return EXIT_SUCCESS;
  684 }
  685 
  686 stressor_info_t stress_sysbadaddr_info = {
  687     .stressor = stress_sysbadaddr,
  688     .class = CLASS_OS
  689 };