BVB Source Codes

rkt Show enterexec.c Source code

Return Download rkt: download enterexec.c Source code - Download rkt Source code - Type:.c
  1. // Copyright 2014 The rkt Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. //     http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14.  
  15. #define _GNU_SOURCE
  16. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <grp.h>
  19. #include <inttypes.h>
  20. #include <limits.h>
  21. #include <stdint.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <sys/mman.h>
  26. #include <sys/stat.h>
  27. #include <sys/types.h>
  28. #include <unistd.h>
  29.  
  30. #include "diagnostic-util.h"
  31.  
  32. /* Create keep_env file from keep_env, if they're present in
  33.  * current environment and file doesn't exist */
  34. void initialize_keep_env(const char *keep_env_file, const char **keep_env)
  35. {
  36.         FILE            *f;
  37.         const char      **p;
  38.         char            *v;
  39.         char            nul = '\0';
  40.  
  41.         if (!access(keep_env_file, F_OK)) return;
  42.         pexit_if((f = fopen(keep_env_file, "a")) == NULL,
  43.                 "Unable to fopen \"%s\"", keep_env_file);
  44.  
  45.         p = keep_env;
  46.         while (*p) {
  47.                 v = getenv(*p);
  48.                 if (v) {
  49.                         pexit_if(fprintf(f, "%s=%s%c", *p, v, nul) != (strlen(*p) + strlen(v) + 2),
  50.                                 "Unable to write to \"%s\"", keep_env_file);
  51.                 }
  52.                 p++;
  53.         }
  54.  
  55.         pexit_if(fclose(f) == EOF,
  56.                 "Unable to fclose \"%s\"", keep_env_file);
  57. }
  58.  
  59. /* Try to set current env from keep_env and env file. */
  60. static void set_env(const char *env_file)
  61. {
  62.         FILE            *f;
  63.         char            *line = NULL;
  64.         size_t          len = 0;
  65.         ssize_t         read;
  66.         char            *v, *nl;
  67.  
  68.         pexit_if((f = fopen(env_file, "r")) == NULL,
  69.              "Unable to fopen \"%s\"", env_file);
  70.         while ((read = getline(&line, &len, f)) != -1) {
  71.                 pexit_if((v = strchr(line, '=')) == NULL,
  72.                                 "Malformed environment entry: \"%s\"", line);
  73.                 *v = '\0';
  74.                 v++;
  75.                 /* remove new line character */
  76.                 if ((nl = strchr(v, '\n')) != NULL)
  77.                         *nl = '\0';
  78.                 pexit_if(setenv(line, v, 1) == -1,
  79.                                  "Unable to set env variable: \"%s\"=\"%s\"", line, v);
  80.         }
  81.         free(line);
  82.         pexit_if(fclose(f) == EOF,
  83.                          "Unable to fclose \"%s\"", env_file);
  84. }
  85.  
  86. /* Read environment from env and keep_env files make it our own, keeping the env variables in
  87.  * if they're present in the current environment.
  88.  * The environment files must exist, may be empty, and are expected to be of the format:
  89.  * key=value\nkey=value\n...
  90.  */
  91. static void load_env(const char *env_file, const char *keep_env_file, int entering)
  92. {
  93.         char *term = getenv("TERM"); /* useful to keep during entering. */
  94.         pexit_if(clearenv() != 0,
  95.                 "Unable to clear environment");
  96.  
  97.         set_env(env_file);
  98.         set_env(keep_env_file);
  99.         if (entering) {
  100.                 // enter is typically interactive; ensure we always have a sane enough term
  101.                 // variable.
  102.                 if (term == NULL) {
  103.                         setenv("TERM", "vt100", 1);
  104.                 } else {
  105.                         setenv("TERM", term, 1);
  106.                 }
  107.         }
  108. }
  109.  
  110. /* Parse a comma-separated list of numeric gids from str, returns an malloc'd
  111.  * array of gids in *gids_p with the number of elements in *n_gids_p.
  112.  */
  113. static void parse_gids(const char *str, size_t *n_gids_p, gid_t **gids_p)
  114. {
  115.         char    c = ',', last_c;
  116.         int     i, n_gids = 0, done = 0;
  117.         gid_t   gid = 0;
  118.         gid_t   *gids = NULL;
  119.  
  120.         for(i = 0; !done; i++) {
  121.                 last_c = c;
  122.                 switch(c = str[i]) {
  123.                 case '0' ... '9':
  124.                         gid *= 10;
  125.                         gid += c - '0';
  126.                         break;
  127.  
  128.                 case '\0':
  129.                         done = 1;
  130.                         /* fallthrough */
  131.                 case ',':
  132.                         exit_if(last_c == ',',
  133.                                 "Gids contains an empty gid: \"%s\"", str);
  134.                         pexit_if((gids = realloc(gids, sizeof(*gids) * (n_gids + 1))) == NULL,
  135.                                 "Unable to allocate gids: \"%s\"", str);
  136.                         gids[n_gids++] = gid;
  137.                         gid = 0;
  138.                         break;
  139.  
  140.                 default:
  141.                         exit_if(1,
  142.                                 "Gids contains invalid input (%c): \"%s\"",
  143.                                 c, str);
  144.                 }
  145.         }
  146.  
  147.         exit_if(!n_gids, "At least one gid is required, got: \"%s\"", str);
  148.  
  149.         *gids_p = gids;
  150.         *n_gids_p = n_gids;
  151. }
  152.  
  153. int main(int argc, char *argv[])
  154. {
  155.         int entering = 0;
  156.  
  157.         /* '-e' optional flag passed only during 'entering' phase from stage1.
  158.          */
  159.         int c;
  160.         while ((c = getopt(argc, argv, "e")) != -1)
  161.                 switch (c) {
  162.                         case 'e':
  163.                                 entering = 1;
  164.                                 break;
  165.                 }
  166.  
  167.         /* We need to keep these env variables since systemd uses them for socket
  168.          * activation
  169.          */
  170.         static const char *keep_env[] = {
  171.                 "LISTEN_FDS",
  172.                 "LISTEN_PID",
  173.                 NULL
  174.         };
  175.  
  176.         const char *keep_env_file = "/rkt/env/keep_env";
  177.         const char      *root, *cwd, *env_file, *uid_str, *gid_str, *exe;
  178.  
  179.         char            **args;
  180.         uid_t           uid;
  181.         gid_t           *gids;
  182.         size_t          n_gids;
  183.  
  184.         exit_if(argc < 7,
  185.                 "Usage: %s /path/to/root /work/directory /env/file uid gid[,gid...] [-e] /to/exec [args ...]", argv[0]);
  186.  
  187.         root = argv[optind];
  188.         cwd = argv[optind+1];
  189.         env_file = argv[optind+2];
  190.         uid_str = argv[optind+3];
  191.         uid = atoi(uid_str);
  192.         gid_str = argv[optind+4];
  193.         args = &argv[optind+5];
  194.         exe = args[0];
  195.  
  196.         parse_gids(gid_str, &n_gids, &gids);
  197.  
  198.         initialize_keep_env(keep_env_file, keep_env);
  199.         load_env(env_file, keep_env_file, entering);
  200.  
  201.         pexit_if(chroot(root) == -1, "Chroot \"%s\" failed", root);
  202.         pexit_if(chdir(cwd) == -1, "Chdir \"%s\" failed", cwd);
  203.         pexit_if(gids[0] > 0 && setresgid(gids[0], gids[0], gids[0]) == -1,
  204.                 "Setresgid \"%s\" failed", gid_str);
  205.         pexit_if(n_gids > 1 && setgroups(n_gids - 1, &gids[1]) == -1,
  206.                 "Setgroups \"%s\" failed", gid_str);
  207.         pexit_if(uid > 0 && setresuid(uid, uid, uid) == -1,
  208.                 "Setresuid \"%s\" failed", uid_str);
  209.  
  210.         /* XXX(vc): note that since execvp() is happening post-chroot, the
  211.          * app's environment settings correctly affect the PATH search.
  212.          * This is why execvpe() isn't being used, we manipulate the environment
  213.          * manually then let it potentially affect execvp().  execvpe() simply
  214.          * passes the environment to execve() _after_ performing the search, not
  215.          * what we want here. */
  216.         pexit_if(execvp(exe, args) == -1 &&
  217.                  errno != ENOENT && errno != EACCES,
  218.                  "Exec of \"%s\" failed", exe);
  219.         diag(exe);
  220.  
  221.         return EXIT_FAILURE;
  222. }
  223.  
downloadenterexec.c Source code - Download rkt Source code
Related Source Codes/Software:
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
postal - 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
angular-starter - 2017-06-10

 Back to top