xref: /linux/security/apparmor/af_unix.c (revision 6456ccbd2ff72814b3c1b2e2a3a2145a2ced858d)
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 /* This fn is only checked if something has changed in the security
650  * boundaries. Otherwise cached info off file is sufficient
651  */
652 int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label,
653 		      const char *op, u32 request, struct file *file)
654 {
655 	struct socket *sock = (struct socket *) file->private_data;
656 	struct sockaddr_un *addr, *peer_addr;
657 	int addrlen, peer_addrlen;
658 	struct sock *peer_sk = NULL;
659 	u32 sk_req = request & ~NET_PEER_MASK;
660 	struct path path;
661 	bool is_sk_fs;
662 	int error = 0;
663 
664 	AA_BUG(!label);
665 	AA_BUG(!sock);
666 	AA_BUG(!sock->sk);
667 	AA_BUG(sock->sk->sk_family != PF_UNIX);
668 
669 	/* TODO: update sock label with new task label */
670 	/* investigate only using lock via unix_peer_get()
671 	 * addr only needs the memory barrier, but need to investigate
672 	 * path
673 	 */
674 	unix_state_lock(sock->sk);
675 	peer_sk = unix_peer(sock->sk);
676 	if (peer_sk)
677 		sock_hold(peer_sk);
678 
679 	is_sk_fs = is_unix_fs(sock->sk);
680 	addr = aa_sunaddr(unix_sk(sock->sk), &addrlen);
681 	path = unix_sk(sock->sk)->path;
682 	unix_state_unlock(sock->sk);
683 
684 	if (is_sk_fs && peer_sk)
685 		sk_req = request;
686 	if (sk_req) {
687 			error = aa_unix_label_sk_perm(subj_cred, label, op,
688 						      sk_req, sock->sk,
689 						      is_sk_fs ? &path : NULL);
690 	}
691 	if (!peer_sk)
692 		goto out;
693 
694 	peer_addr = aa_sunaddr(unix_sk(peer_sk), &peer_addrlen);
695 
696 	struct path peer_path;
697 
698 	peer_path = unix_sk(peer_sk)->path;
699 	if (!is_sk_fs && is_unix_fs(peer_sk)) {
700 		last_error(error,
701 			   unix_fs_perm(op, request, subj_cred, label,
702 					is_unix_fs(peer_sk) ? &peer_path : NULL));
703 	} else if (!is_sk_fs) {
704 		struct aa_sk_ctx *pctx = aa_sock(peer_sk);
705 
706 		/* no fs check of aa_unix_peer_perm because conditions above
707 		 * ensure they will never be done
708 		 */
709 		last_error(error,
710 			xcheck(unix_peer_perm(subj_cred, label, op,
711 					      MAY_READ | MAY_WRITE, sock->sk,
712 					      is_sk_fs ? &path : NULL,
713 					      peer_addr, peer_addrlen,
714 					      is_unix_fs(peer_sk) ?
715 							&peer_path : NULL,
716 					      pctx->label),
717 			       unix_peer_perm(file->f_cred, pctx->label, op,
718 					      MAY_READ | MAY_WRITE, peer_sk,
719 					      is_unix_fs(peer_sk) ?
720 							&peer_path : NULL,
721 					      addr, addrlen,
722 					      is_sk_fs ? &path : NULL,
723 					      label)));
724 	}
725 	sock_put(peer_sk);
726 
727 out:
728 
729 	return error;
730 }
731