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 attachment and domain transitions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * Copyright (C) 2002-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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) #include <linux/fdtable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #include <linux/file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/tracehook.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/personality.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/xattr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include "include/audit.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include "include/apparmorfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include "include/cred.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include "include/domain.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include "include/file.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include "include/ipc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include "include/match.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include "include/path.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include "include/policy.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include "include/policy_ns.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32)  * aa_free_domain_entries - free entries in a domain table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33)  * @domain: the domain table to free  (MAYBE NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) void aa_free_domain_entries(struct aa_domain *domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) 	if (domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 		if (!domain->table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 		for (i = 0; i < domain->size; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 			kfree_sensitive(domain->table[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 		kfree_sensitive(domain->table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) 		domain->table = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50)  * may_change_ptraced_domain - check if can change profile on ptraced task
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51)  * @to_label: profile to change to  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52)  * @info: message if there is an error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54)  * Check if current is ptraced and if so if the tracing task is allowed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55)  * to trace the new domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57)  * Returns: %0 or error if change not allowed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) static int may_change_ptraced_domain(struct aa_label *to_label,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 				     const char **info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 	struct task_struct *tracer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 	struct aa_label *tracerl = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 	int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 	rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 	tracer = ptrace_parent(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 	if (tracer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 		/* released below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 		tracerl = aa_get_task_label(tracer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	/* not ptraced */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 	if (!tracer || unconfined(tracerl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 	error = aa_may_ptrace(tracerl, to_label, PTRACE_MODE_ATTACH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 	rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 	aa_put_label(tracerl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 		*info = "ptrace prevents transition";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) /**** TODO: dedup to aa_label_match - needs perm and dfa, merging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88)  * specifically this is an exact copy of aa_label_match except
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89)  * aa_compute_perms is replaced with aa_compute_fperms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90)  * and policy.dfa with file.dfa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91)  ****/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) /* match a profile and its associated ns component if needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93)  * Assumes visibility test has already been done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94)  * If a subns profile is not to be matched should be prescreened with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95)  * visibility test.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) static inline unsigned int match_component(struct aa_profile *profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 					   struct aa_profile *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 					   bool stack, unsigned int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 	const char *ns_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 	if (stack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 		state = aa_dfa_match(profile->file.dfa, state, "&");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	if (profile->ns == tp->ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 		return aa_dfa_match(profile->file.dfa, state, tp->base.hname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 	/* try matching with namespace name and then profile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 	ns_name = aa_ns_name(profile->ns, tp->ns, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	state = aa_dfa_match_len(profile->file.dfa, state, ":", 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 	state = aa_dfa_match(profile->file.dfa, state, ns_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 	state = aa_dfa_match_len(profile->file.dfa, state, ":", 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	return aa_dfa_match(profile->file.dfa, state, tp->base.hname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117)  * label_compound_match - find perms for full compound label
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118)  * @profile: profile to find perms for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119)  * @label: label to check access permissions for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120)  * @stack: whether this is a stacking request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121)  * @start: state to start match in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122)  * @subns: whether to do permission checks on components in a subns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123)  * @request: permissions to request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124)  * @perms: perms struct to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126)  * Returns: 0 on success else ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128)  * For the label A//&B//&C this does the perm match for A//&B//&C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129)  * @perms should be preinitialized with allperms OR a previous permission
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130)  *        check to be stacked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) static int label_compound_match(struct aa_profile *profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 				struct aa_label *label, bool stack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 				unsigned int state, bool subns, u32 request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 				struct aa_perms *perms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 	struct aa_profile *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	struct label_it i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	struct path_cond cond = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	/* find first subcomponent that is visible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	label_for_each(i, label, tp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 		if (!aa_ns_visible(profile->ns, tp->ns, subns))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 		state = match_component(profile, tp, stack, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 		if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 		goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 	/* no component visible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	*perms = allperms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 	label_for_each_cont(i, label, tp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 		if (!aa_ns_visible(profile->ns, tp->ns, subns))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 		state = aa_dfa_match(profile->file.dfa, state, "//&");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 		state = match_component(profile, tp, false, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 		if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	*perms = aa_compute_fperms(profile->file.dfa, state, &cond);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 	aa_apply_modes_to_perms(profile, perms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	if ((perms->allow & request) != request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 		return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	*perms = nullperms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177)  * label_components_match - find perms for all subcomponents of a label
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178)  * @profile: profile to find perms for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179)  * @label: label to check access permissions for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180)  * @stack: whether this is a stacking request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181)  * @start: state to start match in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182)  * @subns: whether to do permission checks on components in a subns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183)  * @request: permissions to request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184)  * @perms: an initialized perms struct to add accumulation to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186)  * Returns: 0 on success else ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188)  * For the label A//&B//&C this does the perm match for each of A and B and C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189)  * @perms should be preinitialized with allperms OR a previous permission
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190)  *        check to be stacked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) static int label_components_match(struct aa_profile *profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 				  struct aa_label *label, bool stack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 				  unsigned int start, bool subns, u32 request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 				  struct aa_perms *perms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	struct aa_profile *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 	struct label_it i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	struct aa_perms tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	struct path_cond cond = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	unsigned int state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	/* find first subcomponent to test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	label_for_each(i, label, tp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 		if (!aa_ns_visible(profile->ns, tp->ns, subns))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 		state = match_component(profile, tp, stack, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 		if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 		goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	/* no subcomponents visible - no change in perms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	tmp = aa_compute_fperms(profile->file.dfa, state, &cond);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	aa_apply_modes_to_perms(profile, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	aa_perms_accum(perms, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	label_for_each_cont(i, label, tp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 		if (!aa_ns_visible(profile->ns, tp->ns, subns))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 		state = match_component(profile, tp, stack, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 		if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 		tmp = aa_compute_fperms(profile->file.dfa, state, &cond);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 		aa_apply_modes_to_perms(profile, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 		aa_perms_accum(perms, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	if ((perms->allow & request) != request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 		return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	*perms = nullperms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242)  * label_match - do a multi-component label match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243)  * @profile: profile to match against (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244)  * @label: label to match (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245)  * @stack: whether this is a stacking request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246)  * @state: state to start in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247)  * @subns: whether to match subns components
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248)  * @request: permission request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249)  * @perms: Returns computed perms (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251)  * Returns: the state the match finished in, may be the none matching state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) static int label_match(struct aa_profile *profile, struct aa_label *label,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 		       bool stack, unsigned int state, bool subns, u32 request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 		       struct aa_perms *perms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	*perms = nullperms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	error = label_compound_match(profile, label, stack, state, subns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 				     request, perms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 	if (!error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	*perms = allperms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	return label_components_match(profile, label, stack, state, subns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 				      request, perms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) /******* end TODO: dedup *****/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273)  * change_profile_perms - find permissions for change_profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274)  * @profile: the current profile  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275)  * @target: label to transition to (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276)  * @stack: whether this is a stacking request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277)  * @request: requested perms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278)  * @start: state to start matching in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281)  * Returns: permission set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283)  * currently only matches full label A//&B//&C or individual components A, B, C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284)  * not arbitrary combinations. Eg. A//&B, C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) static int change_profile_perms(struct aa_profile *profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 				struct aa_label *target, bool stack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 				u32 request, unsigned int start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 				struct aa_perms *perms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 	if (profile_unconfined(profile)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 		perms->allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 		perms->audit = perms->quiet = perms->kill = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	/* TODO: add profile in ns screening */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	return label_match(profile, target, stack, start, true, request, perms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302)  * aa_xattrs_match - check whether a file matches the xattrs defined in profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303)  * @bprm: binprm struct for the process to validate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304)  * @profile: profile to match against (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305)  * @state: state to start match in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307)  * Returns: number of extended attributes that matched, or < 0 on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) static int aa_xattrs_match(const struct linux_binprm *bprm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 			   struct aa_profile *profile, unsigned int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 	ssize_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 	struct dentry *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 	char *value = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	int value_size = 0, ret = profile->xattr_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	if (!bprm || !profile->xattr_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	might_sleep();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	/* transition from exec match to xattr set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	state = aa_dfa_outofband_transition(profile->xmatch, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	d = bprm->file->f_path.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	for (i = 0; i < profile->xattr_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 		size = vfs_getxattr_alloc(d, profile->xattrs[i], &value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 					  value_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 		if (size >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 			u32 perm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 			 * Check the xattr presence before value. This ensure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 			 * that not present xattr can be distinguished from a 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 			 * length value or rule that matches any value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 			state = aa_dfa_null_transition(profile->xmatch, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 			/* Check xattr value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 			state = aa_dfa_match_len(profile->xmatch, state, value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 						 size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 			perm = dfa_user_allow(profile->xmatch, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 			if (!(perm & MAY_EXEC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 				ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 		/* transition to next element */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 		state = aa_dfa_outofband_transition(profile->xmatch, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 		if (size < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 			 * No xattr match, so verify if transition to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 			 * next element was valid. IFF so the xattr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 			 * was optional.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 			if (!state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 				ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 			/* don't count missing optional xattr as matched */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 			ret--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	kfree(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370)  * find_attach - do attachment search for unconfined processes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371)  * @bprm - binprm structure of transitioning task
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372)  * @ns: the current namespace  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373)  * @head - profile list to walk  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374)  * @name - to match against  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375)  * @info - info message if there was an error (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377)  * Do a linear search on the profiles in the list.  There is a matching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378)  * preference where an exact match is preferred over a name which uses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379)  * expressions to match, and matching expressions with the greatest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380)  * xmatch_len are preferred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382)  * Requires: @head not be shared or have appropriate locks held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384)  * Returns: label or NULL if no match found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) static struct aa_label *find_attach(const struct linux_binprm *bprm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 				    struct aa_ns *ns, struct list_head *head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 				    const char *name, const char **info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	int candidate_len = 0, candidate_xattrs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 	bool conflict = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	struct aa_profile *profile, *candidate = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	AA_BUG(!name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 	AA_BUG(!head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) restart:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	list_for_each_entry_rcu(profile, head, base.list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 		if (profile->label.flags & FLAG_NULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 		    &profile->label == ns_unconfined(profile->ns))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 		/* Find the "best" matching profile. Profiles must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 		 * match the path and extended attributes (if any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 		 * associated with the file. A more specific path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 		 * match will be preferred over a less specific one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 		 * and a match with more matching extended attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 		 * will be preferred over one with fewer. If the best
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 		 * match has both the same level of path specificity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 		 * and the same number of matching extended attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 		 * as another profile, signal a conflict and refuse to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 		 * match.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 		if (profile->xmatch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 			unsigned int state, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 			u32 perm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 			state = aa_dfa_leftmatch(profile->xmatch, DFA_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 						 name, &count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 			perm = dfa_user_allow(profile->xmatch, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 			/* any accepting state means a valid match. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 			if (perm & MAY_EXEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 				int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 				if (count < candidate_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 				if (bprm && profile->xattr_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 					long rev = READ_ONCE(ns->revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 					if (!aa_get_profile_not0(profile))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 						goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 					rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 					ret = aa_xattrs_match(bprm, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 							      state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 					rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 					aa_put_profile(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 					if (rev !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 					    READ_ONCE(ns->revision))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 						/* policy changed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 						goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 					/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 					 * Fail matching if the xattrs don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 					 * match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 					 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 					if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 						continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 				 * TODO: allow for more flexible best match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 				 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 				 * The new match isn't more specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 				 * than the current best match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 				if (count == candidate_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 				    ret <= candidate_xattrs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 					/* Match is equivalent, so conflict */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 					if (ret == candidate_xattrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 						conflict = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 				/* Either the same length with more matching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 				 * xattrs, or a longer match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 				candidate = profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 				candidate_len = profile->xmatch_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 				candidate_xattrs = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 				conflict = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 		} else if (!strcmp(profile->base.name, name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 			 * old exact non-re match, without conditionals such
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 			 * as xattrs. no more searching required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 			candidate = profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	if (!candidate || conflict) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 		if (conflict)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 			*info = "conflicting profile attachments";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 		rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	candidate = aa_get_newest_profile(candidate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 	return &candidate->label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) static const char *next_name(int xtype, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502)  * x_table_lookup - lookup an x transition name via transition table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503)  * @profile: current profile (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504)  * @xindex: index into x transition table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505)  * @name: returns: name tested to find label (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507)  * Returns: refcounted label, or NULL on failure (MAYBE NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 				const char **name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	struct aa_label *label = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	u32 xtype = xindex & AA_X_TYPE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	int index = xindex & AA_X_INDEX_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	AA_BUG(!name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	/* index is guaranteed to be in range, validated at load time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	/* TODO: move lookup parsing to unpack time so this is a straight
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	 *       index into the resultant label
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	for (*name = profile->file.trans.table[index]; !label && *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	     *name = next_name(xtype, *name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 		if (xindex & AA_X_CHILD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 			struct aa_profile *new_profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 			/* release by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 			new_profile = aa_find_child(profile, *name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 			if (new_profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 				label = &new_profile->label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 		label = aa_label_parse(&profile->label, *name, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 				       true, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 		if (IS_ERR(label))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 			label = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	/* released by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	return label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544)  * x_to_label - get target label for a given xindex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545)  * @profile: current profile  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546)  * @bprm: binprm structure of transitioning task
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547)  * @name: name to lookup (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548)  * @xindex: index into x transition table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549)  * @lookupname: returns: name used in lookup if one was specified (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551)  * find label for a transition index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553)  * Returns: refcounted label or NULL if not found available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) static struct aa_label *x_to_label(struct aa_profile *profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 				   const struct linux_binprm *bprm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 				   const char *name, u32 xindex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 				   const char **lookupname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 				   const char **info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	struct aa_label *new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	struct aa_ns *ns = profile->ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 	u32 xtype = xindex & AA_X_TYPE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	const char *stack = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	switch (xtype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	case AA_X_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		/* fail exec unless ix || ux fallback - handled by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 		*lookupname = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 	case AA_X_TABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 		/* TODO: fix when perm mapping done at unload */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 		stack = profile->file.trans.table[xindex & AA_X_INDEX_MASK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 		if (*stack != '&') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 			/* released by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 			new = x_table_lookup(profile, xindex, lookupname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 			stack = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		fallthrough;	/* to X_NAME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 	case AA_X_NAME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 		if (xindex & AA_X_CHILD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 			/* released by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 			new = find_attach(bprm, ns, &profile->base.profiles,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 					  name, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 			/* released by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 			new = find_attach(bprm, ns, &ns->base.profiles,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 					  name, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 		*lookupname = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 	if (!new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 		if (xindex & AA_X_INHERIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 			/* (p|c|n)ix - don't change profile but do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 			 * use the newest version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 			*info = "ix fallback";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 			/* no profile && no error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 			new = aa_get_newest_label(&profile->label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 		} else if (xindex & AA_X_UNCONFINED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 			new = aa_get_newest_label(ns_unconfined(profile->ns));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 			*info = "ux fallback";
^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) 	if (new && stack) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		/* base the stack on post domain transition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 		struct aa_label *base = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 		new = aa_label_parse(base, stack, GFP_KERNEL, true, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 		if (IS_ERR(new))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 			new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 		aa_put_label(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 	/* released by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 	return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) static struct aa_label *profile_transition(struct aa_profile *profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 					   const struct linux_binprm *bprm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 					   char *buffer, struct path_cond *cond,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 					   bool *secure_exec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	struct aa_label *new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 	const char *info = NULL, *name = NULL, *target = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 	unsigned int state = profile->file.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 	struct aa_perms perms = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	bool nonewprivs = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	AA_BUG(!profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	AA_BUG(!bprm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	AA_BUG(!buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 			     &name, &info, profile->disconnected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 		if (profile_unconfined(profile) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 		    (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 			AA_DEBUG("name lookup ix on error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 			error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 			new = aa_get_newest_label(&profile->label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 		name = bprm->filename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 		goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	if (profile_unconfined(profile)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 		new = find_attach(bprm, profile->ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 				  &profile->ns->base.profiles, name, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 		if (new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 			AA_DEBUG("unconfined attached to new label");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 			return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 		AA_DEBUG("unconfined exec no attachment");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 		return aa_get_newest_label(&profile->label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 	/* find exec permissions for name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	state = aa_str_perms(profile->file.dfa, state, name, cond, &perms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	if (perms.allow & MAY_EXEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 		/* exec permission determine how to transition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 		new = x_to_label(profile, bprm, name, perms.xindex, &target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 				 &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 		if (new && new->proxy == profile->label.proxy && info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 			/* hack ix fallback - improve how this is detected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 			goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 		} else if (!new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 			error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 			info = "profile transition not found";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 			/* remove MAY_EXEC to audit as failure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 			perms.allow &= ~MAY_EXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	} else if (COMPLAIN_MODE(profile)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 		/* no exec permission - learning mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 		struct aa_profile *new_profile = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 		new_profile = aa_new_null_profile(profile, false, name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 						  GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 		if (!new_profile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 			error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 			info = "could not create null profile";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 			error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 			new = &new_profile->label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 		perms.xindex |= AA_X_UNSAFE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 		/* fail exec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 		error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 	if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 		goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	if (!(perms.xindex & AA_X_UNSAFE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 		if (DEBUG_ON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 			dbg_printk("apparmor: scrubbing environment variables"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 				   " for %s profile=", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 			aa_label_printk(new, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 			dbg_printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		*secure_exec = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) audit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	aa_audit_file(profile, &perms, OP_EXEC, MAY_EXEC, name, target, new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 		      cond->uid, info, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	if (!new || nonewprivs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 		aa_put_label(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 		return ERR_PTR(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 			  bool stack, const struct linux_binprm *bprm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 			  char *buffer, struct path_cond *cond,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 			  bool *secure_exec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	unsigned int state = profile->file.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	struct aa_perms perms = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	const char *xname = NULL, *info = "change_profile onexec";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	int error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	AA_BUG(!profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	AA_BUG(!onexec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	AA_BUG(!bprm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	AA_BUG(!buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 	if (profile_unconfined(profile)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 		/* change_profile on exec already granted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 		 * NOTE: Domain transitions from unconfined are allowed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 		 * even when no_new_privs is set because this aways results
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 		 * in a further reduction of permissions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 			     &xname, &info, profile->disconnected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 		if (profile_unconfined(profile) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 		    (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 			AA_DEBUG("name lookup ix on error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 			error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 		xname = bprm->filename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 		goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	/* find exec permissions for name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	state = aa_str_perms(profile->file.dfa, state, xname, cond, &perms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	if (!(perms.allow & AA_MAY_ONEXEC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 		info = "no change_onexec valid for executable";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 		goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	/* test if this exec can be paired with change_profile onexec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	 * onexec permission is linked to exec with a standard pairing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	 * exec\0change_profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	state = aa_dfa_null_transition(profile->file.dfa, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	error = change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 				     state, &perms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 		perms.allow &= ~AA_MAY_ONEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 		goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	if (!(perms.xindex & AA_X_UNSAFE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 		if (DEBUG_ON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 			dbg_printk("apparmor: scrubbing environment "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 				   "variables for %s label=", xname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 			aa_label_printk(onexec, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 			dbg_printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 		*secure_exec = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) audit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	return aa_audit_file(profile, &perms, OP_EXEC, AA_MAY_ONEXEC, xname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 			     NULL, onexec, cond->uid, info, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) /* ensure none ns domain transitions are correctly applied with onexec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) static struct aa_label *handle_onexec(struct aa_label *label,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 				      struct aa_label *onexec, bool stack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 				      const struct linux_binprm *bprm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 				      char *buffer, struct path_cond *cond,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 				      bool *unsafe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	struct aa_label *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	AA_BUG(!label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	AA_BUG(!onexec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	AA_BUG(!bprm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	AA_BUG(!buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	if (!stack) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 		error = fn_for_each_in_ns(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 				profile_onexec(profile, onexec, stack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 					       bprm, buffer, cond, unsafe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 		if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 			return ERR_PTR(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 		new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 				aa_get_newest_label(onexec),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 				profile_transition(profile, bprm, buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 						   cond, unsafe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 		/* TODO: determine how much we want to loosen this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 		error = fn_for_each_in_ns(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 				profile_onexec(profile, onexec, stack, bprm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 					       buffer, cond, unsafe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 		if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 			return ERR_PTR(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 		new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 				aa_label_merge(&profile->label, onexec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 					       GFP_KERNEL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 				profile_transition(profile, bprm, buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 						   cond, unsafe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	if (new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 		return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	/* TODO: get rid of GLOBAL_ROOT_UID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	error = fn_for_each_in_ns(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 			aa_audit_file(profile, &nullperms, OP_CHANGE_ONEXEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 				      AA_MAY_ONEXEC, bprm->filename, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 				      onexec, GLOBAL_ROOT_UID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 				      "failed to build target label", -ENOMEM));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 	return ERR_PTR(error);
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845)  * apparmor_bprm_creds_for_exec - Update the new creds on the bprm struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846)  * @bprm: binprm for the exec  (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848)  * Returns: %0 or error on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850)  * TODO: once the other paths are done see if we can't refactor into a fn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	struct aa_task_ctx *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 	struct aa_label *label, *new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	char *buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 	const char *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	bool unsafe = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	struct path_cond cond = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 		file_inode(bprm->file)->i_uid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 		file_inode(bprm->file)->i_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	ctx = task_ctx(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	AA_BUG(!cred_label(bprm->cred));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	AA_BUG(!ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	label = aa_get_newest_label(cred_label(bprm->cred));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 	 * Detect no new privs being set, and store the label it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 	 * occurred under. Ideally this would happen when nnp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	 * is set but there isn't a good way to do that yet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	 * Testing for unconfined must be done before the subset test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) && !unconfined(label) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	    !ctx->nnp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 		ctx->nnp = aa_get_label(label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	/* buffer freed below, name is pointer into buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	buffer = aa_get_buffer(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	if (!buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 		error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 	/* Test for onexec first as onexec override other x transitions. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	if (ctx->onexec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 		new = handle_onexec(label, ctx->onexec, ctx->token,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 				    bprm, buffer, &cond, &unsafe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 		new = fn_label_build(label, profile, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 				profile_transition(profile, bprm, buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 						   &cond, &unsafe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	AA_BUG(!new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 	if (IS_ERR(new)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 		error = PTR_ERR(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	} else if (!new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 		error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	/* Policy has specified a domain transitions. If no_new_privs and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	 * confined ensure the transition is to confinement that is subset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	 * of the confinement when the task entered no new privs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	 * NOTE: Domain transitions from unconfined and to stacked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	 * subsets are allowed even when no_new_privs is set because this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	 * aways results in a further reduction of permissions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	    !unconfined(label) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	    !aa_label_is_unconfined_subset(new, ctx->nnp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 		error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 		info = "no new privs";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 		goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	if (bprm->unsafe & LSM_UNSAFE_SHARE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 		/* FIXME: currently don't mediate shared state */
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	if (bprm->unsafe & (LSM_UNSAFE_PTRACE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 		/* TODO: test needs to be profile of label to new */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 		error = may_change_ptraced_domain(new, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 		if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 			goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	if (unsafe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 		if (DEBUG_ON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 			dbg_printk("scrubbing environment variables for %s "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 				   "label=", bprm->filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 			aa_label_printk(new, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 			dbg_printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 		bprm->secureexec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	if (label->proxy != new->proxy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 		/* when transitioning clear unsafe personality bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 		if (DEBUG_ON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 			dbg_printk("apparmor: clearing unsafe personality "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 				   "bits. %s label=", bprm->filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 			aa_label_printk(new, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 			dbg_printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 		bprm->per_clear |= PER_CLEAR_ON_SETID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	aa_put_label(cred_label(bprm->cred));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	/* transfer reference, released when cred is freed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	set_cred_label(bprm->cred, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	aa_put_label(label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	aa_put_buffer(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) audit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	error = fn_for_each(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 			aa_audit_file(profile, &nullperms, OP_EXEC, MAY_EXEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 				      bprm->filename, NULL, new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 				      file_inode(bprm->file)->i_uid, info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 				      error));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	aa_put_label(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977)  * Functions for self directed profile change
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) /* helper fn for change_hat
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983)  * Returns: label for hat transition OR ERR_PTR.  Does NOT return NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) static struct aa_label *build_change_hat(struct aa_profile *profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 					 const char *name, bool sibling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	struct aa_profile *root, *hat = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	const char *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	if (sibling && PROFILE_IS_HAT(profile)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 		root = aa_get_profile_rcu(&profile->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	} else if (!sibling && !PROFILE_IS_HAT(profile)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 		root = aa_get_profile(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 		info = "conflicting target types";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 		error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	hat = aa_find_child(root, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	if (!hat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 		error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 		if (COMPLAIN_MODE(profile)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 			hat = aa_new_null_profile(profile, true, name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 						  GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 			if (!hat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 				info = "failed null profile create";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 				error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	aa_put_profile(root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) audit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	aa_audit_file(profile, &nullperms, OP_CHANGE_HAT, AA_MAY_CHANGEHAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 		      name, hat ? hat->base.hname : NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 		      hat ? &hat->label : NULL, GLOBAL_ROOT_UID, info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 		      error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	if (!hat || (error && error != -ENOENT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 		return ERR_PTR(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 	/* if hat && error - complain mode, already audited and we adjust for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	 * complain mode allow by returning hat->label
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	return &hat->label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) /* helper fn for changing into a hat
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)  * Returns: label for hat transition or ERR_PTR. Does not return NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) static struct aa_label *change_hat(struct aa_label *label, const char *hats[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 				   int count, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 	struct aa_profile *profile, *root, *hat = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 	struct aa_label *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	struct label_it it;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 	bool sibling = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	const char *name, *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	int i, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 	AA_BUG(!label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 	AA_BUG(!hats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 	AA_BUG(count < 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	if (PROFILE_IS_HAT(labels_profile(label)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 		sibling = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	/*find first matching hat */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 	for (i = 0; i < count && !hat; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 		name = hats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 		label_for_each_in_ns(it, labels_ns(label), label, profile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 			if (sibling && PROFILE_IS_HAT(profile)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 				root = aa_get_profile_rcu(&profile->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 			} else if (!sibling && !PROFILE_IS_HAT(profile)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 				root = aa_get_profile(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 			} else {	/* conflicting change type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 				info = "conflicting targets types";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 				error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 				goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 			hat = aa_find_child(root, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 			aa_put_profile(root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 			if (!hat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 				if (!COMPLAIN_MODE(profile))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 					goto outer_continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 				/* complain mode succeed as if hat */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 			} else if (!PROFILE_IS_HAT(hat)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 				info = "target not hat";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 				error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 				aa_put_profile(hat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 				goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 			aa_put_profile(hat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 		/* found a hat for all profiles in ns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 		goto build;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) outer_continue:
^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) 	/* no hats that match, find appropriate error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 	 * In complain mode audit of the failure is based off of the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 	 * hat supplied.  This is done due how userspace interacts with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 	 * change_hat.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 	name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 	label_for_each_in_ns(it, labels_ns(label), label, profile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 		if (!list_empty(&profile->base.profiles)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 			info = "hat not found";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 			error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 	info = "no hats defined";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 	error = -ECHILD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 	label_for_each_in_ns(it, labels_ns(label), label, profile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 		 * no target as it has failed to be found or built
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 		 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 		 * change_hat uses probing and should not log failures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 		 * related to missing hats
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 		/* TODO: get rid of GLOBAL_ROOT_UID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 		if (count > 1 || COMPLAIN_MODE(profile)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 			aa_audit_file(profile, &nullperms, OP_CHANGE_HAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 				      AA_MAY_CHANGEHAT, name, NULL, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 				      GLOBAL_ROOT_UID, info, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 	return ERR_PTR(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) build:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 	new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 				   build_change_hat(profile, name, sibling),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 				   aa_get_label(&profile->label));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	if (!new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 		info = "label build failed";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 		error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 	} /* else if (IS_ERR) build_change_hat has logged error so return new */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)  * aa_change_hat - change hat to/from subprofile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)  * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)  * @count: number of hat names in @hats
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)  * @token: magic value to validate the hat change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)  * @flags: flags affecting behavior of the change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)  * Returns %0 on success, error otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)  * Change to the first profile specified in @hats that exists, and store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)  * the @hat_magic in the current task context.  If the count == 0 and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)  * @token matches that stored in the current task context, return to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)  * top level profile.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)  * change_hat only applies to profiles in the current ns, and each profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)  * in the ns must make the same transition otherwise change_hat will fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) int aa_change_hat(const char *hats[], int count, u64 token, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 	const struct cred *cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	struct aa_task_ctx *ctx = task_ctx(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 	struct aa_label *label, *previous, *new = NULL, *target = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 	struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 	struct aa_perms perms = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 	const char *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 	int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	/* released below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	cred = get_current_cred();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	label = aa_get_newest_cred_label(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	previous = aa_get_newest_label(ctx->previous);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 	 * Detect no new privs being set, and store the label it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	 * occurred under. Ideally this would happen when nnp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 	 * is set but there isn't a good way to do that yet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	 * Testing for unconfined must be done before the subset test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	if (task_no_new_privs(current) && !unconfined(label) && !ctx->nnp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 		ctx->nnp = aa_get_label(label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	if (unconfined(label)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 		info = "unconfined can not change_hat";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 		error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	if (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 		new = change_hat(label, hats, count, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 		AA_BUG(!new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 		if (IS_ERR(new)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 			error = PTR_ERR(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 			new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 			/* already audited */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 		error = may_change_ptraced_domain(new, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 		if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 		 * no new privs prevents domain transitions that would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 		 * reduce restrictions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 		if (task_no_new_privs(current) && !unconfined(label) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 		    !aa_label_is_unconfined_subset(new, ctx->nnp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 			/* not an apparmor denial per se, so don't log it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 			AA_DEBUG("no_new_privs - change_hat denied");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 			error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 		if (flags & AA_CHANGE_TEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 		target = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 		error = aa_set_current_hat(new, token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 		if (error == -EACCES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 			/* kill task in case of brute force attacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 			goto kill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 	} else if (previous && !(flags & AA_CHANGE_TEST)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 		 * no new privs prevents domain transitions that would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 		 * reduce restrictions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 		if (task_no_new_privs(current) && !unconfined(label) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 		    !aa_label_is_unconfined_subset(previous, ctx->nnp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 			/* not an apparmor denial per se, so don't log it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 			AA_DEBUG("no_new_privs - change_hat denied");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 			error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 		/* Return to saved label.  Kill task if restore fails
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 		 * to avoid brute force attacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 		target = previous;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 		error = aa_restore_previous_label(token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 		if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 			if (error == -EACCES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 				goto kill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	} /* else ignore @flags && restores when there is no saved profile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 	aa_put_label(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 	aa_put_label(previous);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 	aa_put_label(label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	put_cred(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) kill:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 	info = "failed token match";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 	perms.kill = AA_MAY_CHANGEHAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 	fn_for_each_in_ns(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 		aa_audit_file(profile, &perms, OP_CHANGE_HAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 			      AA_MAY_CHANGEHAT, NULL, NULL, target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 			      GLOBAL_ROOT_UID, info, error));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 	goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) static int change_profile_perms_wrapper(const char *op, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 					struct aa_profile *profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 					struct aa_label *target, bool stack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 					u32 request, struct aa_perms *perms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 	const char *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 	int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	if (!error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 		error = change_profile_perms(profile, target, stack, request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 					     profile->file.start, perms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 		error = aa_audit_file(profile, perms, op, request, name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 				      NULL, target, GLOBAL_ROOT_UID, info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 				      error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)  * aa_change_profile - perform a one-way profile transition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)  * @fqname: name of profile may include namespace (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)  * @onexec: whether this transition is to take place immediately or at exec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)  * @flags: flags affecting change behavior
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)  * Change to new profile @name.  Unlike with hats, there is no way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)  * to change back.  If @name isn't specified the current profile name is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)  * used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)  * If @onexec then the transition is delayed until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)  * the next exec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)  * Returns %0 on success, error otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) int aa_change_profile(const char *fqname, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 	struct aa_label *label, *new = NULL, *target = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 	struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 	struct aa_perms perms = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	const char *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 	const char *auditname = fqname;		/* retain leading & if stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 	bool stack = flags & AA_CHANGE_STACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 	struct aa_task_ctx *ctx = task_ctx(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 	char *op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 	u32 request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 	label = aa_get_current_label();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 	 * Detect no new privs being set, and store the label it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 	 * occurred under. Ideally this would happen when nnp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 	 * is set but there isn't a good way to do that yet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 	 * Testing for unconfined must be done before the subset test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 	if (task_no_new_privs(current) && !unconfined(label) && !ctx->nnp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 		ctx->nnp = aa_get_label(label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 	if (!fqname || !*fqname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 		aa_put_label(label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 		AA_DEBUG("no profile name");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 	if (flags & AA_CHANGE_ONEXEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 		request = AA_MAY_ONEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 		if (stack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 			op = OP_STACK_ONEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 			op = OP_CHANGE_ONEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 		request = AA_MAY_CHANGE_PROFILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 		if (stack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 			op = OP_STACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 			op = OP_CHANGE_PROFILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 	if (*fqname == '&') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 		stack = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 		/* don't have label_parse() do stacking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 		fqname++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 	target = aa_label_parse(label, fqname, GFP_KERNEL, true, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 	if (IS_ERR(target)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 		struct aa_profile *tprofile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 		info = "label not found";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 		error = PTR_ERR(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 		target = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 		 * TODO: fixme using labels_profile is not right - do profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 		 * per complain profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 		if ((flags & AA_CHANGE_TEST) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 		    !COMPLAIN_MODE(labels_profile(label)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 			goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 		/* released below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 		tprofile = aa_new_null_profile(labels_profile(label), false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 					       fqname, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 		if (!tprofile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 			info = "failed null profile create";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 			error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 			goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 		target = &tprofile->label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 		goto check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 	 * self directed transitions only apply to current policy ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 	 * TODO: currently requiring perms for stacking and straight change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 	 *       stacking doesn't strictly need this. Determine how much
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 	 *       we want to loosen this restriction for stacking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 	 * if (!stack) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 	error = fn_for_each_in_ns(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 			change_profile_perms_wrapper(op, auditname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 						     profile, target, stack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 						     request, &perms));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 		/* auditing done in change_profile_perms_wrapper */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 	/* } */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) check:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 	/* check if tracing task is allowed to trace target domain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 	error = may_change_ptraced_domain(target, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 	if (error && !fn_for_each_in_ns(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 					COMPLAIN_MODE(profile)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 		goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 	/* TODO: add permission check to allow this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 	 * if ((flags & AA_CHANGE_ONEXEC) && !current_is_single_threaded()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 	 *      info = "not a single threaded task";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 	 *      error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 	 *      goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 	 * }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 	if (flags & AA_CHANGE_TEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 	/* stacking is always a subset, so only check the nonstack case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 	if (!stack) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 		new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 					   aa_get_label(target),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 					   aa_get_label(&profile->label));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 		 * no new privs prevents domain transitions that would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 		 * reduce restrictions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 		if (task_no_new_privs(current) && !unconfined(label) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 		    !aa_label_is_unconfined_subset(new, ctx->nnp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 			/* not an apparmor denial per se, so don't log it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 			AA_DEBUG("no_new_privs - change_hat denied");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 			error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 	if (!(flags & AA_CHANGE_ONEXEC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 		/* only transition profiles in the current ns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 		if (stack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 			new = aa_label_merge(label, target, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 		if (IS_ERR_OR_NULL(new)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 			info = "failed to build target label";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 			if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 				error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 				error = PTR_ERR(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 			new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 			perms.allow = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 			goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 		error = aa_replace_current_label(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 		if (new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 			aa_put_label(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 			new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 		/* full transition will be built in exec path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 		error = aa_set_current_onexec(target, stack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) audit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 	error = fn_for_each_in_ns(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 			aa_audit_file(profile, &perms, op, request, auditname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 				      NULL, new ? new : target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 				      GLOBAL_ROOT_UID, info, error));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 	aa_put_label(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 	aa_put_label(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 	aa_put_label(label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) }