Commit | Line | Data |
---|---|---|
b886d83c | 1 | // SPDX-License-Identifier: GPL-2.0-only |
0ed3b28a JJ |
2 | /* |
3 | * AppArmor security module | |
4 | * | |
5 | * This file contains AppArmor ipc mediation | |
6 | * | |
7 | * Copyright (C) 1998-2008 Novell/SUSE | |
b2d09ae4 | 8 | * Copyright 2009-2017 Canonical Ltd. |
0ed3b28a JJ |
9 | */ |
10 | ||
11 | #include <linux/gfp.h> | |
0ed3b28a JJ |
12 | |
13 | #include "include/audit.h" | |
14 | #include "include/capability.h" | |
d8889d49 | 15 | #include "include/cred.h" |
0ed3b28a | 16 | #include "include/policy.h" |
33f8bf58 | 17 | #include "include/ipc.h" |
cd1dbf76 | 18 | #include "include/sig_names.h" |
0ed3b28a | 19 | |
0ed3b28a | 20 | |
cd1dbf76 JJ |
21 | static inline int map_signal_num(int sig) |
22 | { | |
23 | if (sig > SIGRTMAX) | |
24 | return SIGUNKNOWN; | |
25 | else if (sig >= SIGRTMIN) | |
3acfd5f5 | 26 | return sig - SIGRTMIN + SIGRT_BASE; |
f7dc4c9a | 27 | else if (sig < MAXMAPPED_SIG) |
cd1dbf76 JJ |
28 | return sig_map[sig]; |
29 | return SIGUNKNOWN; | |
30 | } | |
31 | ||
32 | /** | |
f1d9b23c | 33 | * audit_signal_mask - convert mask to permission string |
cd1dbf76 | 34 | * @mask: permission mask to convert |
f1d9b23c RGB |
35 | * |
36 | * Returns: pointer to static string | |
cd1dbf76 | 37 | */ |
f1d9b23c | 38 | static const char *audit_signal_mask(u32 mask) |
cd1dbf76 JJ |
39 | { |
40 | if (mask & MAY_READ) | |
f1d9b23c | 41 | return "receive"; |
cd1dbf76 | 42 | if (mask & MAY_WRITE) |
f1d9b23c RGB |
43 | return "send"; |
44 | return ""; | |
cd1dbf76 JJ |
45 | } |
46 | ||
47 | /** | |
a2217387 | 48 | * audit_signal_cb() - call back for signal specific audit fields |
cd1dbf76 JJ |
49 | * @ab: audit_buffer (NOT NULL) |
50 | * @va: audit struct to audit values of (NOT NULL) | |
51 | */ | |
52 | static void audit_signal_cb(struct audit_buffer *ab, void *va) | |
53 | { | |
54 | struct common_audit_data *sa = va; | |
55 | ||
56 | if (aad(sa)->request & AA_SIGNAL_PERM_MASK) { | |
f1d9b23c RGB |
57 | audit_log_format(ab, " requested_mask=\"%s\"", |
58 | audit_signal_mask(aad(sa)->request)); | |
cd1dbf76 | 59 | if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) { |
f1d9b23c RGB |
60 | audit_log_format(ab, " denied_mask=\"%s\"", |
61 | audit_signal_mask(aad(sa)->denied)); | |
cd1dbf76 JJ |
62 | } |
63 | } | |
3acfd5f5 JJ |
64 | if (aad(sa)->signal == SIGUNKNOWN) |
65 | audit_log_format(ab, "signal=unknown(%d)", | |
66 | aad(sa)->unmappedsig); | |
67 | else if (aad(sa)->signal < MAXMAPPED_SIGNAME) | |
cd1dbf76 JJ |
68 | audit_log_format(ab, " signal=%s", sig_names[aad(sa)->signal]); |
69 | else | |
70 | audit_log_format(ab, " signal=rtmin+%d", | |
3acfd5f5 | 71 | aad(sa)->signal - SIGRT_BASE); |
cd1dbf76 JJ |
72 | audit_log_format(ab, " peer="); |
73 | aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, | |
74 | FLAGS_NONE, GFP_ATOMIC); | |
75 | } | |
76 | ||
cd1dbf76 | 77 | static int profile_signal_perm(struct aa_profile *profile, |
3dc6b1ce | 78 | struct aa_label *peer, u32 request, |
cd1dbf76 JJ |
79 | struct common_audit_data *sa) |
80 | { | |
1ad22fcc JJ |
81 | struct aa_ruleset *rules = list_first_entry(&profile->rules, |
82 | typeof(*rules), list); | |
cd1dbf76 | 83 | struct aa_perms perms; |
33fc95d8 | 84 | aa_state_t state; |
cd1dbf76 JJ |
85 | |
86 | if (profile_unconfined(profile) || | |
1ad22fcc | 87 | !ANY_RULE_MEDIATES(&profile->rules, AA_CLASS_SIGNAL)) |
cd1dbf76 JJ |
88 | return 0; |
89 | ||
3dc6b1ce JJ |
90 | aad(sa)->peer = peer; |
91 | /* TODO: secondary cache check <profile, profile, perm> */ | |
217af7e2 JJ |
92 | state = aa_dfa_next(rules->policy.dfa, |
93 | rules->policy.start[AA_CLASS_SIGNAL], | |
3dc6b1ce | 94 | aad(sa)->signal); |
217af7e2 | 95 | aa_label_match(profile, rules, peer, state, false, request, &perms); |
cd1dbf76 JJ |
96 | aa_apply_modes_to_perms(profile, &perms); |
97 | return aa_check_perms(profile, &perms, request, sa, audit_signal_cb); | |
98 | } | |
99 | ||
cd1dbf76 JJ |
100 | int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig) |
101 | { | |
3dc6b1ce | 102 | struct aa_profile *profile; |
8c4b785a | 103 | DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_SIGNAL, OP_SIGNAL); |
cd1dbf76 JJ |
104 | |
105 | aad(&sa)->signal = map_signal_num(sig); | |
3acfd5f5 | 106 | aad(&sa)->unmappedsig = sig; |
3dc6b1ce JJ |
107 | return xcheck_labels(sender, target, profile, |
108 | profile_signal_perm(profile, target, MAY_WRITE, &sa), | |
109 | profile_signal_perm(profile, sender, MAY_READ, &sa)); | |
cd1dbf76 | 110 | } |