1ab516013SSerge E. Hallyn /* 2ab516013SSerge E. Hallyn * Copyright (C) 2006 IBM Corporation 3ab516013SSerge E. Hallyn * 4ab516013SSerge E. Hallyn * Author: Serge Hallyn <serue@us.ibm.com> 5ab516013SSerge E. Hallyn * 6ab516013SSerge E. Hallyn * This program is free software; you can redistribute it and/or 7ab516013SSerge E. Hallyn * modify it under the terms of the GNU General Public License as 8ab516013SSerge E. Hallyn * published by the Free Software Foundation, version 2 of the 9ab516013SSerge E. Hallyn * License. 10ab516013SSerge E. Hallyn */ 11ab516013SSerge E. Hallyn 12ab516013SSerge E. Hallyn #include <linux/module.h> 13ab516013SSerge E. Hallyn #include <linux/version.h> 14ab516013SSerge E. Hallyn #include <linux/nsproxy.h> 150437eb59SSerge E. Hallyn #include <linux/init_task.h> 161651e14eSSerge E. Hallyn #include <linux/namespace.h> 174865ecf1SSerge E. Hallyn #include <linux/utsname.h> 180437eb59SSerge E. Hallyn 190437eb59SSerge E. Hallyn struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy); 20ab516013SSerge E. Hallyn 21ab516013SSerge E. Hallyn static inline void get_nsproxy(struct nsproxy *ns) 22ab516013SSerge E. Hallyn { 23ab516013SSerge E. Hallyn atomic_inc(&ns->count); 24ab516013SSerge E. Hallyn } 25ab516013SSerge E. Hallyn 26ab516013SSerge E. Hallyn void get_task_namespaces(struct task_struct *tsk) 27ab516013SSerge E. Hallyn { 28ab516013SSerge E. Hallyn struct nsproxy *ns = tsk->nsproxy; 29ab516013SSerge E. Hallyn if (ns) { 30ab516013SSerge E. Hallyn get_nsproxy(ns); 31ab516013SSerge E. Hallyn } 32ab516013SSerge E. Hallyn } 33ab516013SSerge E. Hallyn 34ab516013SSerge E. Hallyn /* 35ab516013SSerge E. Hallyn * creates a copy of "orig" with refcount 1. 36ab516013SSerge E. Hallyn * This does not grab references to the contained namespaces, 37ab516013SSerge E. Hallyn * so that needs to be done by dup_namespaces. 38ab516013SSerge E. Hallyn */ 39ab516013SSerge E. Hallyn static inline struct nsproxy *clone_namespaces(struct nsproxy *orig) 40ab516013SSerge E. Hallyn { 41ab516013SSerge E. Hallyn struct nsproxy *ns; 42ab516013SSerge E. Hallyn 43ab516013SSerge E. Hallyn ns = kmalloc(sizeof(struct nsproxy), GFP_KERNEL); 44ab516013SSerge E. Hallyn if (ns) { 45ab516013SSerge E. Hallyn memcpy(ns, orig, sizeof(struct nsproxy)); 46ab516013SSerge E. Hallyn atomic_set(&ns->count, 1); 47ab516013SSerge E. Hallyn } 48ab516013SSerge E. Hallyn return ns; 49ab516013SSerge E. Hallyn } 50ab516013SSerge E. Hallyn 51ab516013SSerge E. Hallyn /* 52ab516013SSerge E. Hallyn * copies the nsproxy, setting refcount to 1, and grabbing a 53ab516013SSerge E. Hallyn * reference to all contained namespaces. Called from 54ab516013SSerge E. Hallyn * sys_unshare() 55ab516013SSerge E. Hallyn */ 56ab516013SSerge E. Hallyn struct nsproxy *dup_namespaces(struct nsproxy *orig) 57ab516013SSerge E. Hallyn { 58ab516013SSerge E. Hallyn struct nsproxy *ns = clone_namespaces(orig); 59ab516013SSerge E. Hallyn 601651e14eSSerge E. Hallyn if (ns) { 611651e14eSSerge E. Hallyn if (ns->namespace) 621651e14eSSerge E. Hallyn get_namespace(ns->namespace); 634865ecf1SSerge E. Hallyn if (ns->uts_ns) 644865ecf1SSerge E. Hallyn get_uts_ns(ns->uts_ns); 651651e14eSSerge E. Hallyn } 661651e14eSSerge E. Hallyn 67ab516013SSerge E. Hallyn return ns; 68ab516013SSerge E. Hallyn } 69ab516013SSerge E. Hallyn 70ab516013SSerge E. Hallyn /* 71ab516013SSerge E. Hallyn * called from clone. This now handles copy for nsproxy and all 72ab516013SSerge E. Hallyn * namespaces therein. 73ab516013SSerge E. Hallyn */ 74ab516013SSerge E. Hallyn int copy_namespaces(int flags, struct task_struct *tsk) 75ab516013SSerge E. Hallyn { 76ab516013SSerge E. Hallyn struct nsproxy *old_ns = tsk->nsproxy; 771651e14eSSerge E. Hallyn struct nsproxy *new_ns; 781651e14eSSerge E. Hallyn int err = 0; 79ab516013SSerge E. Hallyn 80ab516013SSerge E. Hallyn if (!old_ns) 81ab516013SSerge E. Hallyn return 0; 82ab516013SSerge E. Hallyn 83ab516013SSerge E. Hallyn get_nsproxy(old_ns); 84ab516013SSerge E. Hallyn 851651e14eSSerge E. Hallyn if (!(flags & CLONE_NEWNS)) 86ab516013SSerge E. Hallyn return 0; 871651e14eSSerge E. Hallyn 881651e14eSSerge E. Hallyn new_ns = clone_namespaces(old_ns); 891651e14eSSerge E. Hallyn if (!new_ns) { 901651e14eSSerge E. Hallyn err = -ENOMEM; 911651e14eSSerge E. Hallyn goto out; 921651e14eSSerge E. Hallyn } 931651e14eSSerge E. Hallyn 941651e14eSSerge E. Hallyn tsk->nsproxy = new_ns; 951651e14eSSerge E. Hallyn 961651e14eSSerge E. Hallyn err = copy_namespace(flags, tsk); 971651e14eSSerge E. Hallyn if (err) { 981651e14eSSerge E. Hallyn tsk->nsproxy = old_ns; 991651e14eSSerge E. Hallyn put_nsproxy(new_ns); 1001651e14eSSerge E. Hallyn goto out; 1011651e14eSSerge E. Hallyn } 1021651e14eSSerge E. Hallyn 1034865ecf1SSerge E. Hallyn err = copy_utsname(flags, tsk); 1044865ecf1SSerge E. Hallyn if (err) { 1054865ecf1SSerge E. Hallyn if (new_ns->namespace) 1064865ecf1SSerge E. Hallyn put_namespace(new_ns->namespace); 1074865ecf1SSerge E. Hallyn tsk->nsproxy = old_ns; 1084865ecf1SSerge E. Hallyn put_nsproxy(new_ns); 1094865ecf1SSerge E. Hallyn goto out; 1104865ecf1SSerge E. Hallyn } 1114865ecf1SSerge E. Hallyn 1121651e14eSSerge E. Hallyn out: 1131651e14eSSerge E. Hallyn put_nsproxy(old_ns); 1141651e14eSSerge E. Hallyn return err; 115ab516013SSerge E. Hallyn } 116ab516013SSerge E. Hallyn 117ab516013SSerge E. Hallyn void free_nsproxy(struct nsproxy *ns) 118ab516013SSerge E. Hallyn { 1191651e14eSSerge E. Hallyn if (ns->namespace) 1201651e14eSSerge E. Hallyn put_namespace(ns->namespace); 1214865ecf1SSerge E. Hallyn if (ns->uts_ns) 1224865ecf1SSerge E. Hallyn put_uts_ns(ns->uts_ns); 123ab516013SSerge E. Hallyn kfree(ns); 124ab516013SSerge E. Hallyn } 125