14865ecf1SSerge E. Hallyn /* 24865ecf1SSerge E. Hallyn * Copyright (C) 2004 IBM Corporation 34865ecf1SSerge E. Hallyn * 44865ecf1SSerge E. Hallyn * Author: Serge Hallyn <serue@us.ibm.com> 54865ecf1SSerge E. Hallyn * 64865ecf1SSerge E. Hallyn * This program is free software; you can redistribute it and/or 74865ecf1SSerge E. Hallyn * modify it under the terms of the GNU General Public License as 84865ecf1SSerge E. Hallyn * published by the Free Software Foundation, version 2 of the 94865ecf1SSerge E. Hallyn * License. 104865ecf1SSerge E. Hallyn */ 114865ecf1SSerge E. Hallyn 124865ecf1SSerge E. Hallyn #include <linux/module.h> 134865ecf1SSerge E. Hallyn #include <linux/uts.h> 144865ecf1SSerge E. Hallyn #include <linux/utsname.h> 15467e9f4bSCedric Le Goater #include <linux/err.h> 161aeb272cSRobert P. J. Day #include <linux/slab.h> 1759607db3SSerge E. Hallyn #include <linux/user_namespace.h> 184865ecf1SSerge E. Hallyn 194c2a7e72SAlexey Dobriyan static struct uts_namespace *create_uts_ns(void) 204c2a7e72SAlexey Dobriyan { 214c2a7e72SAlexey Dobriyan struct uts_namespace *uts_ns; 224c2a7e72SAlexey Dobriyan 234c2a7e72SAlexey Dobriyan uts_ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL); 244c2a7e72SAlexey Dobriyan if (uts_ns) 254c2a7e72SAlexey Dobriyan kref_init(&uts_ns->kref); 264c2a7e72SAlexey Dobriyan return uts_ns; 274c2a7e72SAlexey Dobriyan } 284c2a7e72SAlexey Dobriyan 294865ecf1SSerge E. Hallyn /* 30071df104SSerge E. Hallyn * Clone a new ns copying an original utsname, setting refcount to 1 31071df104SSerge E. Hallyn * @old_ns: namespace to clone 32071df104SSerge E. Hallyn * Return NULL on error (failure to kmalloc), new ns otherwise 33071df104SSerge E. Hallyn */ 34*bb96a6f5SSerge E. Hallyn static struct uts_namespace *clone_uts_ns(struct task_struct *tsk, 35*bb96a6f5SSerge E. Hallyn struct uts_namespace *old_ns) 36071df104SSerge E. Hallyn { 37071df104SSerge E. Hallyn struct uts_namespace *ns; 38071df104SSerge E. Hallyn 394c2a7e72SAlexey Dobriyan ns = create_uts_ns(); 40467e9f4bSCedric Le Goater if (!ns) 41467e9f4bSCedric Le Goater return ERR_PTR(-ENOMEM); 42467e9f4bSCedric Le Goater 43efc63c4fSAlexey Dobriyan down_read(&uts_sem); 44071df104SSerge E. Hallyn memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); 45*bb96a6f5SSerge E. Hallyn ns->user_ns = get_user_ns(task_cred_xxx(tsk, user)->user_ns); 46efc63c4fSAlexey Dobriyan up_read(&uts_sem); 47071df104SSerge E. Hallyn return ns; 48071df104SSerge E. Hallyn } 49071df104SSerge E. Hallyn 50071df104SSerge E. Hallyn /* 514865ecf1SSerge E. Hallyn * Copy task tsk's utsname namespace, or clone it if flags 524865ecf1SSerge E. Hallyn * specifies CLONE_NEWUTS. In latter case, changes to the 534865ecf1SSerge E. Hallyn * utsname of this process won't be seen by parent, and vice 544865ecf1SSerge E. Hallyn * versa. 554865ecf1SSerge E. Hallyn */ 56*bb96a6f5SSerge E. Hallyn struct uts_namespace *copy_utsname(unsigned long flags, 57*bb96a6f5SSerge E. Hallyn struct task_struct *tsk) 584865ecf1SSerge E. Hallyn { 59*bb96a6f5SSerge E. Hallyn struct uts_namespace *old_ns = tsk->nsproxy->uts_ns; 60071df104SSerge E. Hallyn struct uts_namespace *new_ns; 614865ecf1SSerge E. Hallyn 62e3222c4eSBadari Pulavarty BUG_ON(!old_ns); 634865ecf1SSerge E. Hallyn get_uts_ns(old_ns); 644865ecf1SSerge E. Hallyn 65071df104SSerge E. Hallyn if (!(flags & CLONE_NEWUTS)) 66e3222c4eSBadari Pulavarty return old_ns; 67071df104SSerge E. Hallyn 68*bb96a6f5SSerge E. Hallyn new_ns = clone_uts_ns(tsk, old_ns); 69071df104SSerge E. Hallyn 70071df104SSerge E. Hallyn put_uts_ns(old_ns); 71e3222c4eSBadari Pulavarty return new_ns; 724865ecf1SSerge E. Hallyn } 734865ecf1SSerge E. Hallyn 744865ecf1SSerge E. Hallyn void free_uts_ns(struct kref *kref) 754865ecf1SSerge E. Hallyn { 764865ecf1SSerge E. Hallyn struct uts_namespace *ns; 774865ecf1SSerge E. Hallyn 784865ecf1SSerge E. Hallyn ns = container_of(kref, struct uts_namespace, kref); 7959607db3SSerge E. Hallyn put_user_ns(ns->user_ns); 804865ecf1SSerge E. Hallyn kfree(ns); 814865ecf1SSerge E. Hallyn } 82