1 /* 2 * AppArmor security module 3 * 4 * This file contains AppArmor policy manipulation functions 5 * 6 * Copyright (C) 1998-2008 Novell/SUSE 7 * Copyright 2009-2017 Canonical Ltd. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation, version 2 of the 12 * License. 13 * 14 * AppArmor policy namespaces, allow for different sets of policies 15 * to be loaded for tasks within the namespace. 16 */ 17 18 #include <linux/list.h> 19 #include <linux/mutex.h> 20 #include <linux/slab.h> 21 #include <linux/string.h> 22 23 #include "include/apparmor.h" 24 #include "include/context.h" 25 #include "include/policy_ns.h" 26 #include "include/policy.h" 27 28 /* root profile namespace */ 29 struct aa_ns *root_ns; 30 const char *aa_hidden_ns_name = "---"; 31 32 /** 33 * aa_ns_visible - test if @view is visible from @curr 34 * @curr: namespace to treat as the parent (NOT NULL) 35 * @view: namespace to test if visible from @curr (NOT NULL) 36 * @subns: whether view of a subns is allowed 37 * 38 * Returns: true if @view is visible from @curr else false 39 */ 40 bool aa_ns_visible(struct aa_ns *curr, struct aa_ns *view, bool subns) 41 { 42 if (curr == view) 43 return true; 44 45 if (!subns) 46 return false; 47 48 for ( ; view; view = view->parent) { 49 if (view->parent == curr) 50 return true; 51 } 52 53 return false; 54 } 55 56 /** 57 * aa_na_name - Find the ns name to display for @view from @curr 58 * @curr - current namespace (NOT NULL) 59 * @view - namespace attempting to view (NOT NULL) 60 * @subns - are subns visible 61 * 62 * Returns: name of @view visible from @curr 63 */ 64 const char *aa_ns_name(struct aa_ns *curr, struct aa_ns *view, bool subns) 65 { 66 /* if view == curr then the namespace name isn't displayed */ 67 if (curr == view) 68 return ""; 69 70 if (aa_ns_visible(curr, view, subns)) { 71 /* at this point if a ns is visible it is in a view ns 72 * thus the curr ns.hname is a prefix of its name. 73 * Only output the virtualized portion of the name 74 * Add + 2 to skip over // separating curr hname prefix 75 * from the visible tail of the views hname 76 */ 77 return view->base.hname + strlen(curr->base.hname) + 2; 78 } 79 80 return aa_hidden_ns_name; 81 } 82 83 /** 84 * alloc_ns - allocate, initialize and return a new namespace 85 * @prefix: parent namespace name (MAYBE NULL) 86 * @name: a preallocated name (NOT NULL) 87 * 88 * Returns: refcounted namespace or NULL on failure. 89 */ 90 static struct aa_ns *alloc_ns(const char *prefix, const char *name) 91 { 92 struct aa_ns *ns; 93 94 ns = kzalloc(sizeof(*ns), GFP_KERNEL); 95 AA_DEBUG("%s(%p)\n", __func__, ns); 96 if (!ns) 97 return NULL; 98 if (!aa_policy_init(&ns->base, prefix, name, GFP_KERNEL)) 99 goto fail_ns; 100 101 INIT_LIST_HEAD(&ns->sub_ns); 102 INIT_LIST_HEAD(&ns->rawdata_list); 103 mutex_init(&ns->lock); 104 105 /* released by aa_free_ns() */ 106 ns->unconfined = aa_alloc_profile("unconfined", GFP_KERNEL); 107 if (!ns->unconfined) 108 goto fail_unconfined; 109 110 ns->unconfined->flags = PFLAG_IX_ON_NAME_ERROR | 111 PFLAG_IMMUTABLE | PFLAG_NS_COUNT; 112 ns->unconfined->mode = APPARMOR_UNCONFINED; 113 114 /* ns and ns->unconfined share ns->unconfined refcount */ 115 ns->unconfined->ns = ns; 116 117 atomic_set(&ns->uniq_null, 0); 118 119 return ns; 120 121 fail_unconfined: 122 kzfree(ns->base.hname); 123 fail_ns: 124 kzfree(ns); 125 return NULL; 126 } 127 128 /** 129 * aa_free_ns - free a profile namespace 130 * @ns: the namespace to free (MAYBE NULL) 131 * 132 * Requires: All references to the namespace must have been put, if the 133 * namespace was referenced by a profile confining a task, 134 */ 135 void aa_free_ns(struct aa_ns *ns) 136 { 137 if (!ns) 138 return; 139 140 aa_policy_destroy(&ns->base); 141 aa_put_ns(ns->parent); 142 143 ns->unconfined->ns = NULL; 144 aa_free_profile(ns->unconfined); 145 kzfree(ns); 146 } 147 148 /** 149 * aa_findn_ns - look up a profile namespace on the namespace list 150 * @root: namespace to search in (NOT NULL) 151 * @name: name of namespace to find (NOT NULL) 152 * @n: length of @name 153 * 154 * Returns: a refcounted namespace on the list, or NULL if no namespace 155 * called @name exists. 156 * 157 * refcount released by caller 158 */ 159 struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n) 160 { 161 struct aa_ns *ns = NULL; 162 163 rcu_read_lock(); 164 ns = aa_get_ns(__aa_findn_ns(&root->sub_ns, name, n)); 165 rcu_read_unlock(); 166 167 return ns; 168 } 169 170 /** 171 * aa_find_ns - look up a profile namespace on the namespace list 172 * @root: namespace to search in (NOT NULL) 173 * @name: name of namespace to find (NOT NULL) 174 * 175 * Returns: a refcounted namespace on the list, or NULL if no namespace 176 * called @name exists. 177 * 178 * refcount released by caller 179 */ 180 struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name) 181 { 182 return aa_findn_ns(root, name, strlen(name)); 183 } 184 185 static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, 186 struct dentry *dir) 187 { 188 struct aa_ns *ns; 189 int error; 190 191 AA_BUG(!parent); 192 AA_BUG(!name); 193 AA_BUG(!mutex_is_locked(&parent->lock)); 194 195 ns = alloc_ns(parent->base.hname, name); 196 if (!ns) 197 return NULL; 198 mutex_lock(&ns->lock); 199 error = __aafs_ns_mkdir(ns, ns_subns_dir(parent), name); 200 if (error) { 201 AA_ERROR("Failed to create interface for ns %s\n", 202 ns->base.name); 203 mutex_unlock(&ns->lock); 204 aa_free_ns(ns); 205 return ERR_PTR(error); 206 } 207 ns->parent = aa_get_ns(parent); 208 ns->level = parent->level + 1; 209 list_add_rcu(&ns->base.list, &parent->sub_ns); 210 /* add list ref */ 211 aa_get_ns(ns); 212 mutex_unlock(&ns->lock); 213 214 return ns; 215 } 216 217 /** 218 * aa_create_ns - create an ns, fail if it already exists 219 * @parent: the parent of the namespace being created 220 * @name: the name of the namespace 221 * @dir: if not null the dir to put the ns entries in 222 * 223 * Returns: the a refcounted ns that has been add or an ERR_PTR 224 */ 225 struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name, 226 struct dentry *dir) 227 { 228 struct aa_ns *ns; 229 230 AA_BUG(!mutex_is_locked(&parent->lock)); 231 232 /* try and find the specified ns */ 233 /* released by caller */ 234 ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name)); 235 if (!ns) 236 ns = __aa_create_ns(parent, name, dir); 237 else 238 ns = ERR_PTR(-EEXIST); 239 240 /* return ref */ 241 return ns; 242 } 243 244 /** 245 * aa_prepare_ns - find an existing or create a new namespace of @name 246 * @parent: ns to treat as parent 247 * @name: the namespace to find or add (NOT NULL) 248 * 249 * Returns: refcounted namespace or PTR_ERR if failed to create one 250 */ 251 struct aa_ns *aa_prepare_ns(struct aa_ns *parent, const char *name) 252 { 253 struct aa_ns *ns; 254 255 mutex_lock(&parent->lock); 256 /* try and find the specified ns and if it doesn't exist create it */ 257 /* released by caller */ 258 ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name)); 259 if (!ns) 260 ns = __aa_create_ns(parent, name, NULL); 261 mutex_unlock(&parent->lock); 262 263 /* return ref */ 264 return ns; 265 } 266 267 static void __ns_list_release(struct list_head *head); 268 269 /** 270 * destroy_ns - remove everything contained by @ns 271 * @ns: namespace to have it contents removed (NOT NULL) 272 */ 273 static void destroy_ns(struct aa_ns *ns) 274 { 275 if (!ns) 276 return; 277 278 mutex_lock(&ns->lock); 279 /* release all profiles in this namespace */ 280 __aa_profile_list_release(&ns->base.profiles); 281 282 /* release all sub namespaces */ 283 __ns_list_release(&ns->sub_ns); 284 285 if (ns->parent) 286 __aa_update_proxy(ns->unconfined, ns->parent->unconfined); 287 __aafs_ns_rmdir(ns); 288 mutex_unlock(&ns->lock); 289 } 290 291 /** 292 * __aa_remove_ns - remove a namespace and all its children 293 * @ns: namespace to be removed (NOT NULL) 294 * 295 * Requires: ns->parent->lock be held and ns removed from parent. 296 */ 297 void __aa_remove_ns(struct aa_ns *ns) 298 { 299 /* remove ns from namespace list */ 300 list_del_rcu(&ns->base.list); 301 destroy_ns(ns); 302 aa_put_ns(ns); 303 } 304 305 /** 306 * __ns_list_release - remove all profile namespaces on the list put refs 307 * @head: list of profile namespaces (NOT NULL) 308 * 309 * Requires: namespace lock be held 310 */ 311 static void __ns_list_release(struct list_head *head) 312 { 313 struct aa_ns *ns, *tmp; 314 315 list_for_each_entry_safe(ns, tmp, head, base.list) 316 __aa_remove_ns(ns); 317 318 } 319 320 /** 321 * aa_alloc_root_ns - allocate the root profile namespace 322 * 323 * Returns: %0 on success else error 324 * 325 */ 326 int __init aa_alloc_root_ns(void) 327 { 328 /* released by aa_free_root_ns - used as list ref*/ 329 root_ns = alloc_ns(NULL, "root"); 330 if (!root_ns) 331 return -ENOMEM; 332 333 return 0; 334 } 335 336 /** 337 * aa_free_root_ns - free the root profile namespace 338 */ 339 void __init aa_free_root_ns(void) 340 { 341 struct aa_ns *ns = root_ns; 342 343 root_ns = NULL; 344 345 destroy_ns(ns); 346 aa_put_ns(ns); 347 } 348