LCOV - code coverage report
Current view: top level - crtools - namespaces.c (source / functions) Hit Total Coverage
Test: crtools.info Lines: 56 79 70.9 %
Date: 2012-12-28 Functions: 5 6 83.3 %
Branches: 39 66 59.1 %

           Branch data     Line data    Source code
       1                 :            : #include <unistd.h>
       2                 :            : #include <fcntl.h>
       3                 :            : #include <sys/wait.h>
       4                 :            : #include <stdlib.h>
       5                 :            : #include "util.h"
       6                 :            : #include "syscall.h"
       7                 :            : #include "uts_ns.h"
       8                 :            : #include "ipc_ns.h"
       9                 :            : #include "mount.h"
      10                 :            : #include "namespaces.h"
      11                 :            : #include "net.h"
      12                 :            : 
      13                 :        386 : int switch_ns(int pid, int type, char *ns, int *rst)
      14                 :            : {
      15                 :            :         char buf[32];
      16                 :            :         int nsfd;
      17                 :        386 :         int ret = -1;
      18                 :            : 
      19                 :        386 :         snprintf(buf, sizeof(buf), "/proc/%d/ns/%s", pid, ns);
      20                 :        386 :         nsfd = open(buf, O_RDONLY);
      21         [ -  + ]:        386 :         if (nsfd < 0) {
      22                 :          0 :                 pr_perror("Can't open ipcns file");
      23                 :          0 :                 goto err_ns;
      24                 :            :         }
      25                 :            : 
      26         [ +  + ]:        386 :         if (rst) {
      27                 :        152 :                 snprintf(buf, sizeof(buf), "/proc/self/ns/%s", ns);
      28                 :        152 :                 *rst = open(buf, O_RDONLY);
      29         [ -  + ]:        152 :                 if (*rst < 0) {
      30                 :          0 :                         pr_perror("Can't open ns file");
      31                 :          0 :                         goto err_rst;
      32                 :            :                 }
      33                 :            :         }
      34                 :            : 
      35                 :        386 :         ret = setns(nsfd, type);
      36         [ -  + ]:        386 :         if (ret < 0) {
      37                 :          0 :                 pr_perror("Can't setns %d/%s", pid, ns);
      38                 :            :                 goto err_set;
      39                 :            :         }
      40                 :            : 
      41                 :        386 :         close(nsfd);
      42                 :            :         return 0;
      43                 :            : 
      44                 :            : err_set:
      45         [ #  # ]:          0 :         if (rst)
      46                 :          0 :                 close(*rst);
      47                 :            : err_rst:
      48                 :        386 :         close(nsfd);
      49                 :            : err_ns:
      50                 :            :         return -1;
      51                 :            : }
      52                 :            : 
      53                 :        152 : int restore_ns(int rst, int type)
      54                 :            : {
      55                 :            :         int ret;
      56                 :            : 
      57                 :        152 :         ret = setns(rst, type);
      58         [ -  + ]:        152 :         if (ret < 0)
      59                 :          0 :                 pr_perror("Can't restore ns back");
      60                 :            : 
      61                 :        152 :         return ret;
      62                 :            : }
      63                 :            : 
      64                 :         83 : static int do_dump_namespaces(struct pid *ns_pid, unsigned int ns_flags)
      65                 :            : {
      66                 :            :         struct cr_fdset *fdset;
      67                 :         83 :         int ret = 0;
      68                 :            : 
      69                 :         83 :         fdset = cr_ns_fdset_open(ns_pid->virt, O_DUMP);
      70         [ +  - ]:         83 :         if (fdset == NULL)
      71                 :            :                 return -1;
      72                 :            : 
      73         [ +  + ]:         83 :         if (ns_flags & CLONE_NEWUTS) {
      74                 :         77 :                 pr_info("Dump UTS namespace\n");
      75                 :         77 :                 ret = dump_uts_ns(ns_pid->real, fdset);
      76         [ +  - ]:         77 :                 if (ret < 0)
      77                 :            :                         goto err;
      78                 :            :         }
      79         [ +  + ]:         83 :         if (ns_flags & CLONE_NEWIPC) {
      80                 :         81 :                 pr_info("Dump IPC namespace\n");
      81                 :         81 :                 ret = dump_ipc_ns(ns_pid->real, fdset);
      82         [ +  - ]:         81 :                 if (ret < 0)
      83                 :            :                         goto err;
      84                 :            :         }
      85         [ +  + ]:         83 :         if (ns_flags & CLONE_NEWNS) {
      86                 :         77 :                 pr_info("Dump MNT namespace (mountpoints)\n");
      87                 :         77 :                 ret = dump_mnt_ns(ns_pid->real, fdset);
      88         [ +  - ]:         77 :                 if (ret < 0)
      89                 :            :                         goto err;
      90                 :            :         }
      91         [ +  + ]:         83 :         if (ns_flags & CLONE_NEWNET) {
      92                 :         76 :                 pr_info("Dump NET namespace info\n");
      93                 :         76 :                 ret = dump_net_ns(ns_pid->real, fdset);
      94                 :            :                 if (ret < 0)
      95                 :            :                         goto err;
      96                 :            :         }
      97                 :            : err:
      98                 :         83 :         close_cr_fdset(&fdset);
      99                 :            :         return ret;
     100                 :            : 
     101                 :            : }
     102                 :            : 
     103                 :         83 : int dump_namespaces(struct pid *ns_pid, unsigned int ns_flags)
     104                 :            : {
     105                 :            :         int pid, status;
     106                 :         83 :         int ret = 0;
     107                 :            : 
     108                 :            :         /*
     109                 :            :          * The setns syscall is cool, we can switch to the other
     110                 :            :          * namespace and then return back to our initial one, but
     111                 :            :          * for me it's much easier just to fork another task and
     112                 :            :          * let it do the job, all the more so it can be done in
     113                 :            :          * parallel with task dumping routine.
     114                 :            :          *
     115                 :            :          * However, the question how to dump sockets from the target
     116                 :            :          * net namesapce with this is still open
     117                 :            :          */
     118                 :            : 
     119                 :         83 :         pr_info("Dumping %d(%d)'s namespaces\n", ns_pid->virt, ns_pid->real);
     120                 :            : 
     121 [ -  + ][ +  + ]:         83 :         if ((opts.namespaces_flags & CLONE_NEWPID) && ns_pid->virt != 1) {
     122                 :          0 :                 pr_err("Can't dump a pid namespace without the process init\n");
     123                 :            :                 return -1;
     124                 :            :         }
     125                 :            : 
     126                 :         83 :         pid = fork();
     127         [ -  + ]:        166 :         if (pid < 0) {
     128                 :          0 :                 pr_perror("Can't fork ns dumper");
     129                 :            :                 return -1;
     130                 :            :         }
     131                 :            : 
     132         [ +  + ]:        166 :         if (pid == 0) {
     133                 :         83 :                 ret = do_dump_namespaces(ns_pid, ns_flags);
     134                 :         83 :                 exit(ret);
     135                 :            :         }
     136                 :            : 
     137                 :         83 :         ret = waitpid(pid, &status, 0);
     138         [ -  + ]:         83 :         if (ret != pid) {
     139                 :          0 :                 pr_perror("Can't wait ns dumper");
     140                 :            :                 return -1;
     141                 :            :         }
     142                 :            : 
     143 [ +  - ][ -  + ]:         83 :         if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
     144                 :          0 :                 pr_err("Namespaces dumping finished with error %d\n", status);
     145                 :            :                 return -1;
     146                 :            :         }
     147                 :            : 
     148                 :         83 :         pr_info("Namespaces dump complete\n");
     149                 :            :         return 0;
     150                 :            : }
     151                 :            : 
     152                 :        214 : int prepare_namespace(int pid, unsigned long clone_flags)
     153                 :            : {
     154                 :        214 :         pr_info("Restoring namespaces %d flags 0x%lx\n",
     155                 :            :                         pid, clone_flags);
     156                 :            : 
     157                 :            :         /*
     158                 :            :          * On netns restore we launch an IP tool, thus we
     159                 :            :          * have to restore it _before_ altering the mount
     160                 :            :          * tree (i.e. -- mnt_ns restoring)
     161                 :            :          */
     162                 :            : 
     163 [ +  - ][ +  + ]:        214 :         if ((clone_flags & CLONE_NEWNET) && prepare_net_ns(pid))
     164                 :            :                 return -1;
     165 [ +  + ][ +  - ]:        355 :         if ((clone_flags & CLONE_NEWUTS) && prepare_utsns(pid))
     166                 :            :                 return -1;
     167 [ +  + ][ +  - ]:        355 :         if ((clone_flags & CLONE_NEWIPC) && prepare_ipc_ns(pid))
     168                 :            :                 return -1;
     169 [ +  + ][ +  - ]:        355 :         if ((clone_flags & CLONE_NEWNS)  && prepare_mnt_ns(pid))
     170                 :            :                 return -1;
     171                 :            : 
     172                 :            :         return 0;
     173                 :            : }
     174                 :            : 
     175                 :          0 : int try_show_namespaces(int ns_pid, struct cr_options *o)
     176                 :            : {
     177                 :            :         struct cr_fdset *fdset;
     178                 :            :         int i;
     179                 :            : 
     180                 :          0 :         fdset = cr_ns_fdset_open(ns_pid, O_SHOW);
     181         [ #  # ]:          0 :         if (!fdset)
     182                 :            :                 return -1;
     183                 :            : 
     184         [ #  # ]:          0 :         for (i = _CR_FD_NS_FROM + 1; i < _CR_FD_NS_TO; i++) {
     185                 :            :                 int fd;
     186                 :            : 
     187         [ #  # ]:          0 :                 if (!fdset_template[i].show)
     188                 :          0 :                         continue;
     189                 :            : 
     190                 :          0 :                 fd = fdset_fd(fdset, i);
     191         [ #  # ]:          0 :                 if (fd == -1)
     192                 :          0 :                         continue;
     193                 :            : 
     194                 :          0 :                 fdset_template[i].show(fdset_fd(fdset, i), o);
     195                 :            :         }
     196                 :            : 
     197                 :          0 :         close_cr_fdset(&fdset);
     198                 :            :         return 0;
     199                 :            : }

Generated by: LCOV version 1.9