xref: /openbmc/linux/security/apparmor/ipc.c (revision c57bc80f4508acd8c52bd89b01d324889065320d)
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 /**
48a2217387SJiapeng 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;
55*c57bc80fSJohn Johansen 	struct apparmor_audit_data *ad = aad(sa);
56cd1dbf76SJohn Johansen 
57*c57bc80fSJohn Johansen 	if (ad->request & AA_SIGNAL_PERM_MASK) {
58f1d9b23cSRichard Guy Briggs 		audit_log_format(ab, " requested_mask=\"%s\"",
59*c57bc80fSJohn Johansen 				 audit_signal_mask(ad->request));
60*c57bc80fSJohn Johansen 		if (ad->denied & AA_SIGNAL_PERM_MASK) {
61f1d9b23cSRichard Guy Briggs 			audit_log_format(ab, " denied_mask=\"%s\"",
62*c57bc80fSJohn Johansen 					 audit_signal_mask(ad->denied));
63cd1dbf76SJohn Johansen 		}
64cd1dbf76SJohn Johansen 	}
65*c57bc80fSJohn Johansen 	if (ad->signal == SIGUNKNOWN)
663acfd5f5SJohn Johansen 		audit_log_format(ab, "signal=unknown(%d)",
67*c57bc80fSJohn Johansen 				 ad->unmappedsig);
68*c57bc80fSJohn Johansen 	else if (ad->signal < MAXMAPPED_SIGNAME)
69*c57bc80fSJohn Johansen 		audit_log_format(ab, " signal=%s", sig_names[ad->signal]);
70cd1dbf76SJohn Johansen 	else
71cd1dbf76SJohn Johansen 		audit_log_format(ab, " signal=rtmin+%d",
72*c57bc80fSJohn Johansen 				 ad->signal - SIGRT_BASE);
73cd1dbf76SJohn Johansen 	audit_log_format(ab, " peer=");
74*c57bc80fSJohn Johansen 	aa_label_xaudit(ab, labels_ns(ad->label), ad->peer,
75cd1dbf76SJohn Johansen 			FLAGS_NONE, GFP_ATOMIC);
76cd1dbf76SJohn Johansen }
77cd1dbf76SJohn Johansen 
78cd1dbf76SJohn Johansen static int profile_signal_perm(struct aa_profile *profile,
793dc6b1ceSJohn Johansen 			       struct aa_label *peer, u32 request,
80*c57bc80fSJohn Johansen 			       struct apparmor_audit_data *ad)
81cd1dbf76SJohn Johansen {
821ad22fccSJohn Johansen 	struct aa_ruleset *rules = list_first_entry(&profile->rules,
831ad22fccSJohn Johansen 						    typeof(*rules), list);
84cd1dbf76SJohn Johansen 	struct aa_perms perms;
8533fc95d8SJohn Johansen 	aa_state_t state;
86cd1dbf76SJohn Johansen 
87cd1dbf76SJohn Johansen 	if (profile_unconfined(profile) ||
881ad22fccSJohn Johansen 	    !ANY_RULE_MEDIATES(&profile->rules, AA_CLASS_SIGNAL))
89cd1dbf76SJohn Johansen 		return 0;
90cd1dbf76SJohn Johansen 
91*c57bc80fSJohn Johansen 	ad->peer = peer;
923dc6b1ceSJohn Johansen 	/* TODO: secondary cache check <profile, profile, perm> */
93217af7e2SJohn Johansen 	state = aa_dfa_next(rules->policy.dfa,
94217af7e2SJohn Johansen 			    rules->policy.start[AA_CLASS_SIGNAL],
95*c57bc80fSJohn Johansen 			    ad->signal);
96217af7e2SJohn Johansen 	aa_label_match(profile, rules, peer, state, false, request, &perms);
97cd1dbf76SJohn Johansen 	aa_apply_modes_to_perms(profile, &perms);
98*c57bc80fSJohn Johansen 	return aa_check_perms(profile, &perms, request, ad, audit_signal_cb);
99cd1dbf76SJohn Johansen }
100cd1dbf76SJohn Johansen 
101cd1dbf76SJohn Johansen int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig)
102cd1dbf76SJohn Johansen {
1033dc6b1ceSJohn Johansen 	struct aa_profile *profile;
104*c57bc80fSJohn Johansen 	DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_SIGNAL, OP_SIGNAL);
105cd1dbf76SJohn Johansen 
106*c57bc80fSJohn Johansen 	ad.signal = map_signal_num(sig);
107*c57bc80fSJohn Johansen 	ad.unmappedsig = sig;
1083dc6b1ceSJohn Johansen 	return xcheck_labels(sender, target, profile,
109*c57bc80fSJohn Johansen 			profile_signal_perm(profile, target, MAY_WRITE, &ad),
110*c57bc80fSJohn Johansen 			profile_signal_perm(profile, sender, MAY_READ, &ad));
111cd1dbf76SJohn Johansen }
112