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> 154865ecf1SSerge E. Hallyn #include <linux/version.h> 16467e9f4bSCedric Le Goater #include <linux/err.h> 17*1aeb272cSRobert P. J. Day #include <linux/slab.h> 184865ecf1SSerge E. Hallyn 194865ecf1SSerge E. Hallyn /* 20071df104SSerge E. Hallyn * Clone a new ns copying an original utsname, setting refcount to 1 21071df104SSerge E. Hallyn * @old_ns: namespace to clone 22071df104SSerge E. Hallyn * Return NULL on error (failure to kmalloc), new ns otherwise 23071df104SSerge E. Hallyn */ 24071df104SSerge E. Hallyn static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns) 25071df104SSerge E. Hallyn { 26071df104SSerge E. Hallyn struct uts_namespace *ns; 27071df104SSerge E. Hallyn 28071df104SSerge E. Hallyn ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL); 29467e9f4bSCedric Le Goater if (!ns) 30467e9f4bSCedric Le Goater return ERR_PTR(-ENOMEM); 31467e9f4bSCedric Le Goater 32efc63c4fSAlexey Dobriyan down_read(&uts_sem); 33071df104SSerge E. Hallyn memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); 34efc63c4fSAlexey Dobriyan up_read(&uts_sem); 35071df104SSerge E. Hallyn kref_init(&ns->kref); 36071df104SSerge E. Hallyn return ns; 37071df104SSerge E. Hallyn } 38071df104SSerge E. Hallyn 39071df104SSerge E. Hallyn /* 404865ecf1SSerge E. Hallyn * Copy task tsk's utsname namespace, or clone it if flags 414865ecf1SSerge E. Hallyn * specifies CLONE_NEWUTS. In latter case, changes to the 424865ecf1SSerge E. Hallyn * utsname of this process won't be seen by parent, and vice 434865ecf1SSerge E. Hallyn * versa. 444865ecf1SSerge E. Hallyn */ 45213dd266SEric W. Biederman struct uts_namespace *copy_utsname(unsigned long flags, struct uts_namespace *old_ns) 464865ecf1SSerge E. Hallyn { 47071df104SSerge E. Hallyn struct uts_namespace *new_ns; 484865ecf1SSerge E. Hallyn 49e3222c4eSBadari Pulavarty BUG_ON(!old_ns); 504865ecf1SSerge E. Hallyn get_uts_ns(old_ns); 514865ecf1SSerge E. Hallyn 52071df104SSerge E. Hallyn if (!(flags & CLONE_NEWUTS)) 53e3222c4eSBadari Pulavarty return old_ns; 54071df104SSerge E. Hallyn 55071df104SSerge E. Hallyn new_ns = clone_uts_ns(old_ns); 56071df104SSerge E. Hallyn 57071df104SSerge E. Hallyn put_uts_ns(old_ns); 58e3222c4eSBadari Pulavarty return new_ns; 594865ecf1SSerge E. Hallyn } 604865ecf1SSerge E. Hallyn 614865ecf1SSerge E. Hallyn void free_uts_ns(struct kref *kref) 624865ecf1SSerge E. Hallyn { 634865ecf1SSerge E. Hallyn struct uts_namespace *ns; 644865ecf1SSerge E. Hallyn 654865ecf1SSerge E. Hallyn ns = container_of(kref, struct uts_namespace, kref); 664865ecf1SSerge E. Hallyn kfree(ns); 674865ecf1SSerge E. Hallyn } 68