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