xref: /linux/security/apparmor/net.c (revision 8fefe68784ae1606e11a5c65c04167c3b95051a0)
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