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> 174865ecf1SSerge E. Hallyn 18*4c2a7e72SAlexey Dobriyan static struct uts_namespace *create_uts_ns(void) 19*4c2a7e72SAlexey Dobriyan { 20*4c2a7e72SAlexey Dobriyan struct uts_namespace *uts_ns; 21*4c2a7e72SAlexey Dobriyan 22*4c2a7e72SAlexey Dobriyan uts_ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL); 23*4c2a7e72SAlexey Dobriyan if (uts_ns) 24*4c2a7e72SAlexey Dobriyan kref_init(&uts_ns->kref); 25*4c2a7e72SAlexey Dobriyan return uts_ns; 26*4c2a7e72SAlexey Dobriyan } 27*4c2a7e72SAlexey Dobriyan 284865ecf1SSerge E. Hallyn /* 29071df104SSerge E. Hallyn * Clone a new ns copying an original utsname, setting refcount to 1 30071df104SSerge E. Hallyn * @old_ns: namespace to clone 31071df104SSerge E. Hallyn * Return NULL on error (failure to kmalloc), new ns otherwise 32071df104SSerge E. Hallyn */ 33071df104SSerge E. Hallyn static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns) 34071df104SSerge E. Hallyn { 35071df104SSerge E. Hallyn struct uts_namespace *ns; 36071df104SSerge E. Hallyn 37*4c2a7e72SAlexey Dobriyan ns = create_uts_ns(); 38467e9f4bSCedric Le Goater if (!ns) 39467e9f4bSCedric Le Goater return ERR_PTR(-ENOMEM); 40467e9f4bSCedric Le Goater 41efc63c4fSAlexey Dobriyan down_read(&uts_sem); 42071df104SSerge E. Hallyn memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); 43efc63c4fSAlexey Dobriyan up_read(&uts_sem); 44071df104SSerge E. Hallyn return ns; 45071df104SSerge E. Hallyn } 46071df104SSerge E. Hallyn 47071df104SSerge E. Hallyn /* 484865ecf1SSerge E. Hallyn * Copy task tsk's utsname namespace, or clone it if flags 494865ecf1SSerge E. Hallyn * specifies CLONE_NEWUTS. In latter case, changes to the 504865ecf1SSerge E. Hallyn * utsname of this process won't be seen by parent, and vice 514865ecf1SSerge E. Hallyn * versa. 524865ecf1SSerge E. Hallyn */ 53213dd266SEric W. Biederman struct uts_namespace *copy_utsname(unsigned long flags, struct uts_namespace *old_ns) 544865ecf1SSerge E. Hallyn { 55071df104SSerge E. Hallyn struct uts_namespace *new_ns; 564865ecf1SSerge E. Hallyn 57e3222c4eSBadari Pulavarty BUG_ON(!old_ns); 584865ecf1SSerge E. Hallyn get_uts_ns(old_ns); 594865ecf1SSerge E. Hallyn 60071df104SSerge E. Hallyn if (!(flags & CLONE_NEWUTS)) 61e3222c4eSBadari Pulavarty return old_ns; 62071df104SSerge E. Hallyn 63071df104SSerge E. Hallyn new_ns = clone_uts_ns(old_ns); 64071df104SSerge E. Hallyn 65071df104SSerge E. Hallyn put_uts_ns(old_ns); 66e3222c4eSBadari Pulavarty return new_ns; 674865ecf1SSerge E. Hallyn } 684865ecf1SSerge E. Hallyn 694865ecf1SSerge E. Hallyn void free_uts_ns(struct kref *kref) 704865ecf1SSerge E. Hallyn { 714865ecf1SSerge E. Hallyn struct uts_namespace *ns; 724865ecf1SSerge E. Hallyn 734865ecf1SSerge E. Hallyn ns = container_of(kref, struct uts_namespace, kref); 744865ecf1SSerge E. Hallyn kfree(ns); 754865ecf1SSerge E. Hallyn } 76