xref: /linux/security/apparmor/af_unix.c (revision 8b45c6c90af6702b2ad716e148b8bcd5231a8070)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * AppArmor security module
4  *
5  * This file contains AppArmor af_unix fine grained mediation
6  *
7  * Copyright 2023 Canonical Ltd.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation, version 2 of the
12  * License.
13  */
14 
15 #include <linux/fs.h>
16 #include <net/tcp_states.h>
17 
18 #include "include/audit.h"
19 #include "include/af_unix.h"
20 #include "include/apparmor.h"
21 #include "include/file.h"
22 #include "include/label.h"
23 #include "include/path.h"
24 #include "include/policy.h"
25 #include "include/cred.h"
26 
27 
aa_unix_sk(struct unix_sock * u)28 static inline struct sock *aa_unix_sk(struct unix_sock *u)
29 {
30 	return &u->sk;
31 }
32 
unix_fs_perm(const char * op,u32 mask,const struct cred * subj_cred,struct aa_label * label,struct path * path)33 static int unix_fs_perm(const char *op, u32 mask, const struct cred *subj_cred,
34 			struct aa_label *label, struct path *path)
35 {
36 	AA_BUG(!label);
37 	AA_BUG(!path);
38 
39 	if (unconfined(label) || !label_mediates(label, AA_CLASS_FILE))
40 		return 0;
41 
42 	mask &= NET_FS_PERMS;
43 	/* if !u->path.dentry socket is being shutdown - implicit delegation
44 	 * until obj delegation is supported
45 	 */
46 	if (path->dentry) {
47 		/* the sunpath may not be valid for this ns so use the path */
48 		struct inode *inode = path->dentry->d_inode;
49 		vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_idmap(path->mnt), inode);
50 		struct path_cond cond = {
51 			.uid = vfsuid_into_kuid(vfsuid),
52 			.mode = inode->i_mode,
53 		};
54 
55 		return aa_path_perm(op, subj_cred, label, path,
56 				    PATH_SOCK_COND, mask, &cond);
57 	} /* else implicitly delegated */
58 
59 	return 0;
60 }
61 
62 /* match_addr special constants */
63 #define ABSTRACT_ADDR "\x00"		/* abstract socket addr */
64 #define ANONYMOUS_ADDR "\x01"		/* anonymous endpoint, no addr */
65 #define DISCONNECTED_ADDR "\x02"	/* addr is another namespace */
66 #define SHUTDOWN_ADDR "\x03"		/* path addr is shutdown and cleared */
67 #define FS_ADDR "/"			/* path addr in fs */
68 
match_addr(struct aa_dfa * dfa,aa_state_t state,struct sockaddr_un * addr,int addrlen)69 static aa_state_t match_addr(struct aa_dfa *dfa, aa_state_t state,
70 			     struct sockaddr_un *addr, int addrlen)
71 {
72 	if (addr)
73 		/* include leading \0 */
74 		state = aa_dfa_match_len(dfa, state, addr->sun_path,
75 					 unix_addr_len(addrlen));
76 	else
77 		state = aa_dfa_match_len(dfa, state, ANONYMOUS_ADDR, 1);
78 	/* todo: could change to out of band for cleaner separation */
79 	state = aa_dfa_null_transition(dfa, state);
80 
81 	return state;
82 }
83 
match_to_local(struct aa_policydb * policy,aa_state_t state,u32 request,int type,int protocol,struct sockaddr_un * addr,int addrlen,struct aa_perms ** p,const char ** info)84 static aa_state_t match_to_local(struct aa_policydb *policy,
85 				 aa_state_t state, u32 request,
86 				 int type, int protocol,
87 				 struct sockaddr_un *addr, int addrlen,
88 				 struct aa_perms **p,
89 				 const char **info)
90 {
91 	state = aa_match_to_prot(policy, state, request, PF_UNIX, type,
92 				 protocol, NULL, info);
93 	if (state) {
94 		state = match_addr(policy->dfa, state, addr, addrlen);
95 		if (state) {
96 			/* todo: local label matching */
97 			state = aa_dfa_null_transition(policy->dfa, state);
98 			if (!state)
99 				*info = "failed local label match";
100 		} else {
101 			*info = "failed local address match";
102 		}
103 	}
104 
105 	return state;
106 }
107 
aa_sunaddr(const struct unix_sock * u,int * addrlen)108 struct sockaddr_un *aa_sunaddr(const struct unix_sock *u, int *addrlen)
109 {
110 	struct unix_address *addr;
111 
112 	/* memory barrier is sufficient see note in net/unix/af_unix.c */
113 	addr = smp_load_acquire(&u->addr);
114 	if (addr) {
115 		*addrlen = addr->len;
116 		return addr->name;
117 	}
118 	*addrlen = 0;
119 	return NULL;
120 }
121 
match_to_sk(struct aa_policydb * policy,aa_state_t state,u32 request,struct unix_sock * u,struct aa_perms ** p,const char ** info)122 static aa_state_t match_to_sk(struct aa_policydb *policy,
123 			      aa_state_t state, u32 request,
124 			      struct unix_sock *u, struct aa_perms **p,
125 			      const char **info)
126 {
127 	int addrlen;
128 	struct sockaddr_un *addr = aa_sunaddr(u, &addrlen);
129 
130 	return match_to_local(policy, state, request, u->sk.sk_type,
131 			      u->sk.sk_protocol, addr, addrlen, p, info);
132 }
133 
134 #define CMD_ADDR	1
135 #define CMD_LISTEN	2
136 #define CMD_OPT		4
137 
match_to_cmd(struct aa_policydb * policy,aa_state_t state,u32 request,struct unix_sock * u,char cmd,struct aa_perms ** p,const char ** info)138 static aa_state_t match_to_cmd(struct aa_policydb *policy, aa_state_t state,
139 			       u32 request, struct unix_sock *u,
140 			       char cmd, struct aa_perms **p,
141 			       const char **info)
142 {
143 	AA_BUG(!p);
144 
145 	state = match_to_sk(policy, state, request, u, p, info);
146 	if (state && !*p) {
147 		state = aa_dfa_match_len(policy->dfa, state, &cmd, 1);
148 		if (!state)
149 			*info = "failed cmd selection match";
150 	}
151 
152 	return state;
153 }
154 
match_to_peer(struct aa_policydb * policy,aa_state_t state,u32 request,struct unix_sock * u,struct sockaddr_un * peer_addr,int peer_addrlen,struct aa_perms ** p,const char ** info)155 static aa_state_t match_to_peer(struct aa_policydb *policy, aa_state_t state,
156 				u32 request, struct unix_sock *u,
157 				struct sockaddr_un *peer_addr, int peer_addrlen,
158 				struct aa_perms **p, const char **info)
159 {
160 	AA_BUG(!p);
161 
162 	state = match_to_cmd(policy, state, request, u, CMD_ADDR, p, info);
163 	if (state && !*p) {
164 		state = match_addr(policy->dfa, state, peer_addr, peer_addrlen);
165 		if (!state)
166 			*info = "failed peer address match";
167 	}
168 
169 	return state;
170 }
171 
match_label(struct aa_profile * profile,struct aa_ruleset * rule,aa_state_t state,u32 request,struct aa_profile * peer,struct aa_perms * p,struct apparmor_audit_data * ad)172 static aa_state_t match_label(struct aa_profile *profile,
173 			      struct aa_ruleset *rule, aa_state_t state,
174 			      u32 request, struct aa_profile *peer,
175 			      struct aa_perms *p,
176 			      struct apparmor_audit_data *ad)
177 {
178 	AA_BUG(!profile);
179 	AA_BUG(!peer);
180 
181 	ad->peer = &peer->label;
182 
183 	if (state && !p) {
184 		state = aa_dfa_match(rule->policy->dfa, state,
185 				     peer->base.hname);
186 		if (!state)
187 			ad->info = "failed peer label match";
188 
189 	}
190 
191 	return aa_do_perms(profile, rule->policy, state, request, p, ad);
192 }
193 
194 
195 /* unix sock creation comes before we know if the socket will be an fs
196  * socket
197  * v6 - semantics are handled by mapping in profile load
198  * v7 - semantics require sock create for tasks creating an fs socket.
199  * v8 - same as v7
200  */
profile_create_perm(struct aa_profile * profile,int family,int type,int protocol,struct apparmor_audit_data * ad)201 static int profile_create_perm(struct aa_profile *profile, int family,
202 			       int type, int protocol,
203 			       struct apparmor_audit_data *ad)
204 {
205 	struct aa_ruleset *rules = profile->label.rules[0];
206 	aa_state_t state;
207 
208 	AA_BUG(!profile);
209 	AA_BUG(profile_unconfined(profile));
210 
211 	state = RULE_MEDIATES_v9NET(rules);
212 	if (state) {
213 		state = aa_match_to_prot(rules->policy, state, AA_MAY_CREATE,
214 					 PF_UNIX, type, protocol, NULL,
215 					 &ad->info);
216 
217 		return aa_do_perms(profile, rules->policy, state, AA_MAY_CREATE,
218 				   NULL, ad);
219 	}
220 
221 	return aa_profile_af_perm(profile, ad, AA_MAY_CREATE, family, type,
222 				  protocol);
223 }
224 
profile_sk_perm(struct aa_profile * profile,struct apparmor_audit_data * ad,u32 request,struct sock * sk,struct path * path)225 static int profile_sk_perm(struct aa_profile *profile,
226 			   struct apparmor_audit_data *ad,
227 			   u32 request, struct sock *sk, struct path *path)
228 {
229 	struct aa_ruleset *rules = profile->label.rules[0];
230 	struct aa_perms *p = NULL;
231 	aa_state_t state;
232 
233 	AA_BUG(!profile);
234 	AA_BUG(!sk);
235 	AA_BUG(profile_unconfined(profile));
236 
237 	state = RULE_MEDIATES_v9NET(rules);
238 	if (state) {
239 		if (is_unix_fs(sk))
240 			return unix_fs_perm(ad->op, request, ad->subj_cred,
241 					    &profile->label,
242 					    &unix_sk(sk)->path);
243 
244 		state = match_to_sk(rules->policy, state, request, unix_sk(sk),
245 				    &p, &ad->info);
246 
247 		return aa_do_perms(profile, rules->policy, state, request, p,
248 				   ad);
249 	}
250 
251 	return aa_profile_af_sk_perm(profile, ad, request, sk);
252 }
253 
profile_bind_perm(struct aa_profile * profile,struct sock * sk,struct apparmor_audit_data * ad)254 static int profile_bind_perm(struct aa_profile *profile, struct sock *sk,
255 			     struct apparmor_audit_data *ad)
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(!profile);
262 	AA_BUG(!sk);
263 	AA_BUG(!ad);
264 	AA_BUG(profile_unconfined(profile));
265 
266 	state = RULE_MEDIATES_v9NET(rules);
267 	if (state) {
268 		if (is_unix_addr_fs(ad->net.addr, ad->net.addrlen))
269 			/* under v7-9 fs hook handles bind */
270 			return 0;
271 		/* bind for abstract socket */
272 		state = match_to_local(rules->policy, state, AA_MAY_BIND,
273 				       sk->sk_type, sk->sk_protocol,
274 				       unix_addr(ad->net.addr),
275 				       ad->net.addrlen,
276 				       &p, &ad->info);
277 
278 		return aa_do_perms(profile, rules->policy, state, AA_MAY_BIND,
279 				   p, ad);
280 	}
281 
282 	return aa_profile_af_sk_perm(profile, ad, AA_MAY_BIND, sk);
283 }
284 
profile_listen_perm(struct aa_profile * profile,struct sock * sk,int backlog,struct apparmor_audit_data * ad)285 static int profile_listen_perm(struct aa_profile *profile, struct sock *sk,
286 			       int backlog, struct apparmor_audit_data *ad)
287 {
288 	struct aa_ruleset *rules = profile->label.rules[0];
289 	struct aa_perms *p = NULL;
290 	aa_state_t state;
291 
292 	AA_BUG(!profile);
293 	AA_BUG(!sk);
294 	AA_BUG(!ad);
295 	AA_BUG(profile_unconfined(profile));
296 
297 	state = RULE_MEDIATES_v9NET(rules);
298 	if (state) {
299 		__be16 b = cpu_to_be16(backlog);
300 
301 		if (is_unix_fs(sk))
302 			return unix_fs_perm(ad->op, AA_MAY_LISTEN,
303 					    ad->subj_cred, &profile->label,
304 					    &unix_sk(sk)->path);
305 
306 		state = match_to_cmd(rules->policy, state, AA_MAY_LISTEN,
307 				     unix_sk(sk), CMD_LISTEN, &p, &ad->info);
308 		if (state && !p) {
309 			state = aa_dfa_match_len(rules->policy->dfa, state,
310 						 (char *) &b, 2);
311 			if (!state)
312 				ad->info = "failed listen backlog match";
313 		}
314 		return aa_do_perms(profile, rules->policy, state, AA_MAY_LISTEN,
315 				   p, ad);
316 	}
317 
318 	return aa_profile_af_sk_perm(profile, ad, AA_MAY_LISTEN, sk);
319 }
320 
profile_accept_perm(struct aa_profile * profile,struct sock * sk,struct apparmor_audit_data * ad)321 static int profile_accept_perm(struct aa_profile *profile,
322 			       struct sock *sk,
323 			       struct apparmor_audit_data *ad)
324 {
325 	struct aa_ruleset *rules = profile->label.rules[0];
326 	struct aa_perms *p = NULL;
327 	aa_state_t state;
328 
329 	AA_BUG(!profile);
330 	AA_BUG(!sk);
331 	AA_BUG(!ad);
332 	AA_BUG(profile_unconfined(profile));
333 
334 	state = RULE_MEDIATES_v9NET(rules);
335 	if (state) {
336 		if (is_unix_fs(sk))
337 			return unix_fs_perm(ad->op, AA_MAY_ACCEPT,
338 					    ad->subj_cred, &profile->label,
339 					    &unix_sk(sk)->path);
340 
341 		state = match_to_sk(rules->policy, state, AA_MAY_ACCEPT,
342 				    unix_sk(sk), &p, &ad->info);
343 
344 		return aa_do_perms(profile, rules->policy, state, AA_MAY_ACCEPT,
345 				   p, ad);
346 	}
347 
348 	return aa_profile_af_sk_perm(profile, ad, AA_MAY_ACCEPT, sk);
349 }
350 
profile_opt_perm(struct aa_profile * profile,u32 request,struct sock * sk,int optname,struct apparmor_audit_data * ad)351 static int profile_opt_perm(struct aa_profile *profile, u32 request,
352 			    struct sock *sk, int optname,
353 			    struct apparmor_audit_data *ad)
354 {
355 	struct aa_ruleset *rules = profile->label.rules[0];
356 	struct aa_perms *p = NULL;
357 	aa_state_t state;
358 
359 	AA_BUG(!profile);
360 	AA_BUG(!sk);
361 	AA_BUG(!ad);
362 	AA_BUG(profile_unconfined(profile));
363 
364 	state = RULE_MEDIATES_v9NET(rules);
365 	if (state) {
366 		__be16 b = cpu_to_be16(optname);
367 		if (is_unix_fs(sk))
368 			return unix_fs_perm(ad->op, request,
369 					    ad->subj_cred, &profile->label,
370 					    &unix_sk(sk)->path);
371 
372 		state = match_to_cmd(rules->policy, state, request, unix_sk(sk),
373 				     CMD_OPT, &p, &ad->info);
374 		if (state && !p) {
375 			state = aa_dfa_match_len(rules->policy->dfa, state,
376 						 (char *) &b, 2);
377 			if (!state)
378 				ad->info = "failed sockopt match";
379 		}
380 		return aa_do_perms(profile, rules->policy, state, request, p,
381 				   ad);
382 	}
383 
384 	return aa_profile_af_sk_perm(profile, ad, request, sk);
385 }
386 
387 /* null peer_label is allowed, in which case the peer_sk label is used */
profile_peer_perm(struct aa_profile * profile,u32 request,struct sock * sk,struct path * path,struct sockaddr_un * peer_addr,int peer_addrlen,struct path * peer_path,struct aa_label * peer_label,struct apparmor_audit_data * ad)388 static int profile_peer_perm(struct aa_profile *profile, u32 request,
389 			     struct sock *sk, struct path *path,
390 			     struct sockaddr_un *peer_addr,
391 			     int peer_addrlen, struct path *peer_path,
392 			     struct aa_label *peer_label,
393 			     struct apparmor_audit_data *ad)
394 {
395 	struct aa_ruleset *rules = profile->label.rules[0];
396 	struct aa_perms *p = NULL;
397 	aa_state_t state;
398 
399 	AA_BUG(!profile);
400 	AA_BUG(profile_unconfined(profile));
401 	AA_BUG(!sk);
402 	AA_BUG(!peer_label);
403 	AA_BUG(!ad);
404 
405 	state = RULE_MEDIATES_v9NET(rules);
406 	if (state) {
407 		struct aa_profile *peerp;
408 
409 		if (peer_path)
410 			return unix_fs_perm(ad->op, request, ad->subj_cred,
411 					    &profile->label, peer_path);
412 		else if (path)
413 			return unix_fs_perm(ad->op, request, ad->subj_cred,
414 					    &profile->label, path);
415 		state = match_to_peer(rules->policy, state, request,
416 				      unix_sk(sk),
417 				      peer_addr, peer_addrlen, &p, &ad->info);
418 
419 		return fn_for_each_in_ns(peer_label, peerp,
420 				match_label(profile, rules, state, request,
421 					    peerp, p, ad));
422 	}
423 
424 	return aa_profile_af_sk_perm(profile, ad, request, sk);
425 }
426 
427 /* -------------------------------- */
428 
aa_unix_create_perm(struct aa_label * label,int family,int type,int protocol)429 int aa_unix_create_perm(struct aa_label *label, int family, int type,
430 			int protocol)
431 {
432 	if (!unconfined(label)) {
433 		struct aa_profile *profile;
434 		DEFINE_AUDIT_NET(ad, OP_CREATE, current_cred(), NULL, family,
435 				 type, protocol);
436 
437 		return fn_for_each_confined(label, profile,
438 				profile_create_perm(profile, family, type,
439 						    protocol, &ad));
440 	}
441 
442 	return 0;
443 }
444 
aa_unix_label_sk_perm(const struct cred * subj_cred,struct aa_label * label,const char * op,u32 request,struct sock * sk,struct path * path)445 static int aa_unix_label_sk_perm(const struct cred *subj_cred,
446 				 struct aa_label *label,
447 				 const char *op, u32 request, struct sock *sk,
448 				 struct path *path)
449 {
450 	if (!unconfined(label)) {
451 		struct aa_profile *profile;
452 		DEFINE_AUDIT_SK(ad, op, subj_cred, sk);
453 
454 		return fn_for_each_confined(label, profile,
455 				profile_sk_perm(profile, &ad, request, sk,
456 						path));
457 	}
458 	return 0;
459 }
460 
461 /* revalidation, get/set attr, shutdown */
aa_unix_sock_perm(const char * op,u32 request,struct socket * sock)462 int aa_unix_sock_perm(const char *op, u32 request, struct socket *sock)
463 {
464 	struct aa_label *label;
465 	int error;
466 
467 	label = begin_current_label_crit_section();
468 	error = aa_unix_label_sk_perm(current_cred(), label, op,
469 				      request, sock->sk,
470 				      is_unix_fs(sock->sk) ? &unix_sk(sock->sk)->path : NULL);
471 	end_current_label_crit_section(label);
472 
473 	return error;
474 }
475 
valid_addr(struct sockaddr * addr,int addr_len)476 static int valid_addr(struct sockaddr *addr, int addr_len)
477 {
478 	struct sockaddr_un *sunaddr = unix_addr(addr);
479 
480 	/* addr_len == offsetof(struct sockaddr_un, sun_path) is autobind */
481 	if (addr_len < offsetof(struct sockaddr_un, sun_path) ||
482 	    addr_len > sizeof(*sunaddr))
483 		return -EINVAL;
484 	return 0;
485 }
486 
aa_unix_bind_perm(struct socket * sock,struct sockaddr * addr,int addrlen)487 int aa_unix_bind_perm(struct socket *sock, struct sockaddr *addr,
488 		      int addrlen)
489 {
490 	struct aa_profile *profile;
491 	struct aa_label *label;
492 	int error = 0;
493 
494 	error = valid_addr(addr, addrlen);
495 	if (error)
496 		return error;
497 
498 	label = begin_current_label_crit_section();
499 	/* fs bind is handled by mknod */
500 	if (!unconfined(label)) {
501 		DEFINE_AUDIT_SK(ad, OP_BIND, current_cred(), sock->sk);
502 
503 		ad.net.addr = unix_addr(addr);
504 		ad.net.addrlen = addrlen;
505 
506 		error = fn_for_each_confined(label, profile,
507 				profile_bind_perm(profile, sock->sk, &ad));
508 	}
509 	end_current_label_crit_section(label);
510 
511 	return error;
512 }
513 
514 /*
515  * unix connections are covered by the
516  * - unix_stream_connect (stream) and unix_may_send hooks (dgram)
517  * - fs connect is handled by open
518  * This is just here to document this is not needed for af_unix
519  *
520 int aa_unix_connect_perm(struct socket *sock, struct sockaddr *address,
521 			 int addrlen)
522 {
523 	return 0;
524 }
525 */
526 
aa_unix_listen_perm(struct socket * sock,int backlog)527 int aa_unix_listen_perm(struct socket *sock, int backlog)
528 {
529 	struct aa_profile *profile;
530 	struct aa_label *label;
531 	int error = 0;
532 
533 	label = begin_current_label_crit_section();
534 	if (!unconfined(label)) {
535 		DEFINE_AUDIT_SK(ad, OP_LISTEN, current_cred(), sock->sk);
536 
537 		error = fn_for_each_confined(label, profile,
538 				profile_listen_perm(profile, sock->sk,
539 						    backlog, &ad));
540 	}
541 	end_current_label_crit_section(label);
542 
543 	return error;
544 }
545 
546 
547 /* ability of sock to connect, not peer address binding */
aa_unix_accept_perm(struct socket * sock,struct socket * newsock)548 int aa_unix_accept_perm(struct socket *sock, struct socket *newsock)
549 {
550 	struct aa_profile *profile;
551 	struct aa_label *label;
552 	int error = 0;
553 
554 	label = begin_current_label_crit_section();
555 	if (!unconfined(label)) {
556 		DEFINE_AUDIT_SK(ad, OP_ACCEPT, current_cred(), sock->sk);
557 
558 		error = fn_for_each_confined(label, profile,
559 				profile_accept_perm(profile, sock->sk, &ad));
560 	}
561 	end_current_label_crit_section(label);
562 
563 	return error;
564 }
565 
566 
567 /*
568  * dgram handled by unix_may_sendmsg, right to send on stream done at connect
569  * could do per msg unix_stream here, but connect + socket transfer is
570  * sufficient. This is just here to document this is not needed for af_unix
571  *
572  * sendmsg, recvmsg
573 int aa_unix_msg_perm(const char *op, u32 request, struct socket *sock,
574 		     struct msghdr *msg, int size)
575 {
576 	return 0;
577 }
578 */
579 
aa_unix_opt_perm(const char * op,u32 request,struct socket * sock,int level,int optname)580 int aa_unix_opt_perm(const char *op, u32 request, struct socket *sock,
581 		     int level, int optname)
582 {
583 	struct aa_profile *profile;
584 	struct aa_label *label;
585 	int error = 0;
586 
587 	label = begin_current_label_crit_section();
588 	if (!unconfined(label)) {
589 		DEFINE_AUDIT_SK(ad, op, current_cred(), sock->sk);
590 
591 		error = fn_for_each_confined(label, profile,
592 				profile_opt_perm(profile, request, sock->sk,
593 						 optname, &ad));
594 	}
595 	end_current_label_crit_section(label);
596 
597 	return error;
598 }
599 
unix_peer_perm(const struct cred * subj_cred,struct aa_label * label,const char * op,u32 request,struct sock * sk,struct path * path,struct sockaddr_un * peer_addr,int peer_addrlen,struct path * peer_path,struct aa_label * peer_label)600 static int unix_peer_perm(const struct cred *subj_cred,
601 			  struct aa_label *label, const char *op, u32 request,
602 			  struct sock *sk, struct path *path,
603 			  struct sockaddr_un *peer_addr, int peer_addrlen,
604 			  struct path *peer_path, struct aa_label *peer_label)
605 {
606 	struct aa_profile *profile;
607 	DEFINE_AUDIT_SK(ad, op, subj_cred, sk);
608 
609 	ad.net.peer.addr = peer_addr;
610 	ad.net.peer.addrlen = peer_addrlen;
611 
612 	return fn_for_each_confined(label, profile,
613 			profile_peer_perm(profile, request, sk, path,
614 					  peer_addr, peer_addrlen, peer_path,
615 					  peer_label, &ad));
616 }
617 
618 /**
619  *
620  * Requires: lock held on both @sk and @peer_sk
621  *           called by unix_stream_connect, unix_may_send
622  */
aa_unix_peer_perm(const struct cred * subj_cred,struct aa_label * label,const char * op,u32 request,struct sock * sk,struct sock * peer_sk,struct aa_label * peer_label)623 int aa_unix_peer_perm(const struct cred *subj_cred,
624 		      struct aa_label *label, const char *op, u32 request,
625 		      struct sock *sk, struct sock *peer_sk,
626 		      struct aa_label *peer_label)
627 {
628 	struct unix_sock *peeru = unix_sk(peer_sk);
629 	struct unix_sock *u = unix_sk(sk);
630 	int plen;
631 	struct sockaddr_un *paddr = aa_sunaddr(unix_sk(peer_sk), &plen);
632 
633 	AA_BUG(!label);
634 	AA_BUG(!sk);
635 	AA_BUG(!peer_sk);
636 	AA_BUG(!peer_label);
637 
638 	return unix_peer_perm(subj_cred, label, op, request, sk,
639 			      is_unix_fs(sk) ? &u->path : NULL,
640 			      paddr, plen,
641 			      is_unix_fs(peer_sk) ? &peeru->path : NULL,
642 			      peer_label);
643 }
644 
645 /* sk_plabel for comparison only */
update_sk_ctx(struct sock * sk,struct aa_label * label,struct aa_label * plabel)646 static void update_sk_ctx(struct sock *sk, struct aa_label *label,
647 			  struct aa_label *plabel)
648 {
649 	struct aa_label *l, *old;
650 	struct aa_sk_ctx *ctx = aa_sock(sk);
651 	bool update_sk;
652 
653 	rcu_read_lock();
654 	update_sk = (plabel &&
655 		     (plabel != rcu_access_pointer(ctx->peer_lastupdate) ||
656 		      !aa_label_is_subset(plabel, rcu_dereference(ctx->peer)))) ||
657 	  !__aa_subj_label_is_cached(label, rcu_dereference(ctx->label));
658 	rcu_read_unlock();
659 	if (!update_sk)
660 		return;
661 
662 	spin_lock(&unix_sk(sk)->lock);
663 	old = rcu_dereference_protected(ctx->label,
664 					lockdep_is_held(&unix_sk(sk)->lock));
665 	l = aa_label_merge(old, label, GFP_ATOMIC);
666 	if (l) {
667 		if (l != old) {
668 			rcu_assign_pointer(ctx->label, l);
669 			aa_put_label(old);
670 		} else
671 			aa_put_label(l);
672 	}
673 	if (plabel && rcu_access_pointer(ctx->peer_lastupdate) != plabel) {
674 		old = rcu_dereference_protected(ctx->peer, lockdep_is_held(&unix_sk(sk)->lock));
675 
676 		if (old == plabel) {
677 			rcu_assign_pointer(ctx->peer_lastupdate, plabel);
678 		} else if (aa_label_is_subset(plabel, old)) {
679 			rcu_assign_pointer(ctx->peer_lastupdate, plabel);
680 			rcu_assign_pointer(ctx->peer, aa_get_label(plabel));
681 			aa_put_label(old);
682 		} /* else race or a subset - don't update */
683 	}
684 	spin_unlock(&unix_sk(sk)->lock);
685 }
686 
update_peer_ctx(struct sock * sk,struct aa_sk_ctx * ctx,struct aa_label * label)687 static void update_peer_ctx(struct sock *sk, struct aa_sk_ctx *ctx,
688 			    struct aa_label *label)
689 {
690 	struct aa_label *l, *old;
691 
692 	spin_lock(&unix_sk(sk)->lock);
693 	old = rcu_dereference_protected(ctx->peer,
694 					lockdep_is_held(&unix_sk(sk)->lock));
695 	l = aa_label_merge(old, label, GFP_ATOMIC);
696 	if (l) {
697 		if (l != old) {
698 			rcu_assign_pointer(ctx->peer, l);
699 			aa_put_label(old);
700 		} else
701 			aa_put_label(l);
702 	}
703 	spin_unlock(&unix_sk(sk)->lock);
704 }
705 
706 /* This fn is only checked if something has changed in the security
707  * boundaries. Otherwise cached info off file is sufficient
708  */
aa_unix_file_perm(const struct cred * subj_cred,struct aa_label * label,const char * op,u32 request,struct file * file)709 int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label,
710 		      const char *op, u32 request, struct file *file)
711 {
712 	struct socket *sock = (struct socket *) file->private_data;
713 	struct sockaddr_un *addr, *peer_addr;
714 	int addrlen, peer_addrlen;
715 	struct aa_label *plabel = NULL;
716 	struct sock *peer_sk = NULL;
717 	u32 sk_req = request & ~NET_PEER_MASK;
718 	struct path path;
719 	bool is_sk_fs;
720 	int error = 0;
721 
722 	AA_BUG(!label);
723 	AA_BUG(!sock);
724 	AA_BUG(!sock->sk);
725 	AA_BUG(sock->sk->sk_family != PF_UNIX);
726 
727 	/* investigate only using lock via unix_peer_get()
728 	 * addr only needs the memory barrier, but need to investigate
729 	 * path
730 	 */
731 	unix_state_lock(sock->sk);
732 	peer_sk = unix_peer(sock->sk);
733 	if (peer_sk)
734 		sock_hold(peer_sk);
735 
736 	is_sk_fs = is_unix_fs(sock->sk);
737 	addr = aa_sunaddr(unix_sk(sock->sk), &addrlen);
738 	path = unix_sk(sock->sk)->path;
739 	unix_state_unlock(sock->sk);
740 
741 	if (is_sk_fs && peer_sk)
742 		sk_req = request;
743 	if (sk_req) {
744 			error = aa_unix_label_sk_perm(subj_cred, label, op,
745 						      sk_req, sock->sk,
746 						      is_sk_fs ? &path : NULL);
747 	}
748 	if (!peer_sk)
749 		goto out;
750 
751 	peer_addr = aa_sunaddr(unix_sk(peer_sk), &peer_addrlen);
752 
753 	struct path peer_path;
754 
755 	peer_path = unix_sk(peer_sk)->path;
756 	if (!is_sk_fs && is_unix_fs(peer_sk)) {
757 		last_error(error,
758 			   unix_fs_perm(op, request, subj_cred, label,
759 					is_unix_fs(peer_sk) ? &peer_path : NULL));
760 	} else if (!is_sk_fs) {
761 		struct aa_label *plabel;
762 		struct aa_sk_ctx *pctx = aa_sock(peer_sk);
763 
764 		rcu_read_lock();
765 		plabel = aa_get_label_rcu(&pctx->label);
766 		rcu_read_unlock();
767 		/* no fs check of aa_unix_peer_perm because conditions above
768 		 * ensure they will never be done
769 		 */
770 		last_error(error,
771 			xcheck(unix_peer_perm(subj_cred, label, op,
772 					      MAY_READ | MAY_WRITE, sock->sk,
773 					      is_sk_fs ? &path : NULL,
774 					      peer_addr, peer_addrlen,
775 					      is_unix_fs(peer_sk) ?
776 							&peer_path : NULL,
777 					      plabel),
778 			       unix_peer_perm(file->f_cred, plabel, op,
779 					      MAY_READ | MAY_WRITE, peer_sk,
780 					      is_unix_fs(peer_sk) ?
781 							&peer_path : NULL,
782 					      addr, addrlen,
783 					      is_sk_fs ? &path : NULL,
784 					      label)));
785 		if (!error && !__aa_subj_label_is_cached(plabel, label))
786 			update_peer_ctx(peer_sk, pctx, label);
787 	}
788 	sock_put(peer_sk);
789 
790 out:
791 
792 	/* update peer cache to latest successful perm check */
793 	if (error == 0)
794 		update_sk_ctx(sock->sk, label, plabel);
795 	aa_put_label(plabel);
796 
797 	return error;
798 }
799 
800