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