xref: /openbmc/linux/security/apparmor/ipc.c (revision a2217387c3ec09117b3b6eaa5ec8a0d7d347d4ba)
1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20ed3b28aSJohn Johansen /*
30ed3b28aSJohn Johansen  * AppArmor security module
40ed3b28aSJohn Johansen  *
50ed3b28aSJohn Johansen  * This file contains AppArmor ipc mediation
60ed3b28aSJohn Johansen  *
70ed3b28aSJohn Johansen  * Copyright (C) 1998-2008 Novell/SUSE
8b2d09ae4SJohn Johansen  * Copyright 2009-2017 Canonical Ltd.
90ed3b28aSJohn Johansen  */
100ed3b28aSJohn Johansen 
110ed3b28aSJohn Johansen #include <linux/gfp.h>
120ed3b28aSJohn Johansen 
130ed3b28aSJohn Johansen #include "include/audit.h"
140ed3b28aSJohn Johansen #include "include/capability.h"
15d8889d49SJohn Johansen #include "include/cred.h"
160ed3b28aSJohn Johansen #include "include/policy.h"
1733f8bf58SJames Morris #include "include/ipc.h"
18cd1dbf76SJohn Johansen #include "include/sig_names.h"
190ed3b28aSJohn Johansen 
200ed3b28aSJohn Johansen 
21cd1dbf76SJohn Johansen static inline int map_signal_num(int sig)
22cd1dbf76SJohn Johansen {
23cd1dbf76SJohn Johansen 	if (sig > SIGRTMAX)
24cd1dbf76SJohn Johansen 		return SIGUNKNOWN;
25cd1dbf76SJohn Johansen 	else if (sig >= SIGRTMIN)
263acfd5f5SJohn Johansen 		return sig - SIGRTMIN + SIGRT_BASE;
27f7dc4c9aSJohn Johansen 	else if (sig < MAXMAPPED_SIG)
28cd1dbf76SJohn Johansen 		return sig_map[sig];
29cd1dbf76SJohn Johansen 	return SIGUNKNOWN;
30cd1dbf76SJohn Johansen }
31cd1dbf76SJohn Johansen 
32cd1dbf76SJohn Johansen /**
33f1d9b23cSRichard Guy Briggs  * audit_signal_mask - convert mask to permission string
34cd1dbf76SJohn Johansen  * @mask: permission mask to convert
35f1d9b23cSRichard Guy Briggs  *
36f1d9b23cSRichard Guy Briggs  * Returns: pointer to static string
37cd1dbf76SJohn Johansen  */
38f1d9b23cSRichard Guy Briggs static const char *audit_signal_mask(u32 mask)
39cd1dbf76SJohn Johansen {
40cd1dbf76SJohn Johansen 	if (mask & MAY_READ)
41f1d9b23cSRichard Guy Briggs 		return "receive";
42cd1dbf76SJohn Johansen 	if (mask & MAY_WRITE)
43f1d9b23cSRichard Guy Briggs 		return "send";
44f1d9b23cSRichard Guy Briggs 	return "";
45cd1dbf76SJohn Johansen }
46cd1dbf76SJohn Johansen 
47cd1dbf76SJohn Johansen /**
48*a2217387SJiapeng Chong  * audit_signal_cb() - call back for signal specific audit fields
49cd1dbf76SJohn Johansen  * @ab: audit_buffer  (NOT NULL)
50cd1dbf76SJohn Johansen  * @va: audit struct to audit values of  (NOT NULL)
51cd1dbf76SJohn Johansen  */
52cd1dbf76SJohn Johansen static void audit_signal_cb(struct audit_buffer *ab, void *va)
53cd1dbf76SJohn Johansen {
54cd1dbf76SJohn Johansen 	struct common_audit_data *sa = va;
55cd1dbf76SJohn Johansen 
56cd1dbf76SJohn Johansen 	if (aad(sa)->request & AA_SIGNAL_PERM_MASK) {
57f1d9b23cSRichard Guy Briggs 		audit_log_format(ab, " requested_mask=\"%s\"",
58f1d9b23cSRichard Guy Briggs 				 audit_signal_mask(aad(sa)->request));
59cd1dbf76SJohn Johansen 		if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) {
60f1d9b23cSRichard Guy Briggs 			audit_log_format(ab, " denied_mask=\"%s\"",
61f1d9b23cSRichard Guy Briggs 					 audit_signal_mask(aad(sa)->denied));
62cd1dbf76SJohn Johansen 		}
63cd1dbf76SJohn Johansen 	}
643acfd5f5SJohn Johansen 	if (aad(sa)->signal == SIGUNKNOWN)
653acfd5f5SJohn Johansen 		audit_log_format(ab, "signal=unknown(%d)",
663acfd5f5SJohn Johansen 				 aad(sa)->unmappedsig);
673acfd5f5SJohn Johansen 	else if (aad(sa)->signal < MAXMAPPED_SIGNAME)
68cd1dbf76SJohn Johansen 		audit_log_format(ab, " signal=%s", sig_names[aad(sa)->signal]);
69cd1dbf76SJohn Johansen 	else
70cd1dbf76SJohn Johansen 		audit_log_format(ab, " signal=rtmin+%d",
713acfd5f5SJohn Johansen 				 aad(sa)->signal - SIGRT_BASE);
72cd1dbf76SJohn Johansen 	audit_log_format(ab, " peer=");
73cd1dbf76SJohn Johansen 	aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
74cd1dbf76SJohn Johansen 			FLAGS_NONE, GFP_ATOMIC);
75cd1dbf76SJohn Johansen }
76cd1dbf76SJohn Johansen 
77cd1dbf76SJohn Johansen static int profile_signal_perm(struct aa_profile *profile,
783dc6b1ceSJohn Johansen 			       struct aa_label *peer, u32 request,
79cd1dbf76SJohn Johansen 			       struct common_audit_data *sa)
80cd1dbf76SJohn Johansen {
811ad22fccSJohn Johansen 	struct aa_ruleset *rules = list_first_entry(&profile->rules,
821ad22fccSJohn Johansen 						    typeof(*rules), list);
83cd1dbf76SJohn Johansen 	struct aa_perms perms;
8433fc95d8SJohn Johansen 	aa_state_t state;
85cd1dbf76SJohn Johansen 
86cd1dbf76SJohn Johansen 	if (profile_unconfined(profile) ||
871ad22fccSJohn Johansen 	    !ANY_RULE_MEDIATES(&profile->rules, AA_CLASS_SIGNAL))
88cd1dbf76SJohn Johansen 		return 0;
89cd1dbf76SJohn Johansen 
903dc6b1ceSJohn Johansen 	aad(sa)->peer = peer;
913dc6b1ceSJohn Johansen 	/* TODO: secondary cache check <profile, profile, perm> */
92217af7e2SJohn Johansen 	state = aa_dfa_next(rules->policy.dfa,
93217af7e2SJohn Johansen 			    rules->policy.start[AA_CLASS_SIGNAL],
943dc6b1ceSJohn Johansen 			    aad(sa)->signal);
95217af7e2SJohn Johansen 	aa_label_match(profile, rules, peer, state, false, request, &perms);
96cd1dbf76SJohn Johansen 	aa_apply_modes_to_perms(profile, &perms);
97cd1dbf76SJohn Johansen 	return aa_check_perms(profile, &perms, request, sa, audit_signal_cb);
98cd1dbf76SJohn Johansen }
99cd1dbf76SJohn Johansen 
100cd1dbf76SJohn Johansen int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig)
101cd1dbf76SJohn Johansen {
1023dc6b1ceSJohn Johansen 	struct aa_profile *profile;
1038c4b785aSJohn Johansen 	DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_SIGNAL, OP_SIGNAL);
104cd1dbf76SJohn Johansen 
105cd1dbf76SJohn Johansen 	aad(&sa)->signal = map_signal_num(sig);
1063acfd5f5SJohn Johansen 	aad(&sa)->unmappedsig = sig;
1073dc6b1ceSJohn Johansen 	return xcheck_labels(sender, target, profile,
1083dc6b1ceSJohn Johansen 			profile_signal_perm(profile, target, MAY_WRITE, &sa),
1093dc6b1ceSJohn Johansen 			profile_signal_perm(profile, sender, MAY_READ, &sa));
110cd1dbf76SJohn Johansen }
111