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