162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AppArmor security module 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This file contains AppArmor policy manipulation functions 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 1998-2008 Novell/SUSE 862306a36Sopenharmony_ci * Copyright 2009-2017 Canonical Ltd. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * AppArmor policy namespaces, allow for different sets of policies 1162306a36Sopenharmony_ci * to be loaded for tasks within the namespace. 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/list.h> 1562306a36Sopenharmony_ci#include <linux/mutex.h> 1662306a36Sopenharmony_ci#include <linux/slab.h> 1762306a36Sopenharmony_ci#include <linux/string.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "include/apparmor.h" 2062306a36Sopenharmony_ci#include "include/cred.h" 2162306a36Sopenharmony_ci#include "include/policy_ns.h" 2262306a36Sopenharmony_ci#include "include/label.h" 2362306a36Sopenharmony_ci#include "include/policy.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* kernel label */ 2662306a36Sopenharmony_cistruct aa_label *kernel_t; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/* root profile namespace */ 2962306a36Sopenharmony_cistruct aa_ns *root_ns; 3062306a36Sopenharmony_ciconst char *aa_hidden_ns_name = "---"; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/** 3362306a36Sopenharmony_ci * aa_ns_visible - test if @view is visible from @curr 3462306a36Sopenharmony_ci * @curr: namespace to treat as the parent (NOT NULL) 3562306a36Sopenharmony_ci * @view: namespace to test if visible from @curr (NOT NULL) 3662306a36Sopenharmony_ci * @subns: whether view of a subns is allowed 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * Returns: true if @view is visible from @curr else false 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_cibool aa_ns_visible(struct aa_ns *curr, struct aa_ns *view, bool subns) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci if (curr == view) 4362306a36Sopenharmony_ci return true; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci if (!subns) 4662306a36Sopenharmony_ci return false; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci for ( ; view; view = view->parent) { 4962306a36Sopenharmony_ci if (view->parent == curr) 5062306a36Sopenharmony_ci return true; 5162306a36Sopenharmony_ci } 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci return false; 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/** 5762306a36Sopenharmony_ci * aa_ns_name - Find the ns name to display for @view from @curr 5862306a36Sopenharmony_ci * @curr: current namespace (NOT NULL) 5962306a36Sopenharmony_ci * @view: namespace attempting to view (NOT NULL) 6062306a36Sopenharmony_ci * @subns: are subns visible 6162306a36Sopenharmony_ci * 6262306a36Sopenharmony_ci * Returns: name of @view visible from @curr 6362306a36Sopenharmony_ci */ 6462306a36Sopenharmony_ciconst char *aa_ns_name(struct aa_ns *curr, struct aa_ns *view, bool subns) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci /* if view == curr then the namespace name isn't displayed */ 6762306a36Sopenharmony_ci if (curr == view) 6862306a36Sopenharmony_ci return ""; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci if (aa_ns_visible(curr, view, subns)) { 7162306a36Sopenharmony_ci /* at this point if a ns is visible it is in a view ns 7262306a36Sopenharmony_ci * thus the curr ns.hname is a prefix of its name. 7362306a36Sopenharmony_ci * Only output the virtualized portion of the name 7462306a36Sopenharmony_ci * Add + 2 to skip over // separating curr hname prefix 7562306a36Sopenharmony_ci * from the visible tail of the views hname 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_ci return view->base.hname + strlen(curr->base.hname) + 2; 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci return aa_hidden_ns_name; 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic struct aa_profile *alloc_unconfined(const char *name) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci struct aa_profile *profile; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci profile = aa_alloc_null(NULL, name, GFP_KERNEL); 8862306a36Sopenharmony_ci if (!profile) 8962306a36Sopenharmony_ci return NULL; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci profile->label.flags |= FLAG_IX_ON_NAME_ERROR | 9262306a36Sopenharmony_ci FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED; 9362306a36Sopenharmony_ci profile->mode = APPARMOR_UNCONFINED; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci return profile; 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/** 9962306a36Sopenharmony_ci * alloc_ns - allocate, initialize and return a new namespace 10062306a36Sopenharmony_ci * @prefix: parent namespace name (MAYBE NULL) 10162306a36Sopenharmony_ci * @name: a preallocated name (NOT NULL) 10262306a36Sopenharmony_ci * 10362306a36Sopenharmony_ci * Returns: refcounted namespace or NULL on failure. 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_cistatic struct aa_ns *alloc_ns(const char *prefix, const char *name) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci struct aa_ns *ns; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci ns = kzalloc(sizeof(*ns), GFP_KERNEL); 11062306a36Sopenharmony_ci AA_DEBUG("%s(%p)\n", __func__, ns); 11162306a36Sopenharmony_ci if (!ns) 11262306a36Sopenharmony_ci return NULL; 11362306a36Sopenharmony_ci if (!aa_policy_init(&ns->base, prefix, name, GFP_KERNEL)) 11462306a36Sopenharmony_ci goto fail_ns; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci INIT_LIST_HEAD(&ns->sub_ns); 11762306a36Sopenharmony_ci INIT_LIST_HEAD(&ns->rawdata_list); 11862306a36Sopenharmony_ci mutex_init(&ns->lock); 11962306a36Sopenharmony_ci init_waitqueue_head(&ns->wait); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci /* released by aa_free_ns() */ 12262306a36Sopenharmony_ci ns->unconfined = alloc_unconfined("unconfined"); 12362306a36Sopenharmony_ci if (!ns->unconfined) 12462306a36Sopenharmony_ci goto fail_unconfined; 12562306a36Sopenharmony_ci /* ns and ns->unconfined share ns->unconfined refcount */ 12662306a36Sopenharmony_ci ns->unconfined->ns = ns; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci atomic_set(&ns->uniq_null, 0); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci aa_labelset_init(&ns->labels); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci return ns; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cifail_unconfined: 13562306a36Sopenharmony_ci aa_policy_destroy(&ns->base); 13662306a36Sopenharmony_cifail_ns: 13762306a36Sopenharmony_ci kfree_sensitive(ns); 13862306a36Sopenharmony_ci return NULL; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/** 14262306a36Sopenharmony_ci * aa_free_ns - free a profile namespace 14362306a36Sopenharmony_ci * @ns: the namespace to free (MAYBE NULL) 14462306a36Sopenharmony_ci * 14562306a36Sopenharmony_ci * Requires: All references to the namespace must have been put, if the 14662306a36Sopenharmony_ci * namespace was referenced by a profile confining a task, 14762306a36Sopenharmony_ci */ 14862306a36Sopenharmony_civoid aa_free_ns(struct aa_ns *ns) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci if (!ns) 15162306a36Sopenharmony_ci return; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci aa_policy_destroy(&ns->base); 15462306a36Sopenharmony_ci aa_labelset_destroy(&ns->labels); 15562306a36Sopenharmony_ci aa_put_ns(ns->parent); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci ns->unconfined->ns = NULL; 15862306a36Sopenharmony_ci aa_free_profile(ns->unconfined); 15962306a36Sopenharmony_ci kfree_sensitive(ns); 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci/** 16362306a36Sopenharmony_ci * aa_findn_ns - look up a profile namespace on the namespace list 16462306a36Sopenharmony_ci * @root: namespace to search in (NOT NULL) 16562306a36Sopenharmony_ci * @name: name of namespace to find (NOT NULL) 16662306a36Sopenharmony_ci * @n: length of @name 16762306a36Sopenharmony_ci * 16862306a36Sopenharmony_ci * Returns: a refcounted namespace on the list, or NULL if no namespace 16962306a36Sopenharmony_ci * called @name exists. 17062306a36Sopenharmony_ci * 17162306a36Sopenharmony_ci * refcount released by caller 17262306a36Sopenharmony_ci */ 17362306a36Sopenharmony_cistruct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n) 17462306a36Sopenharmony_ci{ 17562306a36Sopenharmony_ci struct aa_ns *ns = NULL; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci rcu_read_lock(); 17862306a36Sopenharmony_ci ns = aa_get_ns(__aa_findn_ns(&root->sub_ns, name, n)); 17962306a36Sopenharmony_ci rcu_read_unlock(); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci return ns; 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci/** 18562306a36Sopenharmony_ci * aa_find_ns - look up a profile namespace on the namespace list 18662306a36Sopenharmony_ci * @root: namespace to search in (NOT NULL) 18762306a36Sopenharmony_ci * @name: name of namespace to find (NOT NULL) 18862306a36Sopenharmony_ci * 18962306a36Sopenharmony_ci * Returns: a refcounted namespace on the list, or NULL if no namespace 19062306a36Sopenharmony_ci * called @name exists. 19162306a36Sopenharmony_ci * 19262306a36Sopenharmony_ci * refcount released by caller 19362306a36Sopenharmony_ci */ 19462306a36Sopenharmony_cistruct aa_ns *aa_find_ns(struct aa_ns *root, const char *name) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci return aa_findn_ns(root, name, strlen(name)); 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci/** 20062306a36Sopenharmony_ci * __aa_lookupn_ns - lookup the namespace matching @hname 20162306a36Sopenharmony_ci * @view: namespace to search in (NOT NULL) 20262306a36Sopenharmony_ci * @hname: hierarchical ns name (NOT NULL) 20362306a36Sopenharmony_ci * @n: length of @hname 20462306a36Sopenharmony_ci * 20562306a36Sopenharmony_ci * Requires: rcu_read_lock be held 20662306a36Sopenharmony_ci * 20762306a36Sopenharmony_ci * Returns: unrefcounted ns pointer or NULL if not found 20862306a36Sopenharmony_ci * 20962306a36Sopenharmony_ci * Do a relative name lookup, recursing through profile tree. 21062306a36Sopenharmony_ci */ 21162306a36Sopenharmony_cistruct aa_ns *__aa_lookupn_ns(struct aa_ns *view, const char *hname, size_t n) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci struct aa_ns *ns = view; 21462306a36Sopenharmony_ci const char *split; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci for (split = strnstr(hname, "//", n); split; 21762306a36Sopenharmony_ci split = strnstr(hname, "//", n)) { 21862306a36Sopenharmony_ci ns = __aa_findn_ns(&ns->sub_ns, hname, split - hname); 21962306a36Sopenharmony_ci if (!ns) 22062306a36Sopenharmony_ci return NULL; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci n -= split + 2 - hname; 22362306a36Sopenharmony_ci hname = split + 2; 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci if (n) 22762306a36Sopenharmony_ci return __aa_findn_ns(&ns->sub_ns, hname, n); 22862306a36Sopenharmony_ci return NULL; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci/** 23262306a36Sopenharmony_ci * aa_lookupn_ns - look up a policy namespace relative to @view 23362306a36Sopenharmony_ci * @view: namespace to search in (NOT NULL) 23462306a36Sopenharmony_ci * @name: name of namespace to find (NOT NULL) 23562306a36Sopenharmony_ci * @n: length of @name 23662306a36Sopenharmony_ci * 23762306a36Sopenharmony_ci * Returns: a refcounted namespace on the list, or NULL if no namespace 23862306a36Sopenharmony_ci * called @name exists. 23962306a36Sopenharmony_ci * 24062306a36Sopenharmony_ci * refcount released by caller 24162306a36Sopenharmony_ci */ 24262306a36Sopenharmony_cistruct aa_ns *aa_lookupn_ns(struct aa_ns *view, const char *name, size_t n) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci struct aa_ns *ns = NULL; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci rcu_read_lock(); 24762306a36Sopenharmony_ci ns = aa_get_ns(__aa_lookupn_ns(view, name, n)); 24862306a36Sopenharmony_ci rcu_read_unlock(); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci return ns; 25162306a36Sopenharmony_ci} 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cistatic struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, 25462306a36Sopenharmony_ci struct dentry *dir) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci struct aa_ns *ns; 25762306a36Sopenharmony_ci int error; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci AA_BUG(!parent); 26062306a36Sopenharmony_ci AA_BUG(!name); 26162306a36Sopenharmony_ci AA_BUG(!mutex_is_locked(&parent->lock)); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci ns = alloc_ns(parent->base.hname, name); 26462306a36Sopenharmony_ci if (!ns) 26562306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 26662306a36Sopenharmony_ci ns->level = parent->level + 1; 26762306a36Sopenharmony_ci mutex_lock_nested(&ns->lock, ns->level); 26862306a36Sopenharmony_ci error = __aafs_ns_mkdir(ns, ns_subns_dir(parent), name, dir); 26962306a36Sopenharmony_ci if (error) { 27062306a36Sopenharmony_ci AA_ERROR("Failed to create interface for ns %s\n", 27162306a36Sopenharmony_ci ns->base.name); 27262306a36Sopenharmony_ci mutex_unlock(&ns->lock); 27362306a36Sopenharmony_ci aa_free_ns(ns); 27462306a36Sopenharmony_ci return ERR_PTR(error); 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci ns->parent = aa_get_ns(parent); 27762306a36Sopenharmony_ci list_add_rcu(&ns->base.list, &parent->sub_ns); 27862306a36Sopenharmony_ci /* add list ref */ 27962306a36Sopenharmony_ci aa_get_ns(ns); 28062306a36Sopenharmony_ci mutex_unlock(&ns->lock); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci return ns; 28362306a36Sopenharmony_ci} 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci/** 28662306a36Sopenharmony_ci * __aa_find_or_create_ns - create an ns, fail if it already exists 28762306a36Sopenharmony_ci * @parent: the parent of the namespace being created 28862306a36Sopenharmony_ci * @name: the name of the namespace 28962306a36Sopenharmony_ci * @dir: if not null the dir to put the ns entries in 29062306a36Sopenharmony_ci * 29162306a36Sopenharmony_ci * Returns: the a refcounted ns that has been add or an ERR_PTR 29262306a36Sopenharmony_ci */ 29362306a36Sopenharmony_cistruct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name, 29462306a36Sopenharmony_ci struct dentry *dir) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci struct aa_ns *ns; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci AA_BUG(!mutex_is_locked(&parent->lock)); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* try and find the specified ns */ 30162306a36Sopenharmony_ci /* released by caller */ 30262306a36Sopenharmony_ci ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name)); 30362306a36Sopenharmony_ci if (!ns) 30462306a36Sopenharmony_ci ns = __aa_create_ns(parent, name, dir); 30562306a36Sopenharmony_ci else 30662306a36Sopenharmony_ci ns = ERR_PTR(-EEXIST); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci /* return ref */ 30962306a36Sopenharmony_ci return ns; 31062306a36Sopenharmony_ci} 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci/** 31362306a36Sopenharmony_ci * aa_prepare_ns - find an existing or create a new namespace of @name 31462306a36Sopenharmony_ci * @parent: ns to treat as parent 31562306a36Sopenharmony_ci * @name: the namespace to find or add (NOT NULL) 31662306a36Sopenharmony_ci * 31762306a36Sopenharmony_ci * Returns: refcounted namespace or PTR_ERR if failed to create one 31862306a36Sopenharmony_ci */ 31962306a36Sopenharmony_cistruct aa_ns *aa_prepare_ns(struct aa_ns *parent, const char *name) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci struct aa_ns *ns; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci mutex_lock_nested(&parent->lock, parent->level); 32462306a36Sopenharmony_ci /* try and find the specified ns and if it doesn't exist create it */ 32562306a36Sopenharmony_ci /* released by caller */ 32662306a36Sopenharmony_ci ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name)); 32762306a36Sopenharmony_ci if (!ns) 32862306a36Sopenharmony_ci ns = __aa_create_ns(parent, name, NULL); 32962306a36Sopenharmony_ci mutex_unlock(&parent->lock); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci /* return ref */ 33262306a36Sopenharmony_ci return ns; 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic void __ns_list_release(struct list_head *head); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci/** 33862306a36Sopenharmony_ci * destroy_ns - remove everything contained by @ns 33962306a36Sopenharmony_ci * @ns: namespace to have it contents removed (NOT NULL) 34062306a36Sopenharmony_ci */ 34162306a36Sopenharmony_cistatic void destroy_ns(struct aa_ns *ns) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci if (!ns) 34462306a36Sopenharmony_ci return; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci mutex_lock_nested(&ns->lock, ns->level); 34762306a36Sopenharmony_ci /* release all profiles in this namespace */ 34862306a36Sopenharmony_ci __aa_profile_list_release(&ns->base.profiles); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci /* release all sub namespaces */ 35162306a36Sopenharmony_ci __ns_list_release(&ns->sub_ns); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci if (ns->parent) { 35462306a36Sopenharmony_ci unsigned long flags; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci write_lock_irqsave(&ns->labels.lock, flags); 35762306a36Sopenharmony_ci __aa_proxy_redirect(ns_unconfined(ns), 35862306a36Sopenharmony_ci ns_unconfined(ns->parent)); 35962306a36Sopenharmony_ci write_unlock_irqrestore(&ns->labels.lock, flags); 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci __aafs_ns_rmdir(ns); 36262306a36Sopenharmony_ci mutex_unlock(&ns->lock); 36362306a36Sopenharmony_ci} 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci/** 36662306a36Sopenharmony_ci * __aa_remove_ns - remove a namespace and all its children 36762306a36Sopenharmony_ci * @ns: namespace to be removed (NOT NULL) 36862306a36Sopenharmony_ci * 36962306a36Sopenharmony_ci * Requires: ns->parent->lock be held and ns removed from parent. 37062306a36Sopenharmony_ci */ 37162306a36Sopenharmony_civoid __aa_remove_ns(struct aa_ns *ns) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci /* remove ns from namespace list */ 37462306a36Sopenharmony_ci list_del_rcu(&ns->base.list); 37562306a36Sopenharmony_ci destroy_ns(ns); 37662306a36Sopenharmony_ci aa_put_ns(ns); 37762306a36Sopenharmony_ci} 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci/** 38062306a36Sopenharmony_ci * __ns_list_release - remove all profile namespaces on the list put refs 38162306a36Sopenharmony_ci * @head: list of profile namespaces (NOT NULL) 38262306a36Sopenharmony_ci * 38362306a36Sopenharmony_ci * Requires: namespace lock be held 38462306a36Sopenharmony_ci */ 38562306a36Sopenharmony_cistatic void __ns_list_release(struct list_head *head) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci struct aa_ns *ns, *tmp; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci list_for_each_entry_safe(ns, tmp, head, base.list) 39062306a36Sopenharmony_ci __aa_remove_ns(ns); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci/** 39562306a36Sopenharmony_ci * aa_alloc_root_ns - allocate the root profile namespace 39662306a36Sopenharmony_ci * 39762306a36Sopenharmony_ci * Returns: %0 on success else error 39862306a36Sopenharmony_ci * 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_ciint __init aa_alloc_root_ns(void) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci struct aa_profile *kernel_p; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci /* released by aa_free_root_ns - used as list ref*/ 40562306a36Sopenharmony_ci root_ns = alloc_ns(NULL, "root"); 40662306a36Sopenharmony_ci if (!root_ns) 40762306a36Sopenharmony_ci return -ENOMEM; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci kernel_p = alloc_unconfined("kernel_t"); 41062306a36Sopenharmony_ci if (!kernel_p) { 41162306a36Sopenharmony_ci destroy_ns(root_ns); 41262306a36Sopenharmony_ci aa_free_ns(root_ns); 41362306a36Sopenharmony_ci return -ENOMEM; 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci kernel_t = &kernel_p->label; 41662306a36Sopenharmony_ci root_ns->unconfined->ns = aa_get_ns(root_ns); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci return 0; 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci /** 42262306a36Sopenharmony_ci * aa_free_root_ns - free the root profile namespace 42362306a36Sopenharmony_ci */ 42462306a36Sopenharmony_civoid __init aa_free_root_ns(void) 42562306a36Sopenharmony_ci{ 42662306a36Sopenharmony_ci struct aa_ns *ns = root_ns; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci root_ns = NULL; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci aa_label_free(kernel_t); 43162306a36Sopenharmony_ci destroy_ns(ns); 43262306a36Sopenharmony_ci aa_put_ns(ns); 43362306a36Sopenharmony_ci} 434