File Index
Files and directories
Sign in
FILE

af_unix.c

File preview with syntax highlighting.

linux-6.19.14/security/apparmor/af_unix.c C
  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_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
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
~/ Read-only file preview.