LCOV - code coverage report
Current view: top level - kernel - nsproxy.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 63 152 41.4 %
Date: 2022-04-01 14:17:54 Functions: 7 11 63.6 %
Branches: 19 76 25.0 %

           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/time_namespace.h>
      22                 :            : #include <linux/proc_ns.h>
      23                 :            : #include <linux/file.h>
      24                 :            : #include <linux/syscalls.h>
      25                 :            : #include <linux/cgroup.h>
      26                 :            : #include <linux/perf_event.h>
      27                 :            : 
      28                 :            : static struct kmem_cache *nsproxy_cachep;
      29                 :            : 
      30                 :            : struct nsproxy init_nsproxy = {
      31                 :            :         .count                  = ATOMIC_INIT(1),
      32                 :            :         .uts_ns                 = &init_uts_ns,
      33                 :            : #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
      34                 :            :         .ipc_ns                 = &init_ipc_ns,
      35                 :            : #endif
      36                 :            :         .mnt_ns                 = NULL,
      37                 :            :         .pid_ns_for_children    = &init_pid_ns,
      38                 :            : #ifdef CONFIG_NET
      39                 :            :         .net_ns                 = &init_net,
      40                 :            : #endif
      41                 :            : #ifdef CONFIG_CGROUPS
      42                 :            :         .cgroup_ns              = &init_cgroup_ns,
      43                 :            : #endif
      44                 :            : #ifdef CONFIG_TIME_NS
      45                 :            :         .time_ns                = &init_time_ns,
      46                 :            :         .time_ns_for_children   = &init_time_ns,
      47                 :            : #endif
      48                 :            : };
      49                 :            : 
      50                 :         33 : static inline struct nsproxy *create_nsproxy(void)
      51                 :            : {
      52                 :         33 :         struct nsproxy *nsproxy;
      53                 :            : 
      54                 :         33 :         nsproxy = kmem_cache_alloc(nsproxy_cachep, GFP_KERNEL);
      55         [ +  - ]:         33 :         if (nsproxy)
      56                 :         33 :                 atomic_set(&nsproxy->count, 1);
      57                 :         33 :         return nsproxy;
      58                 :            : }
      59                 :            : 
      60                 :            : /*
      61                 :            :  * Create new nsproxy and all of its the associated namespaces.
      62                 :            :  * Return the newly created nsproxy.  Do not attach this to the task,
      63                 :            :  * leave it to the caller to do proper locking and attach it to task.
      64                 :            :  */
      65                 :         33 : static struct nsproxy *create_new_namespaces(unsigned long flags,
      66                 :            :         struct task_struct *tsk, struct user_namespace *user_ns,
      67                 :            :         struct fs_struct *new_fs)
      68                 :            : {
      69                 :         33 :         struct nsproxy *new_nsp;
      70                 :         33 :         int err;
      71                 :            : 
      72                 :         33 :         new_nsp = create_nsproxy();
      73         [ +  - ]:         33 :         if (!new_nsp)
      74                 :            :                 return ERR_PTR(-ENOMEM);
      75                 :            : 
      76                 :         33 :         new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, user_ns, new_fs);
      77         [ -  + ]:         33 :         if (IS_ERR(new_nsp->mnt_ns)) {
      78                 :          0 :                 err = PTR_ERR(new_nsp->mnt_ns);
      79                 :          0 :                 goto out_ns;
      80                 :            :         }
      81                 :            : 
      82                 :         33 :         new_nsp->uts_ns = copy_utsname(flags, user_ns, tsk->nsproxy->uts_ns);
      83         [ -  + ]:         33 :         if (IS_ERR(new_nsp->uts_ns)) {
      84                 :          0 :                 err = PTR_ERR(new_nsp->uts_ns);
      85                 :          0 :                 goto out_uts;
      86                 :            :         }
      87                 :            : 
      88                 :         33 :         new_nsp->ipc_ns = copy_ipcs(flags, user_ns, tsk->nsproxy->ipc_ns);
      89         [ -  + ]:         33 :         if (IS_ERR(new_nsp->ipc_ns)) {
      90                 :          0 :                 err = PTR_ERR(new_nsp->ipc_ns);
      91                 :          0 :                 goto out_ipc;
      92                 :            :         }
      93                 :            : 
      94                 :         66 :         new_nsp->pid_ns_for_children =
      95                 :         33 :                 copy_pid_ns(flags, user_ns, tsk->nsproxy->pid_ns_for_children);
      96         [ -  + ]:         33 :         if (IS_ERR(new_nsp->pid_ns_for_children)) {
      97                 :          0 :                 err = PTR_ERR(new_nsp->pid_ns_for_children);
      98                 :          0 :                 goto out_pid;
      99                 :            :         }
     100                 :            : 
     101                 :         66 :         new_nsp->cgroup_ns = copy_cgroup_ns(flags, user_ns,
     102                 :         33 :                                             tsk->nsproxy->cgroup_ns);
     103         [ -  + ]:         33 :         if (IS_ERR(new_nsp->cgroup_ns)) {
     104                 :          0 :                 err = PTR_ERR(new_nsp->cgroup_ns);
     105                 :          0 :                 goto out_cgroup;
     106                 :            :         }
     107                 :            : 
     108                 :         33 :         new_nsp->net_ns = copy_net_ns(flags, user_ns, tsk->nsproxy->net_ns);
     109         [ -  + ]:         33 :         if (IS_ERR(new_nsp->net_ns)) {
     110                 :          0 :                 err = PTR_ERR(new_nsp->net_ns);
     111                 :          0 :                 goto out_net;
     112                 :            :         }
     113                 :            : 
     114                 :         66 :         new_nsp->time_ns_for_children = copy_time_ns(flags, user_ns,
     115                 :         33 :                                         tsk->nsproxy->time_ns_for_children);
     116         [ -  + ]:         33 :         if (IS_ERR(new_nsp->time_ns_for_children)) {
     117                 :          0 :                 err = PTR_ERR(new_nsp->time_ns_for_children);
     118                 :          0 :                 goto out_time;
     119                 :            :         }
     120                 :         33 :         new_nsp->time_ns = get_time_ns(tsk->nsproxy->time_ns);
     121                 :            : 
     122                 :         33 :         return new_nsp;
     123                 :            : 
     124                 :            : out_time:
     125                 :          0 :         put_net(new_nsp->net_ns);
     126                 :          0 : out_net:
     127                 :          0 :         put_cgroup_ns(new_nsp->cgroup_ns);
     128                 :          0 : out_cgroup:
     129         [ #  # ]:          0 :         if (new_nsp->pid_ns_for_children)
     130                 :          0 :                 put_pid_ns(new_nsp->pid_ns_for_children);
     131                 :          0 : out_pid:
     132         [ #  # ]:          0 :         if (new_nsp->ipc_ns)
     133                 :          0 :                 put_ipc_ns(new_nsp->ipc_ns);
     134                 :          0 : out_ipc:
     135         [ #  # ]:          0 :         if (new_nsp->uts_ns)
     136                 :          0 :                 put_uts_ns(new_nsp->uts_ns);
     137                 :          0 : out_uts:
     138         [ #  # ]:          0 :         if (new_nsp->mnt_ns)
     139                 :          0 :                 put_mnt_ns(new_nsp->mnt_ns);
     140                 :          0 : out_ns:
     141                 :          0 :         kmem_cache_free(nsproxy_cachep, new_nsp);
     142                 :          0 :         return ERR_PTR(err);
     143                 :            : }
     144                 :            : 
     145                 :            : /*
     146                 :            :  * called from clone.  This now handles copy for nsproxy and all
     147                 :            :  * namespaces therein.
     148                 :            :  */
     149                 :       5621 : int copy_namespaces(unsigned long flags, struct task_struct *tsk)
     150                 :            : {
     151                 :       5621 :         struct nsproxy *old_ns = tsk->nsproxy;
     152                 :       5621 :         struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
     153                 :       5621 :         struct nsproxy *new_ns;
     154                 :       5621 :         int ret;
     155                 :            : 
     156         [ +  - ]:       5621 :         if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
     157                 :            :                               CLONE_NEWPID | CLONE_NEWNET |
     158                 :            :                               CLONE_NEWCGROUP | CLONE_NEWTIME)))) {
     159         [ +  - ]:       5621 :                 if (likely(old_ns->time_ns_for_children == old_ns->time_ns)) {
     160                 :       5621 :                         get_nsproxy(old_ns);
     161                 :       5621 :                         return 0;
     162                 :            :                 }
     163         [ #  # ]:          0 :         } else if (!ns_capable(user_ns, CAP_SYS_ADMIN))
     164                 :            :                 return -EPERM;
     165                 :            : 
     166                 :            :         /*
     167                 :            :          * CLONE_NEWIPC must detach from the undolist: after switching
     168                 :            :          * to a new ipc namespace, the semaphore arrays from the old
     169                 :            :          * namespace are unreachable.  In clone parlance, CLONE_SYSVSEM
     170                 :            :          * means share undolist with parent, so we must forbid using
     171                 :            :          * it along with CLONE_NEWIPC.
     172                 :            :          */
     173         [ #  # ]:          0 :         if ((flags & (CLONE_NEWIPC | CLONE_SYSVSEM)) ==
     174                 :            :                 (CLONE_NEWIPC | CLONE_SYSVSEM)) 
     175                 :            :                 return -EINVAL;
     176                 :            : 
     177                 :          0 :         new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs);
     178         [ #  # ]:          0 :         if (IS_ERR(new_ns))
     179                 :          0 :                 return  PTR_ERR(new_ns);
     180                 :            : 
     181                 :          0 :         ret = timens_on_fork(new_ns, tsk);
     182         [ #  # ]:          0 :         if (ret) {
     183                 :          0 :                 free_nsproxy(new_ns);
     184                 :          0 :                 return ret;
     185                 :            :         }
     186                 :            : 
     187                 :          0 :         tsk->nsproxy = new_ns;
     188                 :          0 :         return 0;
     189                 :            : }
     190                 :            : 
     191                 :          0 : void free_nsproxy(struct nsproxy *ns)
     192                 :            : {
     193         [ #  # ]:          0 :         if (ns->mnt_ns)
     194                 :          0 :                 put_mnt_ns(ns->mnt_ns);
     195         [ #  # ]:          0 :         if (ns->uts_ns)
     196                 :          0 :                 put_uts_ns(ns->uts_ns);
     197         [ #  # ]:          0 :         if (ns->ipc_ns)
     198                 :          0 :                 put_ipc_ns(ns->ipc_ns);
     199         [ #  # ]:          0 :         if (ns->pid_ns_for_children)
     200                 :          0 :                 put_pid_ns(ns->pid_ns_for_children);
     201         [ #  # ]:          0 :         if (ns->time_ns)
     202                 :          0 :                 put_time_ns(ns->time_ns);
     203         [ #  # ]:          0 :         if (ns->time_ns_for_children)
     204                 :          0 :                 put_time_ns(ns->time_ns_for_children);
     205                 :          0 :         put_cgroup_ns(ns->cgroup_ns);
     206                 :          0 :         put_net(ns->net_ns);
     207                 :          0 :         kmem_cache_free(nsproxy_cachep, ns);
     208                 :          0 : }
     209                 :            : 
     210                 :            : /*
     211                 :            :  * Called from unshare. Unshare all the namespaces part of nsproxy.
     212                 :            :  * On success, returns the new nsproxy.
     213                 :            :  */
     214                 :         33 : int unshare_nsproxy_namespaces(unsigned long unshare_flags,
     215                 :            :         struct nsproxy **new_nsp, struct cred *new_cred, struct fs_struct *new_fs)
     216                 :            : {
     217                 :         33 :         struct user_namespace *user_ns;
     218                 :         33 :         int err = 0;
     219                 :            : 
     220         [ +  - ]:         33 :         if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
     221                 :            :                                CLONE_NEWNET | CLONE_NEWPID | CLONE_NEWCGROUP |
     222                 :            :                                CLONE_NEWTIME)))
     223                 :            :                 return 0;
     224                 :            : 
     225         [ -  + ]:         33 :         user_ns = new_cred ? new_cred->user_ns : current_user_ns();
     226         [ +  - ]:         33 :         if (!ns_capable(user_ns, CAP_SYS_ADMIN))
     227                 :            :                 return -EPERM;
     228                 :            : 
     229         [ +  + ]:         33 :         *new_nsp = create_new_namespaces(unshare_flags, current, user_ns,
     230                 :            :                                          new_fs ? new_fs : current->fs);
     231         [ +  - ]:         33 :         if (IS_ERR(*new_nsp)) {
     232                 :          0 :                 err = PTR_ERR(*new_nsp);
     233                 :          0 :                 goto out;
     234                 :            :         }
     235                 :            : 
     236                 :         33 : out:
     237                 :            :         return err;
     238                 :            : }
     239                 :            : 
     240                 :       4851 : void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
     241                 :            : {
     242                 :       4851 :         struct nsproxy *ns;
     243                 :            : 
     244                 :       4851 :         might_sleep();
     245                 :            : 
     246                 :       4851 :         task_lock(p);
     247                 :       4851 :         ns = p->nsproxy;
     248                 :       4851 :         p->nsproxy = new;
     249                 :       4851 :         task_unlock(p);
     250                 :            : 
     251   [ +  -  -  + ]:       4851 :         if (ns && atomic_dec_and_test(&ns->count))
     252                 :          0 :                 free_nsproxy(ns);
     253                 :       4851 : }
     254                 :            : 
     255                 :       4818 : void exit_task_namespaces(struct task_struct *p)
     256                 :            : {
     257                 :       4818 :         switch_task_namespaces(p, NULL);
     258                 :       4818 : }
     259                 :            : 
     260                 :          0 : SYSCALL_DEFINE2(setns, int, fd, int, nstype)
     261                 :            : {
     262                 :          0 :         struct task_struct *tsk = current;
     263                 :          0 :         struct nsproxy *new_nsproxy;
     264                 :          0 :         struct file *file;
     265                 :          0 :         struct ns_common *ns;
     266                 :          0 :         int err;
     267                 :            : 
     268                 :          0 :         file = proc_ns_fget(fd);
     269         [ #  # ]:          0 :         if (IS_ERR(file))
     270                 :          0 :                 return PTR_ERR(file);
     271                 :            : 
     272                 :          0 :         err = -EINVAL;
     273         [ #  # ]:          0 :         ns = get_proc_ns(file_inode(file));
     274   [ #  #  #  # ]:          0 :         if (nstype && (ns->ops->type != nstype))
     275                 :          0 :                 goto out;
     276                 :            : 
     277                 :          0 :         new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs);
     278         [ #  # ]:          0 :         if (IS_ERR(new_nsproxy)) {
     279                 :          0 :                 err = PTR_ERR(new_nsproxy);
     280                 :          0 :                 goto out;
     281                 :            :         }
     282                 :            : 
     283                 :          0 :         err = ns->ops->install(new_nsproxy, ns);
     284         [ #  # ]:          0 :         if (err) {
     285                 :          0 :                 free_nsproxy(new_nsproxy);
     286                 :          0 :                 goto out;
     287                 :            :         }
     288                 :          0 :         switch_task_namespaces(tsk, new_nsproxy);
     289                 :            : 
     290                 :          0 :         perf_event_namespaces(tsk);
     291                 :          0 : out:
     292                 :          0 :         fput(file);
     293                 :          0 :         return err;
     294                 :            : }
     295                 :            : 
     296                 :         11 : int __init nsproxy_cache_init(void)
     297                 :            : {
     298                 :         11 :         nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);
     299                 :         11 :         return 0;
     300                 :            : }

Generated by: LCOV version 1.14