xref: /openbmc/linux/security/apparmor/ipc.c (revision 690f33e1)
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 
map_signal_num(int sig)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  */
audit_signal_mask(u32 mask)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  */
audit_signal_cb(struct audit_buffer * ab,void * va)52cd1dbf76SJohn Johansen static void audit_signal_cb(struct audit_buffer *ab, void *va)
53cd1dbf76SJohn Johansen {
54cd1dbf76SJohn Johansen 	struct common_audit_data *sa = va;
55c57bc80fSJohn Johansen 	struct apparmor_audit_data *ad = aad(sa);
56cd1dbf76SJohn Johansen 
57c57bc80fSJohn Johansen 	if (ad->request & AA_SIGNAL_PERM_MASK) {
58f1d9b23cSRichard Guy Briggs 		audit_log_format(ab, " requested_mask=\"%s\"",
59c57bc80fSJohn Johansen 				 audit_signal_mask(ad->request));
60c57bc80fSJohn Johansen 		if (ad->denied & AA_SIGNAL_PERM_MASK) {
61f1d9b23cSRichard Guy Briggs 			audit_log_format(ab, " denied_mask=\"%s\"",
62c57bc80fSJohn Johansen 					 audit_signal_mask(ad->denied));
63cd1dbf76SJohn Johansen 		}
64cd1dbf76SJohn Johansen 	}
65c57bc80fSJohn Johansen 	if (ad->signal == SIGUNKNOWN)
663acfd5f5SJohn Johansen 		audit_log_format(ab, "signal=unknown(%d)",
67c57bc80fSJohn Johansen 				 ad->unmappedsig);
68c57bc80fSJohn Johansen 	else if (ad->signal < MAXMAPPED_SIGNAME)
69c57bc80fSJohn Johansen 		audit_log_format(ab, " signal=%s", sig_names[ad->signal]);
70cd1dbf76SJohn Johansen 	else
71cd1dbf76SJohn Johansen 		audit_log_format(ab, " signal=rtmin+%d",
72c57bc80fSJohn Johansen 				 ad->signal - SIGRT_BASE);
73cd1dbf76SJohn Johansen 	audit_log_format(ab, " peer=");
7430b3669dSJohn Johansen 	aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer,
75cd1dbf76SJohn Johansen 			FLAGS_NONE, GFP_ATOMIC);
76cd1dbf76SJohn Johansen }
77cd1dbf76SJohn Johansen 
profile_signal_perm(const struct cred * cred,struct aa_profile * profile,struct aa_label * peer,u32 request,struct apparmor_audit_data * ad)78*690f33e1SJohn Johansen static int profile_signal_perm(const struct cred *cred,
79*690f33e1SJohn Johansen 			       struct aa_profile *profile,
803dc6b1ceSJohn Johansen 			       struct aa_label *peer, u32 request,
81c57bc80fSJohn Johansen 			       struct apparmor_audit_data *ad)
82cd1dbf76SJohn Johansen {
831ad22fccSJohn Johansen 	struct aa_ruleset *rules = list_first_entry(&profile->rules,
841ad22fccSJohn Johansen 						    typeof(*rules), list);
85cd1dbf76SJohn Johansen 	struct aa_perms perms;
8633fc95d8SJohn Johansen 	aa_state_t state;
87cd1dbf76SJohn Johansen 
88cd1dbf76SJohn Johansen 	if (profile_unconfined(profile) ||
891ad22fccSJohn Johansen 	    !ANY_RULE_MEDIATES(&profile->rules, AA_CLASS_SIGNAL))
90cd1dbf76SJohn Johansen 		return 0;
91cd1dbf76SJohn Johansen 
92*690f33e1SJohn Johansen 	ad->subj_cred = cred;
93c57bc80fSJohn Johansen 	ad->peer = peer;
943dc6b1ceSJohn Johansen 	/* TODO: secondary cache check <profile, profile, perm> */
95217af7e2SJohn Johansen 	state = aa_dfa_next(rules->policy.dfa,
96217af7e2SJohn Johansen 			    rules->policy.start[AA_CLASS_SIGNAL],
97c57bc80fSJohn Johansen 			    ad->signal);
98217af7e2SJohn Johansen 	aa_label_match(profile, rules, peer, state, false, request, &perms);
99cd1dbf76SJohn Johansen 	aa_apply_modes_to_perms(profile, &perms);
100c57bc80fSJohn Johansen 	return aa_check_perms(profile, &perms, request, ad, audit_signal_cb);
101cd1dbf76SJohn Johansen }
102cd1dbf76SJohn Johansen 
aa_may_signal(const struct cred * subj_cred,struct aa_label * sender,const struct cred * target_cred,struct aa_label * target,int sig)103*690f33e1SJohn Johansen int aa_may_signal(const struct cred *subj_cred, struct aa_label *sender,
104*690f33e1SJohn Johansen 		  const struct cred *target_cred, struct aa_label *target,
105*690f33e1SJohn Johansen 		  int sig)
106cd1dbf76SJohn Johansen {
1073dc6b1ceSJohn Johansen 	struct aa_profile *profile;
108c57bc80fSJohn Johansen 	DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_SIGNAL, OP_SIGNAL);
109cd1dbf76SJohn Johansen 
110c57bc80fSJohn Johansen 	ad.signal = map_signal_num(sig);
111c57bc80fSJohn Johansen 	ad.unmappedsig = sig;
1123dc6b1ceSJohn Johansen 	return xcheck_labels(sender, target, profile,
113*690f33e1SJohn Johansen 			     profile_signal_perm(subj_cred, profile, target,
114*690f33e1SJohn Johansen 						 MAY_WRITE, &ad),
115*690f33e1SJohn Johansen 			     profile_signal_perm(target_cred, profile, sender,
116*690f33e1SJohn Johansen 						 MAY_READ, &ad));
117cd1dbf76SJohn Johansen }
118