"Fossies" - the Fresh Open Source Software Archive

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

    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_CHROOT)
   28 
   29 typedef int (*stress_chroot_test_func)(const args_t *args);
   30 
   31 static char temppath[PATH_MAX];
   32 static char longpath[PATH_MAX + 32];
   33 static char badpath[PATH_MAX];
   34 static char filename[PATH_MAX];
   35 
   36 /*
   37  *  stress_chroot_supported()
   38  *      check if we can run this as root
   39  */
   40 static int stress_chroot_supported(void)
   41 {
   42     if (geteuid() != 0) {
   43         pr_inf("chroot stressor will be skipped, "
   44             "need to be running as root for this stressor\n");
   45         return -1;
   46     }
   47     return 0;
   48 }
   49 
   50 /*
   51  *  do_chroot()
   52  *  helper to do a chroot followed by chdir
   53  */
   54 static void do_chroot(
   55     const char *path,
   56     int *ret1, int *ret2,
   57     int *errno1, int *errno2)
   58 {
   59     *ret1 = chroot(path);
   60     *errno1 = errno;
   61 
   62     /*
   63      * we must do chdir immediately after a chroot
   64      * otherwise we have a security risk. Also
   65      * CoverityScan will pick this up as an error.
   66      */
   67     *ret2 = chdir("/");
   68     *errno2 = errno;
   69 }
   70 
   71 static int stress_chroot_test1(const args_t *args)
   72 {
   73     char cwd[PATH_MAX];
   74     int ret1, ret2, errno1, errno2;
   75 
   76     do_chroot(temppath, &ret1, &ret2, &errno1, &errno2);
   77 
   78     /*
   79      * We check for error, ENOENT can happen on termination
   80      * so ignore this error
   81      */
   82     if ((ret1 < 0) && (errno != ENOENT)) {
   83         pr_fail("%s: chroot(\"%s\"), errno=%d (%s)\n",
   84             args->name, temppath, errno1, strerror(errno1));
   85         return EXIT_FAILURE;
   86     }
   87     if (ret2 < 0) {
   88         pr_fail_errno("chdir(\"/\")\n", errno2);
   89         return EXIT_FAILURE;
   90     }
   91     if (!getcwd(cwd, sizeof(cwd))) {
   92         pr_fail_err("getcwd");
   93         return EXIT_FAILURE;
   94     }
   95     if (strcmp(cwd, "/")) {
   96         pr_fail("%s: cwd in chroot is \"%s\" and not \"/\"\n", args->name, cwd);
   97         return EXIT_FAILURE;
   98     }
   99     return EXIT_SUCCESS;
  100 }
  101 
  102 static int stress_chroot_test2(const args_t *args)
  103 {
  104     int ret1, ret2, errno1, errno2;
  105 
  106     do_chroot((void *)1, &ret1, &ret2, &errno1, &errno2);
  107 
  108     if ((ret1 >= 0) || (errno1 != EFAULT))  {
  109         pr_fail("%s: chroot(\"%s\"), expected EFAULT"
  110             ", got instead errno=%d (%s)\n",
  111             args->name, temppath, errno1, strerror(errno1));
  112         return EXIT_FAILURE;
  113     }
  114     if (ret2 < 0) {
  115         pr_fail_errno("chdir(\"/\")\n", errno2);
  116         return EXIT_FAILURE;
  117     }
  118     return EXIT_SUCCESS;
  119 }
  120 
  121 static int stress_chroot_test3(const args_t *args)
  122 {
  123     int ret1, ret2, errno1, errno2;
  124 
  125     do_chroot(longpath, &ret1, &ret2, &errno1, &errno2);
  126 
  127 #if defined(__HAIKU__)
  128     if ((ret1 >= 0) || (errno1 != EINVAL))  {
  129 #else
  130     if ((ret1 >= 0) || (errno1 != ENAMETOOLONG))  {
  131 #endif
  132         pr_fail("%s: chroot(\"<very long path>\"), expected "
  133             "ENAMETOOLONG, got instead errno=%d (%s)\n",
  134             args->name, errno1, strerror(errno1));
  135         return EXIT_FAILURE;
  136     }
  137     if (ret2 < 0) {
  138         pr_fail_errno("chdir(\"/\")\n", errno2);
  139         return EXIT_FAILURE;
  140     }
  141     return EXIT_SUCCESS;
  142 }
  143 
  144 static int stress_chroot_test4(const args_t *args)
  145 {
  146     int ret1, ret2, errno1, errno2;
  147 
  148     do_chroot(badpath, &ret1, &ret2, &errno1, &errno2);
  149 
  150     if ((ret1 >= 0) || (errno1 != ENOENT))  {
  151         pr_fail("%s: chroot(\"%s\"), expected ENOENT"
  152             ", got instead errno=%d (%s)\n",
  153             args->name, badpath, errno1, strerror(errno1));
  154         return EXIT_SUCCESS;
  155     }
  156     if (ret2 < 0) {
  157         pr_fail_errno("chdir(\"/\")\n", errno2);
  158         return EXIT_FAILURE;
  159     }
  160     return EXIT_SUCCESS;
  161 }
  162 
  163 static int stress_chroot_test5(const args_t *args)
  164 {
  165     int ret1, ret2, errno1, errno2;
  166 
  167     do_chroot(filename, &ret1, &ret2, &errno1, &errno2);
  168 
  169     /*
  170      * We check for error, ENOENT can happen on termination
  171      * so ignore this error
  172      */
  173     if ((ret1 >= 0) || ((errno1 != ENOTDIR) && (errno1 != ENOENT)))  {
  174         pr_fail("%s: chroot(\"%s\"), expected ENOTDIR"
  175             ", got instead errno=%d (%s)\n",
  176             args->name, filename, errno1, strerror(errno1));
  177         return EXIT_SUCCESS;
  178     }
  179     if (ret2 < 0) {
  180         pr_fail_errno("chdir(\"/\")\n", errno2);
  181         return EXIT_FAILURE;
  182     }
  183     return EXIT_SUCCESS;
  184 }
  185 
  186 static const stress_chroot_test_func test_chroot_test_funcs[] =
  187 {
  188     stress_chroot_test1,
  189     stress_chroot_test2,
  190     stress_chroot_test3,
  191     stress_chroot_test4,
  192     stress_chroot_test5
  193 };
  194 
  195 /*
  196  *  stress_chroot()
  197  *  stress chroot system call
  198  */
  199 static int stress_chroot(const args_t *args)
  200 {
  201     size_t i = 0;
  202     int fd, ret = EXIT_FAILURE;
  203 
  204     stress_strnrnd(longpath, sizeof(longpath));
  205     (void)stress_temp_dir(badpath, sizeof(badpath), "badpath", args->pid, 0xbad);
  206     (void)stress_temp_dir_args(args, temppath, sizeof(temppath));
  207     (void)stress_temp_filename_args(args, filename, sizeof(filename), mwc32());
  208     if (mkdir(temppath, S_IRWXU) < 0) {
  209         pr_fail_err("mkdir");
  210         goto tidy_ret;
  211     }
  212     if ((fd = creat(filename, S_IRUSR | S_IWUSR)) < 0) {
  213         pr_fail_err("creat");
  214         goto tidy_dir;
  215     }
  216     (void)close(fd);
  217 
  218     do {
  219         pid_t pid;
  220 retry:
  221         if (!keep_stressing())
  222             break;
  223 
  224         pid = fork();
  225         if (pid < 0) {
  226             goto retry;
  227         } else if (pid == 0) {
  228             (void)setpgid(0, g_pgrp);
  229             set_oom_adjustment(args->name, true);
  230 
  231             ret = test_chroot_test_funcs[i](args);
  232 
  233             /* Children */
  234             _exit(ret);
  235         } else {
  236             /* Parent */
  237             int status, waitret;
  238 
  239             waitret = waitpid(pid, &status, 0);
  240             if (waitret < 0) {
  241                 if (errno == EINTR)
  242                     break;
  243                 pr_fail_err("waitpid waiting on chroot child");
  244                 goto tidy_all;
  245             }
  246             if (WEXITSTATUS(status) != EXIT_SUCCESS)
  247                 goto tidy_all;
  248 
  249             inc_counter(args);
  250         }
  251         i++;
  252         i %= SIZEOF_ARRAY(test_chroot_test_funcs);
  253     } while (keep_stressing());
  254 
  255     ret = EXIT_SUCCESS;
  256 tidy_all:
  257     (void)unlink(filename);
  258 tidy_dir:
  259     (void)rmdir(temppath);
  260 tidy_ret:
  261     return ret;
  262 }
  263 
  264 stressor_info_t stress_chroot_info = {
  265     .stressor = stress_chroot,
  266     .supported = stress_chroot_supported,
  267     .class = CLASS_OS
  268 };
  269 #else
  270 
  271 /*
  272  *  stress_chroot_supported()
  273  *      check if we can run this as root
  274  */
  275 static int stress_chroot_supported(void)
  276 {
  277     pr_inf("chroot stressor is not supported on this system\n");
  278     return -1;
  279 }
  280 
  281 stressor_info_t stress_chroot_info = {
  282     .stressor = stress_not_implemented,
  283     .supported = stress_chroot_supported,
  284     .class = CLASS_OS
  285 };
  286 #endif