LCOV - code coverage report
Current view: top level - home/snorch/criu - util.c (source / functions) Hit Total Coverage
Test: coverage3.info Lines: 209 270 77.4 %
Date: 2014-04-22 Functions: 31 31 100.0 %
Branches: 117 186 62.9 %

           Branch data     Line data    Source code
       1                 :            : #define _XOPEN_SOURCE
       2                 :            : 
       3                 :            : #include <stdlib.h>
       4                 :            : #include <stdio.h>
       5                 :            : #include <stdarg.h>
       6                 :            : #include <string.h>
       7                 :            : #include <errno.h>
       8                 :            : #include <unistd.h>
       9                 :            : #include <stdbool.h>
      10                 :            : #include <limits.h>
      11                 :            : #include <signal.h>
      12                 :            : #include <limits.h>
      13                 :            : #include <unistd.h>
      14                 :            : #include <errno.h>
      15                 :            : #include <string.h>
      16                 :            : #include <dirent.h>
      17                 :            : #include <sys/sendfile.h>
      18                 :            : #include <fcntl.h>
      19                 :            : 
      20                 :            : #include <sys/param.h>
      21                 :            : #include <sys/types.h>
      22                 :            : #include <sys/ptrace.h>
      23                 :            : #include <sys/types.h>
      24                 :            : #include <sys/time.h>
      25                 :            : #include <sys/resource.h>
      26                 :            : #include <sys/stat.h>
      27                 :            : #include <sys/mman.h>
      28                 :            : #include <sys/vfs.h>
      29                 :            : #include <sys/ptrace.h>
      30                 :            : #include <sys/wait.h>
      31                 :            : #include <sys/resource.h>
      32                 :            : #include <sys/wait.h>
      33                 :            : 
      34                 :            : #include "compiler.h"
      35                 :            : #include "asm/types.h"
      36                 :            : #include "list.h"
      37                 :            : #include "util.h"
      38                 :            : #include "rst-malloc.h"
      39                 :            : #include "image.h"
      40                 :            : #include "vma.h"
      41                 :            : #include "mem.h"
      42                 :            : 
      43                 :            : #include "cr_options.h"
      44                 :            : #include "servicefd.h"
      45                 :            : #include "cr-service.h"
      46                 :            : 
      47                 :            : #define VMA_OPT_LEN     128
      48                 :            : 
      49                 :     194871 : static void vma_opt_str(const struct vma_area *v, char *opt)
      50                 :            : {
      51                 :            :         int p = 0;
      52                 :            : 
      53                 :            : #define opt2s(_o, _s)   do {                            \
      54                 :            :                 if (v->e->status & _o)                        \
      55                 :            :                         p += sprintf(opt + p, _s " ");        \
      56                 :            :         } while (0)
      57                 :            : 
      58                 :     194871 :         opt[p] = '\0';
      59         [ +  + ]:     194871 :         opt2s(VMA_AREA_REGULAR, "reg");
      60         [ -  + ]:     194871 :         opt2s(VMA_AREA_STACK, "stk");
      61         [ +  + ]:     194871 :         opt2s(VMA_AREA_VSYSCALL, "vsys");
      62         [ +  + ]:     194871 :         opt2s(VMA_AREA_VDSO, "vdso");
      63         [ -  + ]:     194871 :         opt2s(VMA_FORCE_READ, "frd");
      64         [ +  + ]:     194871 :         opt2s(VMA_AREA_HEAP, "heap");
      65         [ +  + ]:     194871 :         opt2s(VMA_FILE_PRIVATE, "fp");
      66         [ +  + ]:     194871 :         opt2s(VMA_FILE_SHARED, "fs");
      67         [ +  + ]:     194871 :         opt2s(VMA_ANON_SHARED, "as");
      68         [ +  + ]:     194871 :         opt2s(VMA_ANON_PRIVATE, "ap");
      69         [ +  + ]:     194871 :         opt2s(VMA_AREA_SYSVIPC, "sysv");
      70         [ -  + ]:     194871 :         opt2s(VMA_AREA_SOCKET, "sk");
      71                 :            : 
      72                 :            : #undef opt2s
      73                 :     194871 : }
      74                 :            : 
      75                 :     194871 : void pr_vma(unsigned int loglevel, const struct vma_area *vma_area)
      76                 :            : {
      77                 :            :         char opt[VMA_OPT_LEN];
      78                 :            :         memset(opt, 0, VMA_OPT_LEN);
      79                 :            : 
      80         [ +  - ]:     194871 :         if (!vma_area)
      81                 :          0 :                 return;
      82                 :            : 
      83                 :     194871 :         vma_opt_str(vma_area, opt);
      84                 :     194871 :         print_on_level(loglevel, "%#"PRIx64"-%#"PRIx64" (%"PRIi64"K) prot %#x flags %#x off %#"PRIx64" "
      85                 :            :                         "%s shmid: %#"PRIx64"\n",
      86                 :            :                         vma_area->e->start, vma_area->e->end,
      87                 :     194871 :                         KBYTES(vma_area_len(vma_area)),
      88                 :            :                         vma_area->e->prot,
      89                 :            :                         vma_area->e->flags,
      90                 :            :                         vma_area->e->pgoff,
      91                 :     194871 :                         opt, vma_area->e->shmid);
      92                 :            : }
      93                 :            : 
      94                 :      51448 : int close_safe(int *fd)
      95                 :            : {
      96                 :            :         int ret = 0;
      97         [ +  + ]:      51448 :         if (*fd > -1) {
      98                 :      47302 :                 ret = close(*fd);
      99         [ +  - ]:      47302 :                 if (!ret)
     100                 :      47302 :                         *fd = -1;
     101                 :            :                 else
     102                 :          0 :                         pr_perror("Unable to close fd %d", *fd);
     103                 :            :         }
     104                 :            : 
     105                 :      51448 :         return ret;
     106                 :            : }
     107                 :            : 
     108                 :       5274 : int reopen_fd_as_safe(char *file, int line, int new_fd, int old_fd, bool allow_reuse_fd)
     109                 :            : {
     110                 :            :         int tmp;
     111                 :            : 
     112         [ +  + ]:       5274 :         if (old_fd != new_fd) {
     113                 :            : 
     114         [ +  + ]:       4099 :                 if (!allow_reuse_fd) {
     115 [ +  - ][ -  + ]:        677 :                         if (fcntl(new_fd, F_GETFD) != -1 || errno != EBADF) {
     116         [ #  # ]:          0 :                                 if (new_fd < 3) {
     117                 :            :                                         /*
     118                 :            :                                          * Standard descriptors.
     119                 :            :                                          */
     120                 :          0 :                                         pr_warn("fd %d already in use (called at %s:%d)\n",
     121                 :            :                                                 new_fd, file, line);
     122                 :            :                                 } else {
     123                 :          0 :                                         pr_err("fd %d already in use (called at %s:%d)\n",
     124                 :            :                                                 new_fd, file, line);
     125                 :          0 :                                         return -1;
     126                 :            :                                 }
     127                 :            :                         }
     128                 :            :                 }
     129                 :            : 
     130                 :       4099 :                 tmp = dup2(old_fd, new_fd);
     131         [ -  + ]:       4099 :                 if (tmp < 0) {
     132                 :          0 :                         pr_perror("Dup %d -> %d failed (called at %s:%d)",
     133                 :            :                                   old_fd, new_fd, file, line);
     134                 :          0 :                         return tmp;
     135                 :            :                 }
     136                 :            : 
     137                 :            :                 /* Just to have error message if failed */
     138                 :       4099 :                 close_safe(&old_fd);
     139                 :            :         }
     140                 :            : 
     141                 :            :         return 0;
     142                 :            : }
     143                 :            : 
     144                 :       4413 : int move_img_fd(int *img_fd, int want_fd)
     145                 :            : {
     146         [ +  + ]:       4413 :         if (*img_fd == want_fd) {
     147                 :            :                 int tmp;
     148                 :            : 
     149                 :        243 :                 tmp = dup(*img_fd);
     150         [ -  + ]:        243 :                 if (tmp < 0) {
     151                 :          0 :                         pr_perror("Can't dup file");
     152                 :          0 :                         return -1;
     153                 :            :                 }
     154                 :            : 
     155                 :        243 :                 close(*img_fd);
     156                 :            : 
     157                 :        243 :                 *img_fd = tmp;
     158                 :            :         }
     159                 :            : 
     160                 :            :         return 0;
     161                 :            : }
     162                 :            : 
     163                 :            : static pid_t open_proc_pid = 0;
     164                 :            : static int open_proc_fd = -1;
     165                 :            : 
     166                 :      28092 : int close_pid_proc(void)
     167                 :            : {
     168                 :            :         int ret = 0;
     169                 :            : 
     170         [ +  + ]:      28092 :         if (open_proc_fd >= 0)
     171                 :      16406 :                 ret = close(open_proc_fd);
     172                 :            : 
     173                 :      28092 :         open_proc_fd = -1;
     174                 :      28092 :         open_proc_pid = 0;
     175                 :            : 
     176                 :      28092 :         return ret;
     177                 :            : }
     178                 :            : 
     179                 :        559 : void close_proc()
     180                 :            : {
     181                 :       3379 :         close_pid_proc();
     182                 :            : 
     183                 :       3379 :         close_service_fd(PROC_FD_OFF);
     184                 :        559 : }
     185                 :            : 
     186                 :        564 : int set_proc_fd(int fd)
     187                 :            : {
     188         [ +  - ]:        564 :         if (install_service_fd(PROC_FD_OFF, fd) < 0)
     189                 :            :                 return -1;
     190                 :        564 :         return 0;
     191                 :            : }
     192                 :            : 
     193                 :       2820 : static int open_proc_sfd(char *path)
     194                 :            : {
     195                 :            :         int fd, ret;
     196                 :            :         close_proc();
     197                 :            : 
     198                 :            :         fd = open(path, O_DIRECTORY | O_RDONLY);
     199         [ -  + ]:       2820 :         if (fd == -1) {
     200                 :          0 :                 pr_err("Can't open %s\n", path);
     201                 :          0 :                 return -1;
     202                 :            :         }
     203                 :            : 
     204                 :       2820 :         ret = install_service_fd(PROC_FD_OFF, fd);
     205                 :       2820 :         close(fd);
     206         [ +  - ]:       2820 :         if (ret < 0)
     207                 :            :                 return -1;
     208                 :            : 
     209                 :       2820 :         return 0;
     210                 :            : }
     211                 :            : 
     212                 :      73359 : inline int open_pid_proc(pid_t pid)
     213                 :            : {
     214                 :            :         char path[18];
     215                 :            :         int fd;
     216                 :            :         int dfd;
     217                 :            : 
     218         [ +  + ]:      73359 :         if (pid == open_proc_pid)
     219                 :      54907 :                 return open_proc_fd;
     220                 :            : 
     221                 :      18452 :         close_pid_proc();
     222                 :            : 
     223                 :      18452 :         dfd = get_service_fd(PROC_FD_OFF);
     224         [ +  + ]:      18452 :         if (dfd < 0) {
     225         [ +  - ]:       2820 :                 if (open_proc_sfd("/proc") < 0)
     226                 :            :                         return -1;
     227                 :            : 
     228                 :       2820 :                 dfd = get_service_fd(PROC_FD_OFF);
     229                 :            :         }
     230                 :            : 
     231                 :            :         snprintf(path, sizeof(path), "%d", pid);
     232                 :            :         fd = openat(dfd, path, O_RDONLY);
     233         [ +  + ]:      18452 :         if (fd < 0)
     234                 :         11 :                 pr_perror("Can't open %s", path);
     235                 :            :         else {
     236                 :      18441 :                 open_proc_fd = fd;
     237                 :      18441 :                 open_proc_pid = pid;
     238                 :            :         }
     239                 :            : 
     240                 :      18452 :         return fd;
     241                 :            : }
     242                 :            : 
     243                 :      62984 : int do_open_proc(pid_t pid, int flags, const char *fmt, ...)
     244                 :            : {
     245                 :            :         char path[128];
     246                 :            :         va_list args;
     247                 :      62984 :         int dirfd = open_pid_proc(pid);
     248                 :            : 
     249         [ +  + ]:      62984 :         if (dirfd < 0)
     250                 :            :                 return -1;
     251                 :            : 
     252                 :      62973 :         va_start(args, fmt);
     253                 :            :         vsnprintf(path, sizeof(path), fmt, args);
     254                 :      62973 :         va_end(args);
     255                 :            : 
     256                 :      62973 :         return openat(dirfd, path, flags);
     257                 :            : }
     258                 :            : 
     259                 :            : static int service_fd_rlim_cur;
     260                 :            : static int service_fd_id = 0;
     261                 :            : 
     262                 :       3702 : int init_service_fd(void)
     263                 :            : {
     264                 :            :         struct rlimit rlimit;
     265                 :            : 
     266                 :            :         /*
     267                 :            :          * Service FDs are those that most likely won't
     268                 :            :          * conflict with any 'real-life' ones
     269                 :            :          */
     270                 :            : 
     271         [ -  + ]:       3702 :         if (getrlimit(RLIMIT_NOFILE, &rlimit)) {
     272                 :          0 :                 pr_perror("Can't get rlimit");
     273                 :          0 :                 return -1;
     274                 :            :         }
     275                 :            : 
     276                 :       3702 :         service_fd_rlim_cur = (int)rlimit.rlim_cur;
     277         [ -  + ]:       3702 :         BUG_ON(service_fd_rlim_cur < SERVICE_FD_MAX);
     278                 :            : 
     279                 :            :         return 0;
     280                 :            : }
     281                 :            : 
     282                 :            : static int __get_service_fd(enum sfd_type type, int service_fd_id)
     283                 :            : {
     284                 :    4600565 :         return service_fd_rlim_cur - type - SERVICE_FD_MAX * service_fd_id;
     285                 :            : }
     286                 :            : 
     287                 :            : static DECLARE_BITMAP(sfd_map, SERVICE_FD_MAX);
     288                 :            : 
     289                 :         12 : int reserve_service_fd(enum sfd_type type)
     290                 :            : {
     291                 :         12 :         int sfd = __get_service_fd(type, service_fd_id);
     292                 :            : 
     293         [ -  + ]:         12 :         BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
     294                 :            : 
     295                 :         12 :         set_bit(type, sfd_map);
     296                 :         12 :         return sfd;
     297                 :            : }
     298                 :            : 
     299                 :      14160 : int install_service_fd(enum sfd_type type, int fd)
     300                 :            : {
     301                 :      14160 :         int sfd = __get_service_fd(type, service_fd_id);
     302                 :            : 
     303         [ -  + ]:      14160 :         BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
     304                 :            : 
     305         [ -  + ]:      14160 :         if (dup3(fd, sfd, O_CLOEXEC) != sfd) {
     306                 :          0 :                 pr_perror("Dup %d -> %d failed", fd, sfd);
     307                 :          0 :                 return -1;
     308                 :            :         }
     309                 :            : 
     310                 :      14160 :         set_bit(type, sfd_map);
     311                 :      14160 :         return sfd;
     312                 :            : }
     313                 :            : 
     314                 :    4583868 : int get_service_fd(enum sfd_type type)
     315                 :            : {
     316         [ -  + ]:    4583868 :         BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
     317                 :            : 
     318         [ +  + ]:    4583868 :         if (!test_bit(type, sfd_map))
     319                 :            :                 return -1;
     320                 :            : 
     321                 :    4575353 :         return __get_service_fd(type, service_fd_id);
     322                 :            : }
     323                 :            : 
     324                 :          6 : int criu_get_image_dir(void)
     325                 :            : {
     326                 :          6 :         return get_service_fd(IMG_FD_OFF);
     327                 :            : }
     328                 :            : 
     329                 :       7365 : int close_service_fd(enum sfd_type type)
     330                 :            : {
     331                 :            :         int fd;
     332                 :            : 
     333                 :       7365 :         fd = get_service_fd(type);
     334         [ +  + ]:       7365 :         if (fd < 0)
     335                 :            :                 return 0;
     336                 :            : 
     337         [ +  - ]:       1810 :         if (close_safe(&fd))
     338                 :            :                 return -1;
     339                 :            : 
     340                 :       1810 :         clear_bit(type, sfd_map);
     341                 :       1810 :         return 0;
     342                 :            : }
     343                 :            : 
     344                 :        688 : int clone_service_fd(int id)
     345                 :            : {
     346                 :            :         int ret = -1, i;
     347                 :            : 
     348         [ +  + ]:        688 :         if (service_fd_id == id)
     349                 :            :                 return 0;
     350                 :            : 
     351         [ +  + ]:         80 :         for (i = SERVICE_FD_MIN + 1; i < SERVICE_FD_MAX; i++) {
     352                 :         70 :                 int old = __get_service_fd(i, service_fd_id);
     353                 :            :                 int new = __get_service_fd(i, id);
     354                 :            : 
     355                 :         70 :                 ret = dup2(old, new);
     356         [ +  + ]:         70 :                 if (ret == -1) {
     357         [ +  - ]:         20 :                         if (errno == EBADF)
     358                 :         20 :                                 continue;
     359                 :          0 :                         pr_perror("Unable to clone %d->%d", old, new);
     360                 :            :                 }
     361                 :            :         }
     362                 :            : 
     363                 :         10 :         service_fd_id = id;
     364                 :            :         ret = 0;
     365                 :            : 
     366                 :         10 :         return ret;
     367                 :            : }
     368                 :            : 
     369                 :       6850 : bool is_any_service_fd(int fd)
     370                 :            : {
     371 [ +  + ][ -  + ]:       6850 :         return fd > __get_service_fd(SERVICE_FD_MAX, service_fd_id) &&
     372                 :            :                 fd < __get_service_fd(SERVICE_FD_MIN, service_fd_id);
     373                 :            : }
     374                 :            : 
     375                 :        192 : bool is_service_fd(int fd, enum sfd_type type)
     376                 :            : {
     377                 :        192 :         return fd == get_service_fd(type);
     378                 :            : }
     379                 :            : 
     380                 :         44 : int copy_file(int fd_in, int fd_out, size_t bytes)
     381                 :            : {
     382                 :            :         ssize_t written = 0;
     383         [ +  + ]:         44 :         size_t chunk = bytes ? bytes : 4096;
     384                 :            : 
     385                 :            :         while (1) {
     386                 :            :                 ssize_t ret;
     387                 :            : 
     388                 :         78 :                 ret = sendfile(fd_out, fd_in, NULL, chunk);
     389         [ -  + ]:         78 :                 if (ret < 0) {
     390                 :          0 :                         pr_perror("Can't send data to ghost file");
     391                 :          0 :                         return -1;
     392                 :            :                 }
     393                 :            : 
     394         [ +  + ]:         78 :                 if (ret == 0) {
     395         [ -  + ]:         44 :                         if (bytes && (written != bytes)) {
     396                 :          0 :                                 pr_err("Ghost file size mismatch %zu/%zu\n",
     397                 :            :                                                 written, bytes);
     398                 :          0 :                                 return -1;
     399                 :            :                         }
     400                 :            :                         break;
     401                 :            :                 }
     402                 :            : 
     403                 :         34 :                 written += ret;
     404                 :         34 :         }
     405                 :            : 
     406                 :            :         return 0;
     407                 :            : }
     408                 :            : 
     409                 :       5092 : int read_fd_link(int lfd, char *buf, size_t size)
     410                 :            : {
     411                 :            :         char t[32];
     412                 :            :         ssize_t ret;
     413                 :            : 
     414                 :            :         snprintf(t, sizeof(t), "/proc/self/fd/%d", lfd);
     415                 :            :         ret = readlink(t, buf, size);
     416         [ -  + ]:       5092 :         if (ret < 0) {
     417                 :          0 :                 pr_perror("Can't read link of fd %d", lfd);
     418                 :          0 :                 return -1;
     419         [ -  + ]:       5092 :         } else if ((size_t)ret == size) {
     420                 :          0 :                 pr_err("Buffer for read link of fd %d is too small\n", lfd);
     421                 :          0 :                 return -1;
     422                 :            :         }
     423                 :       5092 :         buf[ret] = 0;
     424                 :            : 
     425                 :       5092 :         return ret;
     426                 :            : }
     427                 :            : 
     428                 :      34158 : int is_anon_link_type(char *link, char *type)
     429                 :            : {
     430                 :            :         char aux[32];
     431                 :            : 
     432                 :            :         snprintf(aux, sizeof(aux), "anon_inode:%s", type);
     433                 :      34158 :         return !strcmp(link, aux);
     434                 :            : }
     435                 :            : 
     436                 :      10486 : void *shmalloc(size_t bytes)
     437                 :            : {
     438                 :      10486 :         return rst_mem_alloc(bytes, RM_SHARED);
     439                 :            : }
     440                 :            : 
     441                 :            : /* Only last chunk can be released */
     442                 :        354 : void shfree_last(void *ptr)
     443                 :            : {
     444                 :        354 :         rst_mem_free_last(RM_SHARED);
     445                 :        354 : }
     446                 :            : 
     447                 :       1772 : int run_scripts(char *action)
     448                 :            : {
     449                 :            :         struct script *script;
     450                 :            :         int ret = 0;
     451                 :            : 
     452                 :       1772 :         pr_debug("Running %s scripts\n", action);
     453                 :            : 
     454         [ -  + ]:       1772 :         if (setenv("CRTOOLS_SCRIPT_ACTION", action, 1)) {
     455                 :          0 :                 pr_perror("Can't set CRTOOLS_SCRIPT_ACTION=%s", action);
     456                 :          0 :                 return -1;
     457                 :            :         }
     458                 :            : 
     459         [ -  + ]:       1772 :         list_for_each_entry(script, &opts.scripts, node) {
     460         [ #  # ]:          0 :                 if (script->path == SCRIPT_RPC_NOTIFY) {
     461                 :          0 :                         pr_debug("\tRPC\n");
     462                 :          0 :                         ret |= send_criu_rpc_script(action, script->arg);
     463                 :            :                 } else {
     464                 :          0 :                         pr_debug("\t[%s]\n", script->path);
     465                 :          0 :                         ret |= system(script->path);
     466                 :            :                 }
     467                 :            :         }
     468                 :            : 
     469                 :       1772 :         unsetenv("CRTOOLS_SCRIPT_ACTION");
     470                 :       1772 :         return ret;
     471                 :            : }
     472                 :            : 
     473                 :            : #define DUP_SAFE(fd, out)                                               \
     474                 :            :         ({                                                      \
     475                 :            :                 int ret__;                                      \
     476                 :            :                 ret__ = dup(fd);                                \
     477                 :            :                 if (ret__ == -1) {                              \
     478                 :            :                         pr_perror("dup(%d) failed", fd);      \
     479                 :            :                         goto out;                               \
     480                 :            :                 }                                               \
     481                 :            :                 ret__;                                          \
     482                 :            :         })
     483                 :            : 
     484                 :            : /*
     485                 :            :  * If "in" is negative, stdin will be closed.
     486                 :            :  * If "out" or "err" are negative, a log file descriptor will be used.
     487                 :            :  */
     488                 :       1388 : int cr_system(int in, int out, int err, char *cmd, char *const argv[])
     489                 :            : {
     490                 :            :         sigset_t blockmask, oldmask;
     491                 :            :         int ret = -1, status;
     492                 :            :         pid_t pid;
     493                 :            : 
     494                 :       1388 :         sigemptyset(&blockmask);
     495                 :       1388 :         sigaddset(&blockmask, SIGCHLD);
     496         [ -  + ]:       1388 :         if (sigprocmask(SIG_BLOCK, &blockmask, &oldmask) == -1) {
     497                 :          0 :                 pr_perror("Can not set mask of blocked signals");
     498                 :          0 :                 return -1;
     499                 :            :         }
     500                 :            : 
     501                 :       1388 :         pid = fork();
     502         [ -  + ]:       2566 :         if (pid == -1) {
     503                 :          0 :                 pr_perror("fork() failed");
     504                 :          0 :                 goto out;
     505         [ +  + ]:       2566 :         } else if (pid == 0) {
     506         [ +  + ]:       1388 :                 if (out < 0)
     507                 :        742 :                         out = log_get_fd();
     508         [ +  - ]:       1388 :                 if (err < 0)
     509                 :       1388 :                         err = log_get_fd();
     510                 :            : 
     511                 :            :                 /*
     512                 :            :                  * out, err, in should be a separate fds,
     513                 :            :                  * because reopen_fd_as() closes an old fd
     514                 :            :                  */
     515         [ +  + ]:       1388 :                 if (err == out || err == in)
     516         [ -  + ]:        742 :                         err = DUP_SAFE(err, out_chld);
     517                 :            : 
     518         [ -  + ]:       1388 :                 if (out == in)
     519         [ #  # ]:          0 :                         out = DUP_SAFE(out, out_chld);
     520                 :            : 
     521   [ +  -  +  - ]:       2776 :                 if (move_img_fd(&out, STDIN_FILENO) ||
     522                 :       1388 :                     move_img_fd(&err, STDIN_FILENO))
     523                 :            :                         goto out_chld;
     524                 :            : 
     525         [ +  + ]:       1388 :                 if (in < 0) {
     526                 :        742 :                         close(STDIN_FILENO);
     527                 :            :                 } else {
     528         [ +  - ]:        646 :                         if (reopen_fd_as_nocheck(STDIN_FILENO, in))
     529                 :            :                                 goto out_chld;
     530                 :            :                 }
     531                 :            : 
     532         [ +  - ]:       1388 :                 if (move_img_fd(&err, STDOUT_FILENO))
     533                 :            :                         goto out_chld;
     534                 :            : 
     535         [ +  - ]:       1388 :                 if (reopen_fd_as_nocheck(STDOUT_FILENO, out))
     536                 :            :                         goto out_chld;
     537                 :            : 
     538         [ +  - ]:       1388 :                 if (reopen_fd_as_nocheck(STDERR_FILENO, err))
     539                 :            :                         goto out_chld;
     540                 :            : 
     541                 :       1388 :                 execvp(cmd, argv);
     542                 :            : 
     543                 :       1388 :                 pr_perror("exec failed");
     544                 :            : out_chld:
     545                 :          0 :                 _exit(1);
     546                 :            :         }
     547                 :            : 
     548                 :            :         while (1) {
     549                 :       1178 :                 ret = waitpid(pid, &status, 0);
     550         [ -  + ]:       1178 :                 if (ret == -1) {
     551                 :          0 :                         pr_perror("waitpid() failed");
     552                 :          0 :                         goto out;
     553                 :            :                 }
     554                 :            : 
     555         [ +  - ]:       1178 :                 if (WIFEXITED(status)) {
     556         [ -  + ]:       1178 :                         if (WEXITSTATUS(status))
     557                 :          0 :                                 pr_err("exited, status=%d\n", WEXITSTATUS(status));
     558                 :            :                         break;
     559         [ #  # ]:          0 :                 } else if (WIFSIGNALED(status)) {
     560                 :          0 :                         pr_err("killed by signal %d\n", WTERMSIG(status));
     561                 :          0 :                         break;
     562         [ #  # ]:          0 :                 } else if (WIFSTOPPED(status)) {
     563                 :          0 :                         pr_err("stopped by signal %d\n", WSTOPSIG(status));
     564         [ #  # ]:          0 :                 } else if (WIFCONTINUED(status)) {
     565                 :          0 :                         pr_err("continued\n");
     566                 :            :                 }
     567                 :            :         }
     568                 :            : 
     569         [ +  - ]:       1178 :         ret = status ? -1 : 0;
     570                 :            : out:
     571         [ -  + ]:       1178 :         if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {
     572                 :          0 :                 pr_perror("Can not unset mask of blocked signals");
     573                 :          0 :                 BUG();
     574                 :            :         }
     575                 :            : 
     576                 :       1178 :         return ret;
     577                 :            : }
     578                 :            : 
     579                 :        896 : int cr_daemon(int nochdir, int noclose)
     580                 :            : {
     581                 :            :         int pid;
     582                 :            : 
     583                 :        896 :         pid = fork();
     584         [ -  + ]:       1792 :         if (pid < 0) {
     585                 :          0 :                 pr_perror("Can't fork");
     586                 :          0 :                 return -1;
     587                 :            :         }
     588                 :            : 
     589         [ +  + ]:       1792 :         if (pid > 0)
     590                 :            :                 return pid;
     591                 :            : 
     592                 :        896 :         setsid();
     593         [ -  + ]:        896 :         if (!nochdir)
     594         [ #  # ]:          0 :                 if (chdir("/") == -1)
     595                 :          0 :                         pr_perror("Can't change directory");
     596         [ +  - ]:        896 :         if (!noclose) {
     597                 :            :                 int fd;
     598                 :            : 
     599                 :            :                 fd = open("/dev/null", O_RDWR);
     600         [ -  + ]:        896 :                 if (fd < 0) {
     601                 :          0 :                         pr_perror("Can't open /dev/null");
     602                 :          0 :                         return -1;
     603                 :            :                 }
     604                 :        896 :                 dup2(fd, 0);
     605                 :        896 :                 dup2(fd, 1);
     606                 :        896 :                 dup2(fd, 2);
     607                 :        896 :                 close(fd);
     608                 :            :         }
     609                 :            : 
     610                 :            :         return 0;
     611                 :            : }
     612                 :            : 
     613                 :          2 : int is_root_user()
     614                 :            : {
     615         [ -  + ]:          2 :         if (geteuid() != 0) {
     616                 :          0 :                 pr_err("You need to be root to run this command\n");
     617                 :          0 :                 return 0;
     618                 :            :         }
     619                 :            : 
     620                 :            :         return 1;
     621                 :            : }
     622                 :            : 
     623                 :       4596 : int vaddr_to_pfn(unsigned long vaddr, u64 *pfn)
     624                 :            : {
     625                 :            :         int fd, ret = -1;
     626                 :            :         off_t off;
     627                 :            : 
     628         [ -  + ]:       4596 :         fd = open_proc(getpid(), "pagemap");
     629         [ +  - ]:       4596 :         if (fd < 0)
     630                 :            :                 return -1;
     631                 :            : 
     632                 :       4596 :         off = (vaddr / PAGE_SIZE) * sizeof(u64);
     633         [ -  + ]:       4596 :         if (lseek(fd, off, SEEK_SET) != off) {
     634                 :          0 :                 pr_perror("Failed to seek address %lx\n", vaddr);
     635                 :          0 :                 goto out;
     636                 :            :         }
     637                 :            : 
     638                 :       4596 :         ret = read(fd, pfn, sizeof(*pfn));
     639         [ -  + ]:       4596 :         if (ret != sizeof(*pfn)) {
     640                 :          0 :                 pr_perror("Can't read pme for pid %d", getpid());
     641                 :            :                 ret = -1;
     642                 :            :         } else {
     643                 :       4596 :                 *pfn &= PME_PFRAME_MASK;
     644                 :            :                 ret = 0;
     645                 :            :         }
     646                 :            : out:
     647                 :       4596 :         close(fd);
     648                 :       4596 :         return ret;
     649                 :            : }
     650                 :            : 
     651                 :            : /*
     652                 :            :  * Note since VMA_AREA_NONE = 0 we can skip assignment
     653                 :            :  * here and simply rely on xzalloc
     654                 :            :  */
     655                 :     230799 : struct vma_area *alloc_vma_area(void)
     656                 :            : {
     657                 :            :         struct vma_area *p;
     658                 :            : 
     659         [ -  + ]:     230799 :         p = xzalloc(sizeof(*p) + sizeof(VmaEntry));
     660         [ +  - ]:     230799 :         if (p) {
     661                 :     230799 :                 p->e = (VmaEntry *)(p + 1);
     662                 :     230799 :                 vma_entry__init(p->e);
     663                 :     230799 :                 p->vm_file_fd = -1;
     664                 :     230799 :                 p->e->fd = -1;
     665                 :            :         }
     666                 :            : 
     667                 :     230799 :         return p;
     668                 :            : }

Generated by: LCOV version 1.9