Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * AppArmor security module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * This file contains AppArmor policy manipulation functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * Copyright (C) 1998-2008 Novell/SUSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * Copyright 2009-2010 Canonical Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  * AppArmor policy is based around profiles, which contain the rules a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  * task is confined by.  Every task in the system has a profile attached
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  * to it determined either by matching "unconfined" tasks against the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  * visible set of profiles or by following a profiles attachment rules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  * Each profile exists in a profile namespace which is a container of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  * visible profiles.  Each namespace contains a special "unconfined" profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  * which doesn't enforce any confinement on a task beyond DAC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)  * Namespace and profile names can be written together in either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20)  * of two syntaxes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21)  *	:namespace:profile - used by kernel interfaces for easy detection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22)  *	namespace://profile - used by policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24)  * Profile names can not start with : or @ or ^ and may not contain \0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26)  * Reserved profile names
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27)  *	unconfined - special automatically generated unconfined profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28)  *	inherit - special name to indicate profile inheritance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29)  *	null-XXXX-YYYY - special automatically generated learning profiles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31)  * Namespace names may not start with / or @ and may not contain \0 or :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32)  * Reserved namespace names
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33)  *	user-XXXX - user defined profiles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35)  * a // in a profile or namespace name indicates a hierarchical name with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36)  * name before the // being the parent and the name after the child.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38)  * Profile and namespace hierarchies serve two different but similar purposes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39)  * The namespace contains the set of visible profiles that are considered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40)  * for attachment.  The hierarchy of namespaces allows for virtualizing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41)  * the namespace so that for example a chroot can have its own set of profiles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42)  * which may define some local user namespaces.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43)  * The profile hierarchy severs two distinct purposes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44)  * -  it allows for sub profiles or hats, which allows an application to run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45)  *    subprograms under its own profile with different restriction than it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46)  *    self, and not have it use the system profile.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47)  *    eg. if a mail program starts an editor, the policy might make the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48)  *        restrictions tighter on the editor tighter than the mail program,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49)  *        and definitely different than general editor restrictions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50)  * - it allows for binary hierarchy of profiles, so that execution history
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51)  *   is preserved.  This feature isn't exploited by AppArmor reference policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52)  *   but is allowed.  NOTE: this is currently suboptimal because profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53)  *   aliasing is not currently implemented so that a profile for each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54)  *   level must be defined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55)  *   eg. /bin/bash///bin/ls as a name would indicate /bin/ls was started
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56)  *       from /bin/bash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58)  *   A profile or namespace name that can contain one or more // separators
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59)  *   is referred to as an hname (hierarchical).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60)  *   eg.  /bin/bash//bin/ls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62)  *   An fqname is a name that may contain both namespace and profile hnames.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63)  *   eg. :ns:/bin/bash//bin/ls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65)  * NOTES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66)  *   - locking of profile lists is currently fairly coarse.  All profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67)  *     lists within a namespace use the namespace lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68)  * FIXME: move profile lists to using rcu_lists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) #include <linux/cred.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) #include <linux/rculist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) #include <linux/user_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) #include "include/apparmor.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) #include "include/capability.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) #include "include/cred.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) #include "include/file.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) #include "include/ipc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) #include "include/match.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) #include "include/path.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) #include "include/policy.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) #include "include/policy_ns.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) #include "include/policy_unpack.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) #include "include/resource.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) int unprivileged_userns_apparmor_policy = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) const char *const aa_profile_mode_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 	"enforce",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	"complain",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 	"kill",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 	"unconfined",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101)  * __add_profile - add a profiles to list and label tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102)  * @list: list to add it to  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103)  * @profile: the profile to add  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105)  * refcount @profile, should be put by __list_remove_profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107)  * Requires: namespace lock be held, or list not be shared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) static void __add_profile(struct list_head *list, struct aa_profile *profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 	struct aa_label *l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	AA_BUG(!list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 	AA_BUG(!profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 	AA_BUG(!profile->ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 	AA_BUG(!mutex_is_locked(&profile->ns->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 	list_add_rcu(&profile->base.list, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 	/* get list reference */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	aa_get_profile(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	l = aa_label_insert(&profile->ns->labels, &profile->label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	AA_BUG(l != &profile->label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	aa_put_label(l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127)  * __list_remove_profile - remove a profile from the list it is on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128)  * @profile: the profile to remove  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130)  * remove a profile from the list, warning generally removal should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131)  * be done with __replace_profile as most profile removals are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132)  * replacements to the unconfined profile.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134)  * put @profile list refcount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136)  * Requires: namespace lock be held, or list not have been live
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) static void __list_remove_profile(struct aa_profile *profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 	AA_BUG(!profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	AA_BUG(!profile->ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	AA_BUG(!mutex_is_locked(&profile->ns->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	list_del_rcu(&profile->base.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 	aa_put_profile(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149)  * __remove_profile - remove old profile, and children
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150)  * @profile: profile to be replaced  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152)  * Requires: namespace list lock be held, or list not be shared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) static void __remove_profile(struct aa_profile *profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 	AA_BUG(!profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	AA_BUG(!profile->ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 	AA_BUG(!mutex_is_locked(&profile->ns->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	/* release any children lists first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	__aa_profile_list_release(&profile->base.profiles);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	/* released by free_profile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 	aa_label_remove(&profile->label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	__aafs_profile_rmdir(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 	__list_remove_profile(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169)  * __aa_profile_list_release - remove all profiles on the list and put refs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170)  * @head: list of profiles  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172)  * Requires: namespace lock be held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) void __aa_profile_list_release(struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 	struct aa_profile *profile, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	list_for_each_entry_safe(profile, tmp, head, base.list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 		__remove_profile(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182)  * aa_free_data - free a data blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183)  * @ptr: data to free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184)  * @arg: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) static void aa_free_data(void *ptr, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	struct aa_data *data = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	kfree_sensitive(data->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	kfree_sensitive(data->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	kfree_sensitive(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196)  * aa_free_profile - free a profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197)  * @profile: the profile to free  (MAYBE NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199)  * Free a profile, its hats and null_profile. All references to the profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200)  * its hats and null_profile must have been put.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202)  * If the profile was referenced from a task context, free_profile() will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203)  * be called from an rcu callback routine, so we must not sleep here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) void aa_free_profile(struct aa_profile *profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	struct rhashtable *rht;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	AA_DEBUG("%s(%p)\n", __func__, profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	if (!profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	/* free children profiles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	aa_policy_destroy(&profile->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	aa_put_profile(rcu_access_pointer(profile->parent));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	aa_put_ns(profile->ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	kfree_sensitive(profile->rename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	aa_free_file_rules(&profile->file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	aa_free_cap_rules(&profile->caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	aa_free_rlimit_rules(&profile->rlimits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	for (i = 0; i < profile->xattr_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 		kfree_sensitive(profile->xattrs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	kfree_sensitive(profile->xattrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	for (i = 0; i < profile->secmark_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 		kfree_sensitive(profile->secmark[i].label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	kfree_sensitive(profile->secmark);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	kfree_sensitive(profile->dirname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	aa_put_dfa(profile->xmatch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 	aa_put_dfa(profile->policy.dfa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	if (profile->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 		rht = profile->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 		profile->data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 		rhashtable_free_and_destroy(rht, aa_free_data, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 		kfree_sensitive(rht);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	kfree_sensitive(profile->hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	aa_put_loaddata(profile->rawdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	aa_label_destroy(&profile->label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	kfree_sensitive(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251)  * aa_alloc_profile - allocate, initialize and return a new profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252)  * @hname: name of the profile  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253)  * @gfp: allocation type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255)  * Returns: refcount profile or NULL on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 				    gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 	/* freed by free_profile - usually through aa_put_profile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	profile = kzalloc(sizeof(*profile) + sizeof(struct aa_profile *) * 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 			  gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	if (!profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	if (!aa_policy_init(&profile->base, NULL, hname, gfp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	if (!aa_label_init(&profile->label, 1, gfp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	/* update being set needed by fs interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	if (!proxy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 		proxy = aa_alloc_proxy(&profile->label, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 		if (!proxy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 		aa_get_proxy(proxy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	profile->label.proxy = proxy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	profile->label.hname = profile->base.hname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	profile->label.flags |= FLAG_PROFILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	profile->label.vec[0] = profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	/* refcount released by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	return profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	aa_free_profile(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) /* TODO: profile accounting - setup in remove */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298)  * __strn_find_child - find a profile on @head list using substring of @name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299)  * @head: list to search  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300)  * @name: name of profile (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301)  * @len: length of @name substring to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303)  * Requires: rcu_read_lock be held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305)  * Returns: unrefcounted profile ptr, or NULL if not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) static struct aa_profile *__strn_find_child(struct list_head *head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 					    const char *name, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	return (struct aa_profile *)__policy_strn_find(head, name, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314)  * __find_child - find a profile on @head list with a name matching @name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315)  * @head: list to search  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316)  * @name: name of profile (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318)  * Requires: rcu_read_lock be held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320)  * Returns: unrefcounted profile ptr, or NULL if not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) static struct aa_profile *__find_child(struct list_head *head, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	return __strn_find_child(head, name, strlen(name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328)  * aa_find_child - find a profile by @name in @parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329)  * @parent: profile to search  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330)  * @name: profile name to search for  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332)  * Returns: a refcounted profile or NULL if not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 		profile = __find_child(&parent->base.profiles, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	} while (profile && !aa_get_profile_not0(profile));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 	rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	/* refcount released by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 	return profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349)  * __lookup_parent - lookup the parent of a profile of name @hname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350)  * @ns: namespace to lookup profile in  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351)  * @hname: hierarchical profile name to find parent of  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353)  * Lookups up the parent of a fully qualified profile name, the profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354)  * that matches hname does not need to exist, in general this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355)  * is used to load a new profile.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357)  * Requires: rcu_read_lock be held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359)  * Returns: unrefcounted policy or NULL if not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) static struct aa_policy *__lookup_parent(struct aa_ns *ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 					 const char *hname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	struct aa_policy *policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	struct aa_profile *profile = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	char *split;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	policy = &ns->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 	for (split = strstr(hname, "//"); split;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 		profile = __strn_find_child(&policy->profiles, hname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 					    split - hname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 		if (!profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 			return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 		policy = &profile->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 		hname = split + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 		split = strstr(hname, "//");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	if (!profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 		return &ns->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	return &profile->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385)  * __lookupn_profile - lookup the profile matching @hname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386)  * @base: base list to start looking up profile name from  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387)  * @hname: hierarchical profile name  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388)  * @n: length of @hname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390)  * Requires: rcu_read_lock be held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392)  * Returns: unrefcounted profile pointer or NULL if not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394)  * Do a relative name lookup, recursing through profile tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) static struct aa_profile *__lookupn_profile(struct aa_policy *base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 					    const char *hname, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	struct aa_profile *profile = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	const char *split;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 	for (split = strnstr(hname, "//", n); split;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 	     split = strnstr(hname, "//", n)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 		profile = __strn_find_child(&base->profiles, hname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 					    split - hname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 		if (!profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 			return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 		base = &profile->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 		n -= split + 2 - hname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 		hname = split + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	if (n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 		return __strn_find_child(&base->profiles, hname, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) static struct aa_profile *__lookup_profile(struct aa_policy *base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 					   const char *hname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	return __lookupn_profile(base, hname, strlen(hname));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426)  * aa_lookup_profile - find a profile by its full or partial name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427)  * @ns: the namespace to start from (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428)  * @hname: name to do lookup on.  Does not contain namespace prefix (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429)  * @n: size of @hname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431)  * Returns: refcounted profile or NULL if not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 				      size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 		profile = __lookupn_profile(&ns->base, hname, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	} while (profile && !aa_get_profile_not0(profile));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	/* the unconfined profile is not in the regular profile list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	if (!profile && strncmp(hname, "unconfined", n) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 		profile = aa_get_newest_profile(ns->unconfined);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	/* refcount released by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	return profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *hname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	return aa_lookupn_profile(ns, hname, strlen(hname));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) struct aa_profile *aa_fqlookupn_profile(struct aa_label *base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 					const char *fqname, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	struct aa_ns *ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 	const char *name, *ns_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 	size_t ns_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	name = aa_splitn_fqname(fqname, n, &ns_name, &ns_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	if (ns_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		ns = aa_lookupn_ns(labels_ns(base), ns_name, ns_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		if (!ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 			return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 		ns = aa_get_ns(labels_ns(base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	if (name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 		profile = aa_lookupn_profile(ns, name, n - (name - fqname));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	else if (ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		/* default profile for ns, currently unconfined */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		profile = aa_get_newest_profile(ns->unconfined);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 		profile = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	aa_put_ns(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	return profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486)  * aa_new_null_profile - create or find a null-X learning profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487)  * @parent: profile that caused this profile to be created (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488)  * @hat: true if the null- learning profile is a hat
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489)  * @base: name to base the null profile off of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490)  * @gfp: type of allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492)  * Find/Create a null- complain mode profile used in learning mode.  The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493)  * name of the profile is unique and follows the format of parent//null-XXX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494)  * where XXX is based on the @name or if that fails or is not supplied
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495)  * a unique number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497)  * null profiles are added to the profile list but the list does not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498)  * hold a count on them so that they are automatically released when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499)  * not in use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501)  * Returns: new refcounted profile else NULL on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 				       const char *base, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 	struct aa_profile *p, *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	const char *bname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	char *name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	AA_BUG(!parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	if (base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 		name = kmalloc(strlen(parent->base.hname) + 8 + strlen(base),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 			       gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 		if (name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 			sprintf(name, "%s//null-%s", parent->base.hname, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 			goto name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 		/* fall through to try shorter uniq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	sprintf(name, "%s//null-%x", parent->base.hname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 		atomic_inc_return(&parent->ns->uniq_null));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) name:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	/* lookup to see if this is a dup creation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	bname = basename(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	profile = aa_find_child(parent, bname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	if (profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	profile = aa_alloc_profile(name, NULL, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	if (!profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	profile->mode = APPARMOR_COMPLAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	profile->label.flags |= FLAG_NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	if (hat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 		profile->label.flags |= FLAG_HAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	profile->path_flags = parent->path_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	/* released on free_profile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	rcu_assign_pointer(profile->parent, aa_get_profile(parent));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 	profile->ns = aa_get_ns(parent->ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	profile->file.dfa = aa_get_dfa(nulldfa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	profile->policy.dfa = aa_get_dfa(nulldfa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	mutex_lock_nested(&profile->ns->lock, profile->ns->level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	p = __find_child(&parent->base.profiles, bname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	if (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 		aa_free_profile(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 		profile = aa_get_profile(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 		__add_profile(&parent->base.profiles, profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	mutex_unlock(&profile->ns->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	/* refcount released by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 	kfree(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 	return profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 	kfree(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 	aa_free_profile(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574)  * replacement_allowed - test to see if replacement is allowed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575)  * @profile: profile to test if it can be replaced  (MAYBE NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576)  * @noreplace: true if replacement shouldn't be allowed but addition is okay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577)  * @info: Returns - info about why replacement failed (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579)  * Returns: %0 if replacement allowed else error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) static int replacement_allowed(struct aa_profile *profile, int noreplace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 			       const char **info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	if (profile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		if (profile->label.flags & FLAG_IMMUTIBLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 			*info = "cannot replace immutable profile";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 			return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 		} else if (noreplace) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 			*info = "profile already exists";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 			return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) /* audit callback for net specific fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) static void audit_cb(struct audit_buffer *ab, void *va)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 	struct common_audit_data *sa = va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 	if (aad(sa)->iface.ns) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 		audit_log_format(ab, " ns=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 		audit_log_untrustedstring(ab, aad(sa)->iface.ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608)  * audit_policy - Do auditing of policy changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609)  * @label: label to check if it can manage policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610)  * @op: policy operation being performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611)  * @ns_name: name of namespace being manipulated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612)  * @name: name of profile being manipulated (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613)  * @info: any extra information to be audited (MAYBE NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614)  * @error: error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616)  * Returns: the error to be returned after audit is done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) static int audit_policy(struct aa_label *label, const char *op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 			const char *ns_name, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 			const char *info, int error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 	DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	aad(&sa)->iface.ns = ns_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	aad(&sa)->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	aad(&sa)->info = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	aad(&sa)->error = error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 	aad(&sa)->label = label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 	aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, audit_cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636)  * policy_view_capable - check if viewing policy in at @ns is allowed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637)  * ns: namespace being viewed by current task (may be NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638)  * Returns: true if viewing policy is allowed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640)  * If @ns is NULL then the namespace being viewed is assumed to be the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641)  * tasks current namespace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) bool policy_view_capable(struct aa_ns *ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	struct user_namespace *user_ns = current_user_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 	struct aa_ns *view_ns = aa_get_current_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 	bool root_in_user_ns = uid_eq(current_euid(), make_kuid(user_ns, 0)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 			       in_egroup_p(make_kgid(user_ns, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	bool response = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	if (!ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 		ns = view_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	if (root_in_user_ns && aa_ns_visible(view_ns, ns, true) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	    (user_ns == &init_user_ns ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 	     (unprivileged_userns_apparmor_policy != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	      user_ns->level == view_ns->level)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 		response = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	aa_put_ns(view_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	return response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) bool policy_admin_capable(struct aa_ns *ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	struct user_namespace *user_ns = current_user_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	bool capable = ns_capable(user_ns, CAP_MAC_ADMIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	AA_DEBUG("cap_mac_admin? %d\n", capable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	AA_DEBUG("policy locked? %d\n", aa_g_lock_policy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	return policy_view_capable(ns) && capable && !aa_g_lock_policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675)  * aa_may_manage_policy - can the current task manage policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676)  * @label: label to check if it can manage policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677)  * @op: the policy manipulation operation being done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679)  * Returns: 0 if the task is allowed to manipulate policy else error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	const char *op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	if (mask & AA_MAY_REMOVE_POLICY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 		op = OP_PROF_RM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	else if (mask & AA_MAY_REPLACE_POLICY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 		op = OP_PROF_REPL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 		op = OP_PROF_LOAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	/* check if loading policy is locked out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 	if (aa_g_lock_policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		return audit_policy(label, op, NULL, NULL, "policy_locked",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 				    -EACCES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	if (!policy_admin_capable(ns))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 		return audit_policy(label, op, NULL, NULL, "not policy admin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 				    -EACCES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	/* TODO: add fine grained mediation of policy loads */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) static struct aa_profile *__list_lookup_parent(struct list_head *lh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 					       struct aa_profile *profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	const char *base = basename(profile->base.hname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	long len = base - profile->base.hname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	struct aa_load_ent *ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	/* parent won't have trailing // so remove from len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	if (len <= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	len -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	list_for_each_entry(ent, lh, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 		if (ent->new == profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 		if (strncmp(ent->new->base.hname, profile->base.hname, len) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 		    0 && ent->new->base.hname[len] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 			return ent->new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729)  * __replace_profile - replace @old with @new on a list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730)  * @old: profile to be replaced  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731)  * @new: profile to replace @old with  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732)  * @share_proxy: transfer @old->proxy to @new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734)  * Will duplicate and refcount elements that @new inherits from @old
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735)  * and will inherit @old children.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737)  * refcount @new for list, put @old list refcount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739)  * Requires: namespace list lock be held, or list not be shared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) static void __replace_profile(struct aa_profile *old, struct aa_profile *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	struct aa_profile *child, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	if (!list_empty(&old->base.profiles)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 		LIST_HEAD(lh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 		list_splice_init_rcu(&old->base.profiles, &lh, synchronize_rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 		list_for_each_entry_safe(child, tmp, &lh, base.list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 			struct aa_profile *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 			list_del_init(&child->base.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 			p = __find_child(&new->base.profiles, child->base.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 			if (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 				/* @p replaces @child  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 				__replace_profile(child, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 			/* inherit @child and its children */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 			/* TODO: update hname of inherited children */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 			/* list refcount transferred to @new */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 			p = aa_deref_parent(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 			rcu_assign_pointer(child->parent, aa_get_profile(new));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 			list_add_rcu(&child->base.list, &new->base.profiles);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 			aa_put_profile(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	if (!rcu_access_pointer(new->parent)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 		struct aa_profile *parent = aa_deref_parent(old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 		rcu_assign_pointer(new->parent, aa_get_profile(parent));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	aa_label_replace(&old->label, &new->label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	/* migrate dents must come after label replacement b/c update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	__aafs_profile_migrate_dents(old, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 	if (list_empty(&new->base.list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 		/* new is not on a list already */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 		list_replace_rcu(&old->base.list, &new->base.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 		aa_get_profile(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 		aa_put_profile(old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 		__list_remove_profile(old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788)  * __lookup_replace - lookup replacement information for a profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789)  * @ns - namespace the lookup occurs in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790)  * @hname - name of profile to lookup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791)  * @noreplace - true if not replacing an existing profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792)  * @p - Returns: profile to be replaced
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793)  * @info - Returns: info string on why lookup failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795)  * Returns: profile to replace (no ref) on success else ptr error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) static int __lookup_replace(struct aa_ns *ns, const char *hname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 			    bool noreplace, struct aa_profile **p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 			    const char **info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	*p = aa_get_profile(__lookup_profile(&ns->base, hname));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	if (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 		int error = replacement_allowed(*p, noreplace, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 		if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 			*info = "profile can not be replaced";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 			return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) static void share_name(struct aa_profile *old, struct aa_profile *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 	aa_put_str(new->base.hname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	aa_get_str(old->base.hname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	new->base.hname = old->base.hname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	new->base.name = old->base.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	new->label.hname = old->label.hname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) /* Update to newest version of parent after previous replacements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823)  * Returns: unrefcount newest version of parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) static struct aa_profile *update_to_newest_parent(struct aa_profile *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	struct aa_profile *parent, *newest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	parent = rcu_dereference_protected(new->parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 					   mutex_is_locked(&new->ns->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	newest = aa_get_newest_profile(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	/* parent replaced in this atomic set? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	if (newest != parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 		aa_put_profile(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 		rcu_assign_pointer(new->parent, newest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 		aa_put_profile(newest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	return newest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844)  * aa_replace_profiles - replace profile(s) on the profile list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845)  * @policy_ns: namespace load is occurring on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846)  * @label: label that is attempting to load/replace policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847)  * @mask: permission mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848)  * @udata: serialized data stream  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850)  * unpack and replace a profile on the profile list and uses of that profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851)  * by any task creds via invalidating the old version of the profile, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852)  * tasks will notice to update their own cred.  If the profile does not exist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853)  * on the profile list it is added.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855)  * Returns: size of data consumed else error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 			    u32 mask, struct aa_loaddata *udata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	const char *ns_name = NULL, *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	struct aa_ns *ns = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	struct aa_load_ent *ent, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 	struct aa_loaddata *rawdata_ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	const char *op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	ssize_t count, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	LIST_HEAD(lh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	op = mask & AA_MAY_REPLACE_POLICY ? OP_PROF_REPL : OP_PROF_LOAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	aa_get_loaddata(udata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	/* released below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 	error = aa_unpack(udata, &lh, &ns_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	/* ensure that profiles are all for the same ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 	 * TODO: update locking to remove this constaint. All profiles in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	 *       the load set must succeed as a set or the load will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	 *       fail. Sort ent list and take ns locks in hierarchy order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	list_for_each_entry(ent, &lh, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 		if (ns_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 			if (ent->ns_name &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 			    strcmp(ent->ns_name, ns_name) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 				info = "policy load has mixed namespaces";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 				error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 				goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 		} else if (ent->ns_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 			if (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 				info = "policy load has mixed namespaces";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 				error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 				goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 			ns_name = ent->ns_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 			count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	if (ns_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 		ns = aa_prepare_ns(policy_ns ? policy_ns : labels_ns(label),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 				   ns_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 		if (IS_ERR(ns)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 			op = OP_PROF_LOAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 			info = "failed to prepare namespace";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 			error = PTR_ERR(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 			ns = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 			ent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 		ns = aa_get_ns(policy_ns ? policy_ns : labels_ns(label));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	mutex_lock_nested(&ns->lock, ns->level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	/* check for duplicate rawdata blobs: space and file dedup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	list_for_each_entry(rawdata_ent, &ns->rawdata_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 		if (aa_rawdata_eq(rawdata_ent, udata)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 			struct aa_loaddata *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 			tmp = __aa_get_loaddata(rawdata_ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 			/* check we didn't fail the race */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 			if (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 				aa_put_loaddata(udata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 				udata = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	/* setup parent and ns info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	list_for_each_entry(ent, &lh, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 		struct aa_policy *policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 		ent->new->rawdata = aa_get_loaddata(udata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 		error = __lookup_replace(ns, ent->new->base.hname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 					 !(mask & AA_MAY_REPLACE_POLICY),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 					 &ent->old, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 		if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 			goto fail_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 		if (ent->new->rename) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 			error = __lookup_replace(ns, ent->new->rename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 						!(mask & AA_MAY_REPLACE_POLICY),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 						&ent->rename, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 			if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 				goto fail_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 		/* released when @new is freed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 		ent->new->ns = aa_get_ns(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 		if (ent->old || ent->rename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 		/* no ref on policy only use inside lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 		policy = __lookup_parent(ns, ent->new->base.hname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 		if (!policy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 			struct aa_profile *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 			p = __list_lookup_parent(&lh, ent->new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 			if (!p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 				error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 				info = "parent does not exist";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 				goto fail_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 			rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 		} else if (policy != &ns->base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 			/* released on profile replacement or free_profile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 			struct aa_profile *p = (struct aa_profile *) policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 			rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	/* create new fs entries for introspection if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	if (!udata->dents[AAFS_LOADDATA_DIR]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 		error = __aa_fs_create_rawdata(ns, udata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 			info = "failed to create raw_data dir and files";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 			ent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 			goto fail_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	list_for_each_entry(ent, &lh, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 		if (!ent->old) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 			struct dentry *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 			if (rcu_access_pointer(ent->new->parent)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 				struct aa_profile *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 				p = aa_deref_parent(ent->new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 				parent = prof_child_dir(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 			} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 				parent = ns_subprofs_dir(ent->new->ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 			error = __aafs_profile_mkdir(ent->new, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 		if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 			info = "failed to create";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 			goto fail_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 	/* Done with checks that may fail - do actual replacement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	__aa_bump_ns_revision(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	__aa_loaddata_update(udata, ns->revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	list_for_each_entry_safe(ent, tmp, &lh, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 		list_del_init(&ent->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 		op = (!ent->old && !ent->rename) ? OP_PROF_LOAD : OP_PROF_REPL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 		if (ent->old && ent->old->rawdata == ent->new->rawdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 			/* dedup actual profile replacement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 			audit_policy(label, op, ns_name, ent->new->base.hname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 				     "same as current profile, skipping",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 				     error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 			/* break refcount cycle with proxy. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 			aa_put_proxy(ent->new->label.proxy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 			ent->new->label.proxy = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 			goto skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 		 * TODO: finer dedup based on profile range in data. Load set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 		 * can differ but profile may remain unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 		audit_policy(label, op, ns_name, ent->new->base.hname, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 			     error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 		if (ent->old) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 			share_name(ent->old, ent->new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 			__replace_profile(ent->old, ent->new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 			struct list_head *lh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 			if (rcu_access_pointer(ent->new->parent)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 				struct aa_profile *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 				parent = update_to_newest_parent(ent->new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 				lh = &parent->base.profiles;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 			} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 				lh = &ns->base.profiles;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 			__add_profile(lh, ent->new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	skip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 		aa_load_ent_free(ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	__aa_labelset_update_subtree(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	mutex_unlock(&ns->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 	aa_put_ns(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 	aa_put_loaddata(udata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	kfree(ns_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 	return udata->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) fail_lock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	mutex_unlock(&ns->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 	/* audit cause of failure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 	op = (ent && !ent->old) ? OP_PROF_LOAD : OP_PROF_REPL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 	  audit_policy(label, op, ns_name, ent ? ent->new->base.hname : NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 		       info, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 	/* audit status that rest of profiles in the atomic set failed too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 	info = "valid profile in failed atomic policy load";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	list_for_each_entry(tmp, &lh, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 		if (tmp == ent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 			info = "unchecked profile in failed atomic policy load";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 			/* skip entry that caused failure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 		op = (!tmp->old) ? OP_PROF_LOAD : OP_PROF_REPL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 		audit_policy(label, op, ns_name, tmp->new->base.hname, info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 			     error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 	list_for_each_entry_safe(ent, tmp, &lh, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 		list_del_init(&ent->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 		aa_load_ent_free(ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)  * aa_remove_profiles - remove profile(s) from the system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)  * @policy_ns: namespace the remove is being done from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)  * @subj: label attempting to remove policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)  * @fqname: name of the profile or namespace to remove  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)  * @size: size of the name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)  * Remove a profile or sub namespace from the current namespace, so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)  * they can not be found anymore and mark them as replaced by unconfined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)  * NOTE: removing confinement does not restore rlimits to preconfinement values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)  * Returns: size of data consume else error code if fails
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_label *subj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 			   char *fqname, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 	struct aa_ns *ns = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 	struct aa_profile *profile = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 	const char *name = fqname, *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 	const char *ns_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 	ssize_t error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 	if (*fqname == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 		info = "no profile specified";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 		error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 	if (fqname[0] == ':') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 		size_t ns_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 		name = aa_splitn_fqname(fqname, size, &ns_name, &ns_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 		/* released below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 		ns = aa_lookupn_ns(policy_ns ? policy_ns : labels_ns(subj),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 				   ns_name, ns_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 		if (!ns) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 			info = "namespace does not exist";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 			error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 		/* released below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 		ns = aa_get_ns(policy_ns ? policy_ns : labels_ns(subj));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	if (!name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 		/* remove namespace - can only happen if fqname[0] == ':' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 		mutex_lock_nested(&ns->parent->lock, ns->level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 		__aa_bump_ns_revision(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 		__aa_remove_ns(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 		mutex_unlock(&ns->parent->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 		/* remove profile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 		mutex_lock_nested(&ns->lock, ns->level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 		profile = aa_get_profile(__lookup_profile(&ns->base, name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 		if (!profile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 			error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 			info = "profile does not exist";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 			goto fail_ns_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 		name = profile->base.hname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 		__aa_bump_ns_revision(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 		__remove_profile(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 		__aa_labelset_update_subtree(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 		mutex_unlock(&ns->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 	/* don't fail removal if audit fails */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	(void) audit_policy(subj, OP_PROF_RM, ns_name, name, info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 			    error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 	aa_put_ns(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 	aa_put_profile(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 	return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) fail_ns_lock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	mutex_unlock(&ns->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	aa_put_ns(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 	(void) audit_policy(subj, OP_PROF_RM, ns_name, name, info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 			    error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }