"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-chown.c" (15 Mar 2019, 5181 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-chown.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 /*
   28  *  do_fchown()
   29  *  set ownership different ways
   30  */
   31 static int do_fchown(
   32     const int fd,
   33     const bool cap_chown,
   34     const uid_t uid,
   35     const gid_t gid)
   36 {
   37     int ret, tmp;
   38 
   39     if (fchown(fd, uid, gid) < 0)
   40         return -errno;
   41     if (fchown(fd, -1, gid) < 0)
   42         return -errno;
   43     if (fchown(fd, uid, -1) < 0)
   44         return -errno;
   45     if (fchown(fd, -1, -1) < 0)
   46         return -errno;
   47 
   48     if (cap_chown)
   49         return 0;
   50     if (fchown(fd, 0, 0) == 0)
   51         goto restore;
   52     if (errno != EPERM)
   53         goto restore;
   54     if ((fchown(fd, -1, 0) == 0) && (errno != EPERM))
   55         goto restore;
   56     if (errno != EPERM)
   57         goto restore;
   58     if (fchown(fd, 0, -1) == 0)
   59         goto restore;
   60     if (errno != EPERM)
   61         goto restore;
   62 
   63     return 0;
   64 
   65 restore:
   66     tmp = errno;
   67     ret = fchown(fd, uid, gid);
   68     (void)ret;
   69 
   70     return -tmp;
   71 }
   72 
   73 /*
   74  *  do_chown()
   75  *  set ownership different ways
   76  */
   77 static int do_chown(
   78     int (*chown_func)(const char *pathname, uid_t owner, gid_t group),
   79     const char *filename,
   80     const bool cap_chown,
   81     const uid_t uid,
   82     const gid_t gid)
   83 {
   84     int ret, tmp;
   85 
   86     if (chown_func(filename, uid, gid) < 0)
   87         return -errno;
   88     if (chown_func(filename, -1, gid) < 0)
   89         return -errno;
   90     if (chown_func(filename, uid, -1) < 0)
   91         return -errno;
   92     if (chown_func(filename, -1, -1) < 0)
   93         return -errno;
   94 
   95     if (cap_chown)
   96         return 0;
   97     if (chown_func(filename, 0, 0) == 0)
   98         goto restore;
   99     if (errno != EPERM)
  100         goto restore;
  101     if ((chown_func(filename, -1, 0) == 0) && (errno != EPERM))
  102         goto restore;
  103     if (errno != EPERM)
  104         goto restore;
  105     if (chown_func(filename, 0, -1) == 0)
  106         goto restore;
  107     if (errno != EPERM)
  108         goto restore;
  109 
  110     return 0;
  111 
  112 restore:
  113     tmp = errno;
  114     ret = chown_func(filename, uid, gid);
  115     (void)ret;
  116 
  117     return -tmp;
  118 }
  119 
  120 /*
  121  *  stress_chown
  122  *  stress chown
  123  */
  124 static int stress_chown(const args_t *args)
  125 {
  126     const pid_t ppid = getppid();
  127     int fd = -1, rc = EXIT_FAILURE, retries = 0;
  128     char filename[PATH_MAX], dirname[PATH_MAX];
  129     const uid_t uid = getuid();
  130     const gid_t gid = getgid();
  131     bool cap_chown = false;
  132 
  133     if (geteuid() == 0)
  134         cap_chown = true;
  135 
  136     /*
  137      *  Allow for multiple workers to chown the *same* file
  138      */
  139     stress_temp_dir(dirname, sizeof(dirname), args->name, ppid, 0);
  140     if (mkdir(dirname, S_IRUSR | S_IRWXU) < 0) {
  141         if (errno != EEXIST) {
  142             rc = exit_status(errno);
  143             pr_fail_err("mkdir");
  144             return rc;
  145         }
  146     }
  147     (void)stress_temp_filename(filename, sizeof(filename),
  148         args->name, ppid, 0, 0);
  149 
  150     if (args->instance == 0) {
  151         if ((fd = creat(filename, S_IRUSR | S_IWUSR)) < 0) {
  152             rc = exit_status(errno);
  153             pr_fail_err("creat");
  154             goto tidy;
  155         }
  156     } else {
  157         /* Other instances must try to open the file */
  158         for (;;) {
  159             if ((fd = open(filename, O_RDWR, S_IRUSR | S_IWUSR)) > - 1)
  160                 break;
  161 
  162 #if defined(__NetBSD__)
  163             /* For some reason usleep blocks */
  164             (void)shim_sched_yield();
  165             retries = 0;
  166 #else
  167             (void)shim_usleep(100000);
  168 #endif
  169             /* Timed out, then give up */
  170             if (!g_keep_stressing_flag) {
  171                 rc = EXIT_SUCCESS;
  172                 goto tidy;
  173             }
  174             if (++retries >= 100) {
  175                 pr_err("%s: chown: file %s took %d "
  176                     "retries to open and gave up "
  177                     "(instance %" PRIu32 ")\n",
  178                     args->name, filename, retries, args->instance);
  179                 goto tidy;
  180             }
  181         }
  182     }
  183 
  184     do {
  185         int ret;
  186 
  187         ret = do_fchown(fd, cap_chown, uid, gid);
  188         if ((ret < 0) && (ret != -EPERM))
  189             pr_fail_err("fchown");
  190 
  191         ret = do_chown(chown, filename, cap_chown, uid, gid);
  192         if (ret < 0) {
  193             if (ret == -ENOENT || ret == -ENOTDIR) {
  194                 /*
  195                  * File was removed during test by
  196                  * another worker
  197                  */
  198                 rc = EXIT_SUCCESS;
  199                 goto tidy;
  200             }
  201             if (ret != -EPERM)
  202                 pr_fail_err("chown");
  203         }
  204         ret = do_chown(lchown, filename, cap_chown, uid, gid);
  205         if (ret < 0) {
  206             if (ret == -ENOENT || ret == -ENOTDIR) {
  207                 /*
  208                  * File was removed during test by
  209                  * another worker
  210                  */
  211                 rc = EXIT_SUCCESS;
  212                 goto tidy;
  213             }
  214             if (ret != -EPERM)
  215                 pr_fail_err("chown");
  216         }
  217         inc_counter(args);
  218     } while (keep_stressing());
  219 
  220     rc = EXIT_SUCCESS;
  221 tidy:
  222     if (fd >= 0)
  223         (void)close(fd);
  224     (void)unlink(filename);
  225     (void)rmdir(dirname);
  226 
  227     return rc;
  228 }
  229 
  230 stressor_info_t stress_chown_info = {
  231     .stressor = stress_chown,
  232     .class = CLASS_FILESYSTEM | CLASS_OS
  233 };