LCOV - code coverage report
Current view: top level - kernel - nsproxy.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 58 99 58.6 %
Date: 2020-09-30 20:25:40 Functions: 8 10 80.0 %
Branches: 23 64 35.9 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  *  Copyright (C) 2006 IBM Corporation
       4                 :            :  *
       5                 :            :  *  Author: Serge Hallyn <serue@us.ibm.com>
       6                 :            :  *
       7                 :            :  *  Jun 2006 - namespaces support
       8                 :            :  *             OpenVZ, SWsoft Inc.
       9                 :            :  *             Pavel Emelianov <xemul@openvz.org>
      10                 :            :  */
      11                 :            : 
      12                 :            : #include <linux/slab.h>
      13                 :            : #include <linux/export.h>
      14                 :            : #include <linux/nsproxy.h>
      15                 :            : #include <linux/init_task.h>
      16                 :            : #include <linux/mnt_namespace.h>
      17                 :            : #include <linux/utsname.h>
      18                 :            : #include <linux/pid_namespace.h>
      19                 :            : #include <net/net_namespace.h>
      20                 :            : #include <linux/ipc_namespace.h>
      21                 :            : #include <linux/proc_ns.h>
      22                 :            : #include <linux/file.h>
      23                 :            : #include <linux/syscalls.h>
      24                 :            : #include <linux/cgroup.h>
      25                 :            : #include <linux/perf_event.h>
      26                 :            : 
      27                 :            : static struct kmem_cache *nsproxy_cachep;
      28                 :            : 
      29                 :            : struct nsproxy init_nsproxy = {
      30                 :            :         .count                  = ATOMIC_INIT(1),
      31                 :            :         .uts_ns                 = &init_uts_ns,
      32                 :            : #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
      33                 :            :         .ipc_ns                 = &init_ipc_ns,
      34                 :            : #endif
      35                 :            :         .mnt_ns                 = NULL,
      36                 :            :         .pid_ns_for_children    = &init_pid_ns,
      37                 :            : #ifdef CONFIG_NET
      38                 :            :         .net_ns                 = &init_net,
      39                 :            : #endif
      40                 :            : #ifdef CONFIG_CGROUPS
      41                 :            :         .cgroup_ns              = &init_cgroup_ns,
      42                 :            : #endif
      43                 :            : };
      44                 :            : 
      45                 :        623 : static inline struct nsproxy *create_nsproxy(void)
      46                 :            : {
      47                 :            :         struct nsproxy *nsproxy;
      48                 :            : 
      49                 :        623 :         nsproxy = kmem_cache_alloc(nsproxy_cachep, GFP_KERNEL);
      50         [ +  - ]:        623 :         if (nsproxy)
      51                 :            :                 atomic_set(&nsproxy->count, 1);
      52                 :        623 :         return nsproxy;
      53                 :            : }
      54                 :            : 
      55                 :            : /*
      56                 :            :  * Create new nsproxy and all of its the associated namespaces.
      57                 :            :  * Return the newly created nsproxy.  Do not attach this to the task,
      58                 :            :  * leave it to the caller to do proper locking and attach it to task.
      59                 :            :  */
      60                 :        623 : static struct nsproxy *create_new_namespaces(unsigned long flags,
      61                 :            :         struct task_struct *tsk, struct user_namespace *user_ns,
      62                 :            :         struct fs_struct *new_fs)
      63                 :            : {
      64                 :            :         struct nsproxy *new_nsp;
      65                 :            :         int err;
      66                 :            : 
      67                 :        623 :         new_nsp = create_nsproxy();
      68         [ +  - ]:        623 :         if (!new_nsp)
      69                 :            :                 return ERR_PTR(-ENOMEM);
      70                 :            : 
      71                 :        623 :         new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, user_ns, new_fs);
      72         [ -  + ]:        623 :         if (IS_ERR(new_nsp->mnt_ns)) {
      73                 :            :                 err = PTR_ERR(new_nsp->mnt_ns);
      74                 :          0 :                 goto out_ns;
      75                 :            :         }
      76                 :            : 
      77                 :        623 :         new_nsp->uts_ns = copy_utsname(flags, user_ns, tsk->nsproxy->uts_ns);
      78         [ -  + ]:        623 :         if (IS_ERR(new_nsp->uts_ns)) {
      79                 :            :                 err = PTR_ERR(new_nsp->uts_ns);
      80                 :          0 :                 goto out_uts;
      81                 :            :         }
      82                 :            : 
      83                 :        623 :         new_nsp->ipc_ns = copy_ipcs(flags, user_ns, tsk->nsproxy->ipc_ns);
      84         [ -  + ]:        623 :         if (IS_ERR(new_nsp->ipc_ns)) {
      85                 :            :                 err = PTR_ERR(new_nsp->ipc_ns);
      86                 :          0 :                 goto out_ipc;
      87                 :            :         }
      88                 :            : 
      89                 :        623 :         new_nsp->pid_ns_for_children =
      90                 :        623 :                 copy_pid_ns(flags, user_ns, tsk->nsproxy->pid_ns_for_children);
      91         [ -  + ]:        623 :         if (IS_ERR(new_nsp->pid_ns_for_children)) {
      92                 :            :                 err = PTR_ERR(new_nsp->pid_ns_for_children);
      93                 :          0 :                 goto out_pid;
      94                 :            :         }
      95                 :            : 
      96                 :        623 :         new_nsp->cgroup_ns = copy_cgroup_ns(flags, user_ns,
      97                 :        623 :                                             tsk->nsproxy->cgroup_ns);
      98         [ -  + ]:        623 :         if (IS_ERR(new_nsp->cgroup_ns)) {
      99                 :            :                 err = PTR_ERR(new_nsp->cgroup_ns);
     100                 :          0 :                 goto out_cgroup;
     101                 :            :         }
     102                 :            : 
     103                 :        623 :         new_nsp->net_ns = copy_net_ns(flags, user_ns, tsk->nsproxy->net_ns);
     104         [ -  + ]:        623 :         if (IS_ERR(new_nsp->net_ns)) {
     105                 :            :                 err = PTR_ERR(new_nsp->net_ns);
     106                 :            :                 goto out_net;
     107                 :            :         }
     108                 :            : 
     109                 :            :         return new_nsp;
     110                 :            : 
     111                 :            : out_net:
     112                 :          0 :         put_cgroup_ns(new_nsp->cgroup_ns);
     113                 :            : out_cgroup:
     114         [ #  # ]:          0 :         if (new_nsp->pid_ns_for_children)
     115                 :          0 :                 put_pid_ns(new_nsp->pid_ns_for_children);
     116                 :            : out_pid:
     117         [ #  # ]:          0 :         if (new_nsp->ipc_ns)
     118                 :          0 :                 put_ipc_ns(new_nsp->ipc_ns);
     119                 :            : out_ipc:
     120         [ #  # ]:          0 :         if (new_nsp->uts_ns)
     121                 :            :                 put_uts_ns(new_nsp->uts_ns);
     122                 :            : out_uts:
     123         [ #  # ]:          0 :         if (new_nsp->mnt_ns)
     124                 :          0 :                 put_mnt_ns(new_nsp->mnt_ns);
     125                 :            : out_ns:
     126                 :          0 :         kmem_cache_free(nsproxy_cachep, new_nsp);
     127                 :          0 :         return ERR_PTR(err);
     128                 :            : }
     129                 :            : 
     130                 :            : /*
     131                 :            :  * called from clone.  This now handles copy for nsproxy and all
     132                 :            :  * namespaces therein.
     133                 :            :  */
     134                 :     210626 : int copy_namespaces(unsigned long flags, struct task_struct *tsk)
     135                 :            : {
     136                 :     210626 :         struct nsproxy *old_ns = tsk->nsproxy;
     137                 :     210591 :         struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
     138                 :            :         struct nsproxy *new_ns;
     139                 :            : 
     140         [ +  - ]:     210622 :         if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
     141                 :            :                               CLONE_NEWPID | CLONE_NEWNET |
     142                 :            :                               CLONE_NEWCGROUP)))) {
     143                 :            :                 get_nsproxy(old_ns);
     144                 :     210623 :                 return 0;
     145                 :            :         }
     146                 :            : 
     147         [ #  # ]:          0 :         if (!ns_capable(user_ns, CAP_SYS_ADMIN))
     148                 :            :                 return -EPERM;
     149                 :            : 
     150                 :            :         /*
     151                 :            :          * CLONE_NEWIPC must detach from the undolist: after switching
     152                 :            :          * to a new ipc namespace, the semaphore arrays from the old
     153                 :            :          * namespace are unreachable.  In clone parlance, CLONE_SYSVSEM
     154                 :            :          * means share undolist with parent, so we must forbid using
     155                 :            :          * it along with CLONE_NEWIPC.
     156                 :            :          */
     157         [ #  # ]:          0 :         if ((flags & (CLONE_NEWIPC | CLONE_SYSVSEM)) ==
     158                 :            :                 (CLONE_NEWIPC | CLONE_SYSVSEM)) 
     159                 :            :                 return -EINVAL;
     160                 :            : 
     161                 :          0 :         new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs);
     162         [ #  # ]:          0 :         if (IS_ERR(new_ns))
     163                 :          0 :                 return  PTR_ERR(new_ns);
     164                 :            : 
     165                 :          0 :         tsk->nsproxy = new_ns;
     166                 :          0 :         return 0;
     167                 :            : }
     168                 :            : 
     169                 :          2 : void free_nsproxy(struct nsproxy *ns)
     170                 :            : {
     171         [ +  - ]:          2 :         if (ns->mnt_ns)
     172                 :          2 :                 put_mnt_ns(ns->mnt_ns);
     173         [ +  - ]:          2 :         if (ns->uts_ns)
     174                 :            :                 put_uts_ns(ns->uts_ns);
     175         [ +  - ]:          2 :         if (ns->ipc_ns)
     176                 :          2 :                 put_ipc_ns(ns->ipc_ns);
     177         [ +  - ]:          2 :         if (ns->pid_ns_for_children)
     178                 :          2 :                 put_pid_ns(ns->pid_ns_for_children);
     179                 :          2 :         put_cgroup_ns(ns->cgroup_ns);
     180                 :          2 :         put_net(ns->net_ns);
     181                 :          2 :         kmem_cache_free(nsproxy_cachep, ns);
     182                 :          2 : }
     183                 :            : 
     184                 :            : /*
     185                 :            :  * Called from unshare. Unshare all the namespaces part of nsproxy.
     186                 :            :  * On success, returns the new nsproxy.
     187                 :            :  */
     188                 :        623 : int unshare_nsproxy_namespaces(unsigned long unshare_flags,
     189                 :            :         struct nsproxy **new_nsp, struct cred *new_cred, struct fs_struct *new_fs)
     190                 :            : {
     191                 :            :         struct user_namespace *user_ns;
     192                 :            :         int err = 0;
     193                 :            : 
     194         [ +  - ]:        623 :         if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
     195                 :            :                                CLONE_NEWNET | CLONE_NEWPID | CLONE_NEWCGROUP)))
     196                 :            :                 return 0;
     197                 :            : 
     198         [ -  + ]:       1246 :         user_ns = new_cred ? new_cred->user_ns : current_user_ns();
     199         [ +  - ]:        623 :         if (!ns_capable(user_ns, CAP_SYS_ADMIN))
     200                 :            :                 return -EPERM;
     201                 :            : 
     202         [ +  + ]:        623 :         *new_nsp = create_new_namespaces(unshare_flags, current, user_ns,
     203                 :            :                                          new_fs ? new_fs : current->fs);
     204         [ -  + ]:        623 :         if (IS_ERR(*new_nsp)) {
     205                 :            :                 err = PTR_ERR(*new_nsp);
     206                 :          0 :                 goto out;
     207                 :            :         }
     208                 :            : 
     209                 :            : out:
     210                 :        623 :         return err;
     211                 :            : }
     212                 :            : 
     213                 :     172597 : void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
     214                 :            : {
     215                 :            :         struct nsproxy *ns;
     216                 :            : 
     217                 :     172597 :         might_sleep();
     218                 :            : 
     219                 :            :         task_lock(p);
     220                 :     172483 :         ns = p->nsproxy;
     221                 :     172483 :         p->nsproxy = new;
     222                 :            :         task_unlock(p);
     223                 :            : 
     224   [ +  +  +  + ]:     345163 :         if (ns && atomic_dec_and_test(&ns->count))
     225                 :          2 :                 free_nsproxy(ns);
     226                 :     172745 : }
     227                 :            : 
     228                 :     171972 : void exit_task_namespaces(struct task_struct *p)
     229                 :            : {
     230                 :     171972 :         switch_task_namespaces(p, NULL);
     231                 :     171939 : }
     232                 :            : 
     233                 :          0 : SYSCALL_DEFINE2(setns, int, fd, int, nstype)
     234                 :            : {
     235                 :          0 :         struct task_struct *tsk = current;
     236                 :            :         struct nsproxy *new_nsproxy;
     237                 :            :         struct file *file;
     238                 :            :         struct ns_common *ns;
     239                 :            :         int err;
     240                 :            : 
     241                 :          0 :         file = proc_ns_fget(fd);
     242         [ #  # ]:          0 :         if (IS_ERR(file))
     243                 :          0 :                 return PTR_ERR(file);
     244                 :            : 
     245                 :            :         err = -EINVAL;
     246                 :          0 :         ns = get_proc_ns(file_inode(file));
     247   [ #  #  #  # ]:          0 :         if (nstype && (ns->ops->type != nstype))
     248                 :            :                 goto out;
     249                 :            : 
     250                 :          0 :         new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs);
     251         [ #  # ]:          0 :         if (IS_ERR(new_nsproxy)) {
     252                 :            :                 err = PTR_ERR(new_nsproxy);
     253                 :          0 :                 goto out;
     254                 :            :         }
     255                 :            : 
     256                 :          0 :         err = ns->ops->install(new_nsproxy, ns);
     257         [ #  # ]:          0 :         if (err) {
     258                 :          0 :                 free_nsproxy(new_nsproxy);
     259                 :          0 :                 goto out;
     260                 :            :         }
     261                 :          0 :         switch_task_namespaces(tsk, new_nsproxy);
     262                 :            : 
     263                 :          0 :         perf_event_namespaces(tsk);
     264                 :            : out:
     265                 :          0 :         fput(file);
     266                 :          0 :         return err;
     267                 :            : }
     268                 :            : 
     269                 :        207 : int __init nsproxy_cache_init(void)
     270                 :            : {
     271                 :        207 :         nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);
     272                 :        207 :         return 0;
     273                 :            : }

Generated by: LCOV version 1.14