1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * AppArmor security module
4 *
5 * This file contains AppArmor network mediation
6 *
7 * Copyright (C) 1998-2008 Novell/SUSE
8 * Copyright 2009-2017 Canonical Ltd.
9 */
10
11 #include "include/af_unix.h"
12 #include "include/af_inet.h"
13 #include "include/apparmor.h"
14 #include "include/audit.h"
15 #include "include/cred.h"
16 #include "include/label.h"
17 #include "include/net.h"
18 #include "include/policy.h"
19 #include "include/secid.h"
20
21 #include "net_names.h"
22
23
24 struct aa_sfs_entry aa_sfs_entry_network[] = {
25 AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK),
26 AA_SFS_FILE_BOOLEAN("tcp-fast-open", 1),
27 { }
28 };
29
30 struct aa_sfs_entry aa_sfs_entry_networkv9[] = {
31 AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK),
32 AA_SFS_FILE_BOOLEAN("af_unix", 1),
33 AA_SFS_FILE_BOOLEAN("tcp-fast-open", 1),
34 { }
35 };
36
37 static const char * const net_mask_names[] = {
38 "unknown",
39 "send",
40 "receive",
41 "unknown",
42
43 "create",
44 "shutdown",
45 "connect",
46 "unknown",
47
48 "setattr",
49 "getattr",
50 "setcred",
51 "getcred",
52
53 "chmod",
54 "chown",
55 "chgrp",
56 "lock",
57
58 "mmap",
59 "mprot",
60 "unknown",
61 "unknown",
62
63 "accept",
64 "bind",
65 "listen",
66 "unknown",
67
68 "setopt",
69 "getopt",
70 "unknown",
71 "unknown",
72
73 "unknown",
74 "unknown",
75 "unknown",
76 "unknown",
77 };
78
audit_unix_addr(struct audit_buffer * ab,const char * str,struct sockaddr_un * addr,int addrlen)79 static void audit_unix_addr(struct audit_buffer *ab, const char *str,
80 struct sockaddr_un *addr, int addrlen)
81 {
82 int len = unix_addr_len(addrlen);
83
84 if (!addr || len <= 0) {
85 audit_log_format(ab, " %s=none", str);
86 } else if (addr->sun_path[0]) {
87 audit_log_format(ab, " %s=", str);
88 audit_log_untrustedstring(ab, addr->sun_path);
89 } else {
90 audit_log_format(ab, " %s=\"@", str);
91 if (audit_string_contains_control(&addr->sun_path[1], len - 1))
92 audit_log_n_hex(ab, &addr->sun_path[1], len - 1);
93 else
94 audit_log_format(ab, "%.*s", len - 1,
95 &addr->sun_path[1]);
96 audit_log_format(ab, "\"");
97 }
98 }
99
audit_unix_sk_addr(struct audit_buffer * ab,const char * str,const struct sock * sk)100 static void audit_unix_sk_addr(struct audit_buffer *ab, const char *str,
101 const struct sock *sk)
102 {
103 const struct unix_sock *u = unix_sk(sk);
104
105 if (u && u->addr) {
106 int addrlen;
107 struct sockaddr_un *addr = aa_sunaddr(u, &addrlen);
108
109 audit_unix_addr(ab, str, addr, addrlen);
110 } else {
111 audit_unix_addr(ab, str, NULL, 0);
112
113 }
114 }
115
116 /* audit callback for net specific fields */
audit_net_cb(struct audit_buffer * ab,void * va)117 void audit_net_cb(struct audit_buffer *ab, void *va)
118 {
119 struct common_audit_data *sa = va;
120 struct apparmor_audit_data *ad = aad(sa);
121
122 if (address_family_names[ad->common.u.net->family])
123 audit_log_format(ab, " family=\"%s\"",
124 address_family_names[ad->common.u.net->family]);
125 else
126 audit_log_format(ab, " family=\"unknown(%d)\"",
127 ad->common.u.net->family);
128 if (sock_type_names[ad->net.type])
129 audit_log_format(ab, " sock_type=\"%s\"",
130 sock_type_names[ad->net.type]);
131 else
132 audit_log_format(ab, " sock_type=\"unknown(%d)\"",
133 ad->net.type);
134 audit_log_format(ab, " protocol=%d", ad->net.protocol);
135
136 if (ad->request & NET_PERMS_MASK) {
137 audit_log_format(ab, " requested=");
138 aa_audit_perm_mask(ab, ad->request, NULL, 0,
139 net_mask_names, NET_PERMS_MASK);
140
141 if (ad->denied & NET_PERMS_MASK) {
142 audit_log_format(ab, " denied=");
143 aa_audit_perm_mask(ab, ad->denied, NULL, 0,
144 net_mask_names, NET_PERMS_MASK);
145 }
146 }
147 if (ad->common.u.net->family == PF_UNIX) {
148 if (ad->net.addr || !ad->common.u.net->sk)
149 audit_unix_addr(ab, "addr",
150 unix_addr(ad->net.addr),
151 ad->net.addrlen);
152 else
153 audit_unix_sk_addr(ab, "addr", ad->common.u.net->sk);
154 if (ad->request & NET_PEER_MASK) {
155 audit_unix_addr(ab, "peer_addr",
156 unix_addr(ad->net.peer.addr),
157 ad->net.peer.addrlen);
158 }
159 }
160 if (ad->peer) {
161 audit_log_format(ab, " peer=");
162 aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer,
163 FLAGS_NONE, GFP_ATOMIC);
164 }
165 }
166
167 /* standard permission lookup pattern - supports early bailout */
aa_do_perms(struct aa_profile * profile,struct aa_policydb * policy,aa_state_t state,u32 request,const struct aa_perms * p,struct apparmor_audit_data * ad)168 int aa_do_perms(struct aa_profile *profile, struct aa_policydb *policy,
169 aa_state_t state, u32 request,
170 const struct aa_perms *p, struct apparmor_audit_data *ad)
171 {
172 struct aa_perms perms;
173
174 AA_BUG(!profile);
175 AA_BUG(!policy);
176
177
178 if (state || !p)
179 p = aa_lookup_perms(policy, state);
180 perms = *p;
181 aa_apply_modes_to_perms(profile, &perms);
182 return aa_check_perms(profile, &perms, request, ad,
183 audit_net_cb);
184 }
185
186 /* only continue match if
187 * insufficient current perms at current state
188 * indicates there are more perms in later state
189 * Returns: perms struct if early match
190 */
early_match(struct aa_policydb * policy,aa_state_t state,u32 request)191 static struct aa_perms *early_match(struct aa_policydb *policy,
192 aa_state_t state, u32 request)
193 {
194 struct aa_perms *p;
195
196 p = aa_lookup_perms(policy, state);
197 if (((p->allow & request) != request) && (p->allow & AA_CONT_MATCH))
198 return NULL;
199 return p;
200 }
201
aa_dfa_match_be16(const struct aa_dfa * dfa,aa_state_t state,u16 data)202 static aa_state_t aa_dfa_match_be16(const struct aa_dfa *dfa, aa_state_t state,
203 u16 data)
204 {
205 __be16 buffer = cpu_to_be16(data);
206
207 return aa_dfa_match_len(dfa, state, (char *) &buffer, 2);
208 }
209
210 /**
211 * aa_match_to_prot - match the af, type, protocol triplet
212 * @policy: policy being matched
213 * @state: state to start in
214 * @request: permissions being requested, ignored if @p == NULL
215 * @af: socket address family
216 * @type: socket type
217 * @protocol: socket protocol
218 * @p: output - pointer to permission associated with match
219 * @info: output - pointer to string describing failure
220 *
221 * RETURNS: state match stopped in.
222 *
223 * If @(p) is assigned a value the returned state will be the
224 * corresponding state. Will not set @p on failure or if match completes
225 * only if an early match occurs
226 */
aa_match_to_prot(struct aa_policydb * policy,aa_state_t state,u32 request,u16 af,int type,int protocol,struct aa_perms ** p,const char ** info)227 aa_state_t aa_match_to_prot(struct aa_policydb *policy, aa_state_t state,
228 u32 request, u16 af, int type, int protocol,
229 struct aa_perms **p, const char **info)
230 {
231 state = aa_dfa_match_be16(policy->dfa, state, (u16)af);
232 if (!state) {
233 *info = "failed af match";
234 return state;
235 }
236 state = aa_dfa_match_be16(policy->dfa, state, (u16)type);
237 if (state) {
238 if (p)
239 *p = early_match(policy, state, request);
240 if (!p || !*p) {
241 state = aa_dfa_match_be16(policy->dfa, state, (u16)protocol);
242 if (!state)
243 *info = "failed protocol match";
244 }
245 } else {
246 *info = "failed type match";
247 }
248
249 return state;
250 }
251
252 /* Generic af perm */
aa_profile_af_perm(struct aa_profile * profile,struct apparmor_audit_data * ad,u32 request,u16 family,int type,int protocol)253 int aa_profile_af_perm(struct aa_profile *profile,
254 struct apparmor_audit_data *ad, u32 request, u16 family,
255 int type, int protocol)
256 {
257 struct aa_ruleset *rules = profile->label.rules[0];
258 struct aa_perms *p = NULL;
259 aa_state_t state;
260
261 AA_BUG(family >= AF_MAX);
262 AA_BUG(type < 0 || type >= SOCK_MAX);
263 AA_BUG(profile_unconfined(profile));
264
265 state = RULE_MEDIATES_NET(rules);
266 if (state) {
267 state = aa_match_to_prot(rules->policy, state, request, family,
268 type, protocol, &p, &ad->info);
269 return aa_do_perms(profile, rules->policy, state, request, p,
270 ad);
271 } /* else */
272
273 return 0;
274 }
275
aa_af_perm(const struct cred * subj_cred,struct aa_label * label,const char * op,u32 request,u16 family,int type,int protocol)276 int aa_af_perm(const struct cred *subj_cred, struct aa_label *label,
277 const char *op, u32 request, u16 family, int type, int protocol)
278 {
279 struct aa_profile *profile;
280 DEFINE_AUDIT_NET(ad, op, subj_cred, NULL, family, type, protocol);
281
282 return fn_for_each_confined(label, profile,
283 aa_profile_af_perm(profile, &ad, request, family,
284 type, protocol));
285 }
286
aa_label_sk_perm(const struct cred * subj_cred,struct aa_label * label,const char * op,u32 request,const struct sock * sk)287 int aa_label_sk_perm(const struct cred *subj_cred, struct aa_label *label,
288 const char *op, u32 request, const struct sock *sk)
289 {
290 struct aa_sk_ctx *ctx = aa_sock(sk);
291 int error = 0;
292
293 AA_BUG(!label);
294 AA_BUG(!sk);
295
296 if (rcu_access_pointer(ctx->label) != kernel_t && !unconfined(label)) {
297 struct aa_profile *profile;
298 DEFINE_AUDIT_SK(ad, op, subj_cred, sk);
299
300 ad.subj_cred = subj_cred;
301 error = fn_for_each_confined(label, profile,
302 aa_profile_af_perm(profile, &ad, request, sk->sk_family,
303 sk->sk_type, sk->sk_protocol));
304 }
305
306 return error;
307 }
308
aa_sk_perm(const char * op,u32 request,const struct sock * sk)309 int aa_sk_perm(const char *op, u32 request, const struct sock *sk)
310 {
311 struct aa_label *label;
312 bool needput;
313 int error;
314
315 AA_BUG(!sk);
316 AA_BUG(in_interrupt());
317
318 /* TODO: switch to begin_current_label ???? */
319 label = begin_current_label_crit_section(&needput);
320 error = aa_label_sk_perm(current_cred(), label, op, request, sk);
321 end_current_label_crit_section(label, needput);
322
323 return error;
324 }
325
326
aa_sock_file_perm(const struct cred * subj_cred,struct aa_label * label,const char * op,u32 request,struct file * file)327 int aa_sock_file_perm(const struct cred *subj_cred, struct aa_label *label,
328 const char *op, u32 request, struct file *file)
329 {
330 struct socket *sock = (struct socket *) file->private_data;
331
332 AA_BUG(!label);
333
334 /* sock && sock->sk can be NULL for sockets being set up or torn down */
335 if (!sock || !sock->sk)
336 return 0;
337
338 switch (sock->sk->sk_family) {
339 case PF_UNIX:
340 return aa_unix_file_perm(subj_cred, label, op, request, file);
341 case PF_INET:
342 case PF_INET6:
343 return aa_inet_file_perm(subj_cred, label, op, request, sock);
344 }
345 return aa_label_sk_perm(subj_cred, label, op, request, sock->sk);
346 }
347
348 #ifdef CONFIG_NETWORK_SECMARK
apparmor_secmark_init(struct aa_secmark * secmark)349 static int apparmor_secmark_init(struct aa_secmark *secmark)
350 {
351 struct aa_label *label;
352
353 if (secmark->label[0] == '*') {
354 secmark->secid = AA_SECID_WILDCARD;
355 return 0;
356 }
357
358 label = aa_label_strn_parse(&root_ns->unconfined->label,
359 secmark->label, strlen(secmark->label),
360 GFP_ATOMIC, false, false);
361
362 if (IS_ERR(label))
363 return PTR_ERR(label);
364
365 secmark->secid = label->secid;
366 aa_put_label(label);
367
368 return 0;
369 }
370
aa_secmark_perm(struct aa_profile * profile,u32 request,u32 secid,struct apparmor_audit_data * ad)371 static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid,
372 struct apparmor_audit_data *ad)
373 {
374 int i, ret;
375 struct aa_perms perms = { };
376 struct aa_ruleset *rules = profile->label.rules[0];
377
378 if (rules->secmark_count == 0)
379 return 0;
380
381 for (i = 0; i < rules->secmark_count; i++) {
382 if (!rules->secmark[i].secid) {
383 ret = apparmor_secmark_init(&rules->secmark[i]);
384 if (ret)
385 return ret;
386 }
387
388 if (rules->secmark[i].secid == secid ||
389 rules->secmark[i].secid == AA_SECID_WILDCARD) {
390 if (rules->secmark[i].deny)
391 perms.deny = ALL_PERMS_MASK;
392 else
393 perms.allow = ALL_PERMS_MASK;
394
395 if (rules->secmark[i].audit)
396 perms.audit = ALL_PERMS_MASK;
397 }
398 }
399
400 aa_apply_modes_to_perms(profile, &perms);
401
402 return aa_check_perms(profile, &perms, request, ad, audit_net_cb);
403 }
404
apparmor_secmark_check(struct aa_label * label,char * op,u32 request,u32 secid,const struct sock * sk)405 int apparmor_secmark_check(struct aa_label *label, char *op, u32 request,
406 u32 secid, const struct sock *sk)
407 {
408 struct aa_profile *profile;
409 DEFINE_AUDIT_SK(ad, op, NULL, sk);
410
411 return fn_for_each_confined(label, profile,
412 aa_secmark_perm(profile, request, secid,
413 &ad));
414 }
415 #endif
416