1 /* 2 * Copyright (C) 2004 IBM Corporation 3 * 4 * Author: Serge Hallyn <serue@us.ibm.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation, version 2 of the 9 * License. 10 */ 11 12 #include <linux/module.h> 13 #include <linux/uts.h> 14 #include <linux/utsname.h> 15 #include <linux/version.h> 16 17 /* 18 * Clone a new ns copying an original utsname, setting refcount to 1 19 * @old_ns: namespace to clone 20 * Return NULL on error (failure to kmalloc), new ns otherwise 21 */ 22 static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns) 23 { 24 struct uts_namespace *ns; 25 26 ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL); 27 if (ns) { 28 memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); 29 kref_init(&ns->kref); 30 } 31 return ns; 32 } 33 34 /* 35 * unshare the current process' utsname namespace. 36 * called only in sys_unshare() 37 */ 38 int unshare_utsname(unsigned long unshare_flags, struct uts_namespace **new_uts) 39 { 40 if (unshare_flags & CLONE_NEWUTS) { 41 if (!capable(CAP_SYS_ADMIN)) 42 return -EPERM; 43 44 *new_uts = clone_uts_ns(current->nsproxy->uts_ns); 45 if (!*new_uts) 46 return -ENOMEM; 47 } 48 49 return 0; 50 } 51 52 /* 53 * Copy task tsk's utsname namespace, or clone it if flags 54 * specifies CLONE_NEWUTS. In latter case, changes to the 55 * utsname of this process won't be seen by parent, and vice 56 * versa. 57 */ 58 int copy_utsname(int flags, struct task_struct *tsk) 59 { 60 struct uts_namespace *old_ns = tsk->nsproxy->uts_ns; 61 struct uts_namespace *new_ns; 62 int err = 0; 63 64 if (!old_ns) 65 return 0; 66 67 get_uts_ns(old_ns); 68 69 if (!(flags & CLONE_NEWUTS)) 70 return 0; 71 72 if (!capable(CAP_SYS_ADMIN)) { 73 err = -EPERM; 74 goto out; 75 } 76 77 new_ns = clone_uts_ns(old_ns); 78 if (!new_ns) { 79 err = -ENOMEM; 80 goto out; 81 } 82 tsk->nsproxy->uts_ns = new_ns; 83 84 out: 85 put_uts_ns(old_ns); 86 return err; 87 } 88 89 void free_uts_ns(struct kref *kref) 90 { 91 struct uts_namespace *ns; 92 93 ns = container_of(kref, struct uts_namespace, kref); 94 kfree(ns); 95 } 96