Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
28static inline struct sock *aa_unix_sk(struct unix_sock *u)
29{
30 return &u->sk;
31}
32
33static int unix_fs_perm(const char *op, u32 mask, const struct cred *subj_cred,
34 struct aa_label *label, const 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
69static 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
84static 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
108struct 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
122static 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
138static 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
155static 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
172static 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 */
201static 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
225static int profile_sk_perm(struct aa_profile *profile,
226 struct apparmor_audit_data *ad,
227 u32 request, struct sock *sk, const 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
254static 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
285static 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
321static 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
351static 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 */
388static int profile_peer_perm(struct aa_profile *profile, u32 request,
389 struct sock *sk, const struct path *path,
390 struct sockaddr_un *peer_addr,
391 int peer_addrlen, const 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_scope(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
429int 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
445static 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 const 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 */
462int 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
476static 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
487int 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 *
520int aa_unix_connect_perm(struct socket *sock, struct sockaddr *address,
521 int addrlen)
522{
523 return 0;
524}
525*/
526
527int 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 */
548int 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
573int 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
580int 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
600static int unix_peer_perm(const struct cred *subj_cred,
601 struct aa_label *label, const char *op, u32 request,
602 struct sock *sk, const struct path *path,
603 struct sockaddr_un *peer_addr, int peer_addrlen,
604 const 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 */
623int 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 */
646static 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
687static 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 */
709int 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
790out:
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