Projects STRLCPY criu Commits d2d3b6ff
🤬
  • ■ ■ ■ ■ ■
    criu/Makefile.crtools
    skipped 83 lines
    84 84  obj-y += fdstore.o
    85 85  obj-y += uffd.o
    86 86  obj-y += config.o
     87 +obj-y += servicefd.o
    87 88   
    88 89  ifeq ($(VDSO),y)
    89 90  obj-y += pie-util-vdso.o
    skipped 17 lines
  • ■ ■ ■ ■ ■ ■
    criu/include/servicefd.h
    skipped 7 lines
    8 8   
    9 9   LOG_FD_OFF,
    10 10   IMG_FD_OFF,
    11  - PROC_FD_OFF, /* fd with /proc for all proc_ calls */
     11 + PROC_FD_OFF, /* fd with /proc for all proc_ calls */
    12 12   PROC_PID_FD_OFF,
    13  - CR_PROC_FD_OFF, /* some other's proc fd.
    14  - * For dump -- target ns' proc
    15  - * For restore -- CRIU ns' proc
    16  - */
    17  - ROOT_FD_OFF, /* Root of the namespace we dump/restore */
     13 + CR_PROC_FD_OFF, /* some other's proc fd:
     14 + * - For dump -- target ns' proc
     15 + * - For restore -- CRIU ns' proc
     16 + */
     17 + ROOT_FD_OFF, /* Root of the namespace we dump/restore */
    18 18   CGROUP_YARD,
    19  - USERNSD_SK, /* Socket for usernsd */
    20  - NS_FD_OFF, /* Node's net namespace fd */
    21  - TRANSPORT_FD_OFF, /* to transfer file descriptors */
     19 + USERNSD_SK, /* Socket for usernsd */
     20 + NS_FD_OFF, /* Node's net namespace fd */
     21 + TRANSPORT_FD_OFF, /* to transfer file descriptors */
    22 22   RPC_SK_OFF,
    23 23   FDSTORE_SK_OFF,
    24 24   
    skipped 3 lines
    28 28  struct pstree_item;
    29 29  extern bool sfds_protected;
    30 30   
    31  -extern void set_proc_self_fd(int fd);
    32  -extern int clone_service_fd(struct pstree_item *me);
    33 31  extern int init_service_fd(void);
    34 32  extern int get_service_fd(enum sfd_type type);
     33 +extern bool is_any_service_fd(int fd);
     34 +extern bool is_service_fd(int fd, enum sfd_type type);
     35 +extern int service_fd_min_fd(struct pstree_item *item);
    35 36  extern int install_service_fd(enum sfd_type type, int fd);
    36 37  extern int close_service_fd(enum sfd_type type);
    37  -extern bool is_service_fd(int fd, enum sfd_type type);
    38  -extern bool is_any_service_fd(int fd);
    39  -extern int service_fd_min_fd(struct pstree_item *);
     38 +extern int clone_service_fd(struct pstree_item *me);
    40 39   
    41 40  #endif /* __CR_SERVICE_FD_H__ */
    42 41   
  • ■ ■ ■ ■ ■ ■
    criu/include/util.h
    skipped 179 lines
    180 180  extern int close_status_fd(void);
    181 181  extern int is_root_user(void);
    182 182   
     183 +extern void set_proc_self_fd(int fd);
     184 + 
    183 185  static inline bool dir_dots(const struct dirent *de)
    184 186  {
    185 187   return !strcmp(de->d_name, ".") || !strcmp(de->d_name, "..");
    skipped 195 lines
  • ■ ■ ■ ■ ■ ■
    criu/plugin.c
    skipped 9 lines
    10 10  #include "common/compiler.h"
    11 11  #include "xmalloc.h"
    12 12  #include "plugin.h"
     13 +#include "servicefd.h"
    13 14  #include "common/list.h"
    14 15  #include "log.h"
    15 16   
    skipped 72 lines
    88 89   }
    89 90   
    90 91   return 0;
     92 +}
     93 + 
     94 +int criu_get_image_dir(void)
     95 +{
     96 + return get_service_fd(IMG_FD_OFF);
    91 97  }
    92 98   
    93 99  static int cr_lib_load(int stage, char *path)
    skipped 162 lines
  • ■ ■ ■ ■ ■ ■
    criu/servicefd.c
     1 +#include <stdio.h>
     2 +#include <errno.h>
     3 +#include <unistd.h>
     4 +#include <sched.h>
     5 + 
     6 +#include <sys/time.h>
     7 +#include <sys/syscall.h>
     8 +#include <sys/resource.h>
     9 + 
     10 +#include "common/compiler.h"
     11 +#include "common/list.h"
     12 + 
     13 +#include "criu-log.h"
     14 + 
     15 +#include "util.h"
     16 +#include "bitops.h"
     17 +#include "pstree.h"
     18 +#include "files.h"
     19 +#include "rst_info.h"
     20 +#include "servicefd.h"
     21 + 
     22 +#undef LOG_PREFIX
     23 +#define LOG_PREFIX "sfd: "
     24 + 
     25 +/* Max potentially possible fd to be open by criu process */
     26 +int service_fd_rlim_cur;
     27 + 
     28 +/* Base of current process service fds set */
     29 +static int service_fd_base;
     30 + 
     31 +/* Id of current process in shared fdt */
     32 +static int service_fd_id = 0;
     33 + 
     34 +static DECLARE_BITMAP(sfd_map, SERVICE_FD_MAX);
     35 +static int sfd_arr[SERVICE_FD_MAX];
     36 +/*
     37 + * Variable for marking areas of code, where service fds modifications
     38 + * are prohibited. It's used to safe them from reusing their numbers
     39 + * by ordinary files. See install_service_fd() and close_service_fd().
     40 + */
     41 +bool sfds_protected = false;
     42 + 
     43 +int init_service_fd(void)
     44 +{
     45 + struct rlimit64 rlimit;
     46 + 
     47 + /*
     48 + * Service FDs are those that most likely won't
     49 + * conflict with any 'real-life' ones
     50 + */
     51 + 
     52 + if (syscall(__NR_prlimit64, getpid(), RLIMIT_NOFILE, NULL, &rlimit)) {
     53 + pr_perror("Can't get rlimit");
     54 + return -1;
     55 + }
     56 + 
     57 + service_fd_rlim_cur = (int)rlimit.rlim_cur;
     58 + return 0;
     59 +}
     60 + 
     61 +static int __get_service_fd(enum sfd_type type, int service_fd_id)
     62 +{
     63 + return service_fd_base - type - SERVICE_FD_MAX * service_fd_id;
     64 +}
     65 + 
     66 +int get_service_fd(enum sfd_type type)
     67 +{
     68 + BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
     69 + 
     70 + if (!test_bit(type, sfd_map))
     71 + return -1;
     72 + 
     73 + if (service_fd_base == 0)
     74 + return sfd_arr[type];
     75 + 
     76 + return __get_service_fd(type, service_fd_id);
     77 +}
     78 + 
     79 +bool is_any_service_fd(int fd)
     80 +{
     81 + int sfd_min_fd = __get_service_fd(SERVICE_FD_MAX, service_fd_id);
     82 + int sfd_max_fd = __get_service_fd(SERVICE_FD_MIN, service_fd_id);
     83 + 
     84 + if (fd > sfd_min_fd && fd < sfd_max_fd) {
     85 + int type = SERVICE_FD_MAX - (fd - sfd_min_fd);
     86 + if (type > SERVICE_FD_MIN && type < SERVICE_FD_MAX)
     87 + return !!test_bit(type, sfd_map);
     88 + }
     89 + 
     90 + return false;
     91 +}
     92 + 
     93 +bool is_service_fd(int fd, enum sfd_type type)
     94 +{
     95 + return fd == get_service_fd(type);
     96 +}
     97 + 
     98 +int service_fd_min_fd(struct pstree_item *item)
     99 +{
     100 + struct fdt *fdt = rsti(item)->fdt;
     101 + int id = 0;
     102 + 
     103 + if (fdt)
     104 + id = fdt->nr - 1;
     105 + return service_fd_rlim_cur - (SERVICE_FD_MAX - 1) - SERVICE_FD_MAX * id;
     106 +}
     107 + 
     108 +static void sfds_protection_bug(enum sfd_type type)
     109 +{
     110 + pr_err("Service fd %u is being modified in protected context\n", type);
     111 + print_stack_trace(current ? vpid(current) : 0);
     112 + BUG();
     113 +}
     114 + 
     115 +int install_service_fd(enum sfd_type type, int fd)
     116 +{
     117 + int sfd = __get_service_fd(type, service_fd_id);
     118 + 
     119 + BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
     120 + if (sfds_protected && !test_bit(type, sfd_map))
     121 + sfds_protection_bug(type);
     122 + 
     123 + if (service_fd_base == 0) {
     124 + if (test_bit(type, sfd_map))
     125 + close(sfd_arr[type]);
     126 + sfd_arr[type] = fd;
     127 + set_bit(type, sfd_map);
     128 + return fd;
     129 + }
     130 + 
     131 + if (dup3(fd, sfd, O_CLOEXEC) != sfd) {
     132 + pr_perror("Dup %d -> %d failed", fd, sfd);
     133 + close(fd);
     134 + return -1;
     135 + }
     136 + 
     137 + set_bit(type, sfd_map);
     138 + close(fd);
     139 + return sfd;
     140 +}
     141 + 
     142 +int close_service_fd(enum sfd_type type)
     143 +{
     144 + int fd;
     145 + 
     146 + if (sfds_protected)
     147 + sfds_protection_bug(type);
     148 + 
     149 + fd = get_service_fd(type);
     150 + if (fd < 0)
     151 + return 0;
     152 + 
     153 + if (close_safe(&fd))
     154 + return -1;
     155 + 
     156 + clear_bit(type, sfd_map);
     157 + return 0;
     158 +}
     159 + 
     160 +static void move_service_fd(struct pstree_item *me, int type, int new_id, int new_base)
     161 +{
     162 + int old = get_service_fd(type);
     163 + int new = new_base - type - SERVICE_FD_MAX * new_id;
     164 + int ret;
     165 + 
     166 + if (old < 0)
     167 + return;
     168 + 
     169 + ret = dup2(old, new);
     170 + if (ret == -1) {
     171 + if (errno != EBADF)
     172 + pr_perror("Unable to clone %d->%d", old, new);
     173 + } else if (!(rsti(me)->clone_flags & CLONE_FILES))
     174 + close(old);
     175 +}
     176 + 
     177 +static int choose_service_fd_base(struct pstree_item *me)
     178 +{
     179 + int nr, real_nr, fdt_nr = 1, id = rsti(me)->service_fd_id;
     180 + 
     181 + if (rsti(me)->fdt) {
     182 + /* The base is set by owner of fdt (id 0) */
     183 + if (id != 0)
     184 + return service_fd_base;
     185 + fdt_nr = rsti(me)->fdt->nr;
     186 + }
     187 + /* Now find process's max used fd number */
     188 + if (!list_empty(&rsti(me)->fds))
     189 + nr = list_entry(rsti(me)->fds.prev,
     190 + struct fdinfo_list_entry, ps_list)->fe->fd;
     191 + else
     192 + nr = -1;
     193 + 
     194 + nr = max(nr, inh_fd_max);
     195 + /*
     196 + * Service fds go after max fd near right border of alignment:
     197 + *
     198 + * ...|max_fd|max_fd+1|...|sfd first|...|sfd last (aligned)|
     199 + *
     200 + * So, they take maximum numbers of area allocated by kernel.
     201 + * See linux alloc_fdtable() for details.
     202 + */
     203 + nr += (SERVICE_FD_MAX - SERVICE_FD_MIN) * fdt_nr;
     204 + nr += 16; /* Safety pad */
     205 + real_nr = nr;
     206 + 
     207 + nr /= (1024 / sizeof(void *));
     208 + if (nr)
     209 + nr = 1 << (32 - __builtin_clz(nr));
     210 + else
     211 + nr = 1;
     212 + nr *= (1024 / sizeof(void *));
     213 + 
     214 + if (nr > service_fd_rlim_cur) {
     215 + /* Right border is bigger, than rlim. OK, then just aligned value is enough */
     216 + nr = round_down(service_fd_rlim_cur, (1024 / sizeof(void *)));
     217 + if (nr < real_nr) {
     218 + pr_err("Can't chose service_fd_base: %d %d\n", nr, real_nr);
     219 + return -1;
     220 + }
     221 + }
     222 + 
     223 + return nr;
     224 +}
     225 + 
     226 +int clone_service_fd(struct pstree_item *me)
     227 +{
     228 + int id, new_base, i, ret = -1;
     229 + 
     230 + new_base = choose_service_fd_base(me);
     231 + id = rsti(me)->service_fd_id;
     232 + 
     233 + if (new_base == -1)
     234 + return -1;
     235 + if (service_fd_base == new_base && service_fd_id == id)
     236 + return 0;
     237 + 
     238 + /* Dup sfds in memmove() style: they may overlap */
     239 + if (get_service_fd(LOG_FD_OFF) < new_base - LOG_FD_OFF - SERVICE_FD_MAX * id)
     240 + for (i = SERVICE_FD_MIN + 1; i < SERVICE_FD_MAX; i++)
     241 + move_service_fd(me, i, id, new_base);
     242 + else
     243 + for (i = SERVICE_FD_MAX - 1; i > SERVICE_FD_MIN; i--)
     244 + move_service_fd(me, i, id, new_base);
     245 + 
     246 + service_fd_base = new_base;
     247 + service_fd_id = id;
     248 + ret = 0;
     249 + 
     250 + return ret;
     251 +}
     252 + 
  • ■ ■ ■ ■ ■ ■
    criu/util.c
    skipped 4 lines
    5 5  #include <string.h>
    6 6  #include <errno.h>
    7 7  #include <stdbool.h>
    8  -#include <limits.h>
    9 8  #include <signal.h>
    10 9  #include <unistd.h>
    11 10  #include <dirent.h>
    skipped 5 lines
    17 16  #include <sys/param.h>
    18 17  #include <sys/types.h>
    19 18  #include <sys/ptrace.h>
    20  -#include <sys/time.h>
    21  -#include <sys/resource.h>
    22 19  #include <sys/stat.h>
    23 20  #include <sys/mman.h>
    24 21  #include <sys/wait.h>
    skipped 4 lines
    29 26  #include <sched.h>
    30 27  #include <ctype.h>
    31 28   
    32  -#include "bitops.h"
    33 29  #include "page.h"
    34  -#include "common/compiler.h"
    35  -#include "common/list.h"
    36 30  #include "util.h"
    37  -#include "rst-malloc.h"
    38 31  #include "image.h"
    39 32  #include "vma.h"
    40 33  #include "mem.h"
    skipped 2 lines
    43 36   
    44 37  #include "clone-noasan.h"
    45 38  #include "cr_options.h"
    46  -#include "servicefd.h"
    47 39  #include "cr-service.h"
    48 40  #include "files.h"
    49 41  #include "pstree.h"
    skipped 370 lines
    420 412   va_end(args);
    421 413   
    422 414   return openat(dirfd, path, flags);
    423  -}
    424  - 
    425  -/* Max potentially possible fd to be open by criu process */
    426  -int service_fd_rlim_cur;
    427  -/* Base of current process service fds set */
    428  -static int service_fd_base;
    429  -/* Id of current process in shared fdt */
    430  -static int service_fd_id = 0;
    431  - 
    432  -int init_service_fd(void)
    433  -{
    434  - struct rlimit64 rlimit;
    435  - 
    436  - /*
    437  - * Service FDs are those that most likely won't
    438  - * conflict with any 'real-life' ones
    439  - */
    440  - 
    441  - if (syscall(__NR_prlimit64, getpid(), RLIMIT_NOFILE, NULL, &rlimit)) {
    442  - pr_perror("Can't get rlimit");
    443  - return -1;
    444  - }
    445  - 
    446  - service_fd_rlim_cur = (int)rlimit.rlim_cur;
    447  - 
    448  - return 0;
    449  -}
    450  - 
    451  -static int __get_service_fd(enum sfd_type type, int service_fd_id)
    452  -{
    453  - return service_fd_base - type - SERVICE_FD_MAX * service_fd_id;
    454  -}
    455  - 
    456  -int service_fd_min_fd(struct pstree_item *item)
    457  -{
    458  - struct fdt *fdt = rsti(item)->fdt;
    459  - int id = 0;
    460  - 
    461  - if (fdt)
    462  - id = fdt->nr - 1;
    463  - return service_fd_rlim_cur - (SERVICE_FD_MAX - 1) - SERVICE_FD_MAX * id;
    464  -}
    465  - 
    466  -static DECLARE_BITMAP(sfd_map, SERVICE_FD_MAX);
    467  -static int sfd_arr[SERVICE_FD_MAX];
    468  -/*
    469  - * Variable for marking areas of code, where service fds modifications
    470  - * are prohibited. It's used to safe them from reusing their numbers
    471  - * by ordinary files. See install_service_fd() and close_service_fd().
    472  - */
    473  -bool sfds_protected = false;
    474  - 
    475  -static void sfds_protection_bug(enum sfd_type type)
    476  -{
    477  - pr_err("Service fd %u is being modified in protected context\n", type);
    478  - print_stack_trace(current ? vpid(current) : 0);
    479  - BUG();
    480  -}
    481  - 
    482  -int install_service_fd(enum sfd_type type, int fd)
    483  -{
    484  - int sfd = __get_service_fd(type, service_fd_id);
    485  - 
    486  - BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
    487  - if (sfds_protected && !test_bit(type, sfd_map))
    488  - sfds_protection_bug(type);
    489  - 
    490  - if (service_fd_base == 0) {
    491  - if (test_bit(type, sfd_map))
    492  - close(sfd_arr[type]);
    493  - sfd_arr[type] = fd;
    494  - set_bit(type, sfd_map);
    495  - return fd;
    496  - }
    497  - 
    498  - if (dup3(fd, sfd, O_CLOEXEC) != sfd) {
    499  - pr_perror("Dup %d -> %d failed", fd, sfd);
    500  - close(fd);
    501  - return -1;
    502  - }
    503  - 
    504  - set_bit(type, sfd_map);
    505  - close(fd);
    506  - return sfd;
    507  -}
    508  - 
    509  -int get_service_fd(enum sfd_type type)
    510  -{
    511  - BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
    512  - 
    513  - if (!test_bit(type, sfd_map))
    514  - return -1;
    515  - 
    516  - if (service_fd_base == 0)
    517  - return sfd_arr[type];
    518  - 
    519  - return __get_service_fd(type, service_fd_id);
    520  -}
    521  - 
    522  -int criu_get_image_dir(void)
    523  -{
    524  - return get_service_fd(IMG_FD_OFF);
    525  -}
    526  - 
    527  -int close_service_fd(enum sfd_type type)
    528  -{
    529  - int fd;
    530  - 
    531  - if (sfds_protected)
    532  - sfds_protection_bug(type);
    533  - 
    534  - fd = get_service_fd(type);
    535  - if (fd < 0)
    536  - return 0;
    537  - 
    538  - if (close_safe(&fd))
    539  - return -1;
    540  - 
    541  - clear_bit(type, sfd_map);
    542  - return 0;
    543  -}
    544  - 
    545  -static void move_service_fd(struct pstree_item *me, int type, int new_id, int new_base)
    546  -{
    547  - int old = get_service_fd(type);
    548  - int new = new_base - type - SERVICE_FD_MAX * new_id;
    549  - int ret;
    550  - 
    551  - if (old < 0)
    552  - return;
    553  - ret = dup2(old, new);
    554  - if (ret == -1) {
    555  - if (errno != EBADF)
    556  - pr_perror("Unable to clone %d->%d", old, new);
    557  - } else if (!(rsti(me)->clone_flags & CLONE_FILES))
    558  - close(old);
    559  -}
    560  - 
    561  -static int choose_service_fd_base(struct pstree_item *me)
    562  -{
    563  - int nr, real_nr, fdt_nr = 1, id = rsti(me)->service_fd_id;
    564  - 
    565  - if (rsti(me)->fdt) {
    566  - /* The base is set by owner of fdt (id 0) */
    567  - if (id != 0)
    568  - return service_fd_base;
    569  - fdt_nr = rsti(me)->fdt->nr;
    570  - }
    571  - /* Now find process's max used fd number */
    572  - if (!list_empty(&rsti(me)->fds))
    573  - nr = list_entry(rsti(me)->fds.prev,
    574  - struct fdinfo_list_entry, ps_list)->fe->fd;
    575  - else
    576  - nr = -1;
    577  - 
    578  - nr = max(nr, inh_fd_max);
    579  - /*
    580  - * Service fds go after max fd near right border of alignment:
    581  - *
    582  - * ...|max_fd|max_fd+1|...|sfd first|...|sfd last (aligned)|
    583  - *
    584  - * So, they take maximum numbers of area allocated by kernel.
    585  - * See linux alloc_fdtable() for details.
    586  - */
    587  - nr += (SERVICE_FD_MAX - SERVICE_FD_MIN) * fdt_nr;
    588  - nr += 16; /* Safety pad */
    589  - real_nr = nr;
    590  - 
    591  - nr /= (1024 / sizeof(void *));
    592  - if (nr)
    593  - nr = 1 << (32 - __builtin_clz(nr));
    594  - else
    595  - nr = 1;
    596  - nr *= (1024 / sizeof(void *));
    597  - 
    598  - if (nr > service_fd_rlim_cur) {
    599  - /* Right border is bigger, than rlim. OK, then just aligned value is enough */
    600  - nr = round_down(service_fd_rlim_cur, (1024 / sizeof(void *)));
    601  - if (nr < real_nr) {
    602  - pr_err("Can't chose service_fd_base: %d %d\n", nr, real_nr);
    603  - return -1;
    604  - }
    605  - }
    606  - 
    607  - return nr;
    608  -}
    609  - 
    610  -int clone_service_fd(struct pstree_item *me)
    611  -{
    612  - int id, new_base, i, ret = -1;
    613  - 
    614  - new_base = choose_service_fd_base(me);
    615  - id = rsti(me)->service_fd_id;
    616  - 
    617  - if (new_base == -1)
    618  - return -1;
    619  - if (service_fd_base == new_base && service_fd_id == id)
    620  - return 0;
    621  - 
    622  - /* Dup sfds in memmove() style: they may overlap */
    623  - if (get_service_fd(LOG_FD_OFF) < new_base - LOG_FD_OFF - SERVICE_FD_MAX * id)
    624  - for (i = SERVICE_FD_MIN + 1; i < SERVICE_FD_MAX; i++)
    625  - move_service_fd(me, i, id, new_base);
    626  - else
    627  - for (i = SERVICE_FD_MAX - 1; i > SERVICE_FD_MIN; i--)
    628  - move_service_fd(me, i, id, new_base);
    629  - 
    630  - service_fd_base = new_base;
    631  - service_fd_id = id;
    632  - ret = 0;
    633  - 
    634  - return ret;
    635  -}
    636  - 
    637  -bool is_any_service_fd(int fd)
    638  -{
    639  - int sfd_min_fd = __get_service_fd(SERVICE_FD_MAX, service_fd_id);
    640  - int sfd_max_fd = __get_service_fd(SERVICE_FD_MIN, service_fd_id);
    641  - 
    642  - if (fd > sfd_min_fd && fd < sfd_max_fd) {
    643  - int type = SERVICE_FD_MAX - (fd - sfd_min_fd);
    644  - if (type > SERVICE_FD_MIN && type < SERVICE_FD_MAX)
    645  - return !!test_bit(type, sfd_map);
    646  - }
    647  - 
    648  - return false;
    649  -}
    650  - 
    651  -bool is_service_fd(int fd, enum sfd_type type)
    652  -{
    653  - return fd == get_service_fd(type);
    654 415  }
    655 416   
    656 417  int copy_file(int fd_in, int fd_out, size_t bytes)
    skipped 951 lines
Please wait...
Page is in error, reload to recover