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