@@ -30,11 +30,10 @@ static inline struct sock *aa_unix_sk(struct unix_sock *u)
30
30
}
31
31
32
32
static int unix_fs_perm (const char * op , u32 mask , const struct cred * subj_cred ,
33
- struct aa_label * label , struct unix_sock * u )
33
+ struct aa_label * label , struct path * path )
34
34
{
35
35
AA_BUG (!label );
36
- AA_BUG (!u );
37
- AA_BUG (!is_unix_fs (aa_unix_sk (u )));
36
+ AA_BUG (!path );
38
37
39
38
if (unconfined (label ) || !label_mediates (label , AA_CLASS_FILE ))
40
39
return 0 ;
@@ -43,13 +42,13 @@ static int unix_fs_perm(const char *op, u32 mask, const struct cred *subj_cred,
43
42
/* if !u->path.dentry socket is being shutdown - implicit delegation
44
43
* until obj delegation is supported
45
44
*/
46
- if (u -> path . dentry ) {
45
+ if (path -> dentry ) {
47
46
/* the sunpath may not be valid for this ns so use the path */
48
- struct path_cond cond = { u -> path . dentry -> d_inode -> i_uid ,
49
- u -> path . dentry -> d_inode -> i_mode
47
+ struct path_cond cond = { path -> dentry -> d_inode -> i_uid ,
48
+ path -> dentry -> d_inode -> i_mode
50
49
};
51
50
52
- return aa_path_perm (op , subj_cred , label , & u -> path ,
51
+ return aa_path_perm (op , subj_cred , label , path ,
53
52
PATH_SOCK_COND , mask , & cond );
54
53
} /* else implicitly delegated */
55
54
@@ -102,18 +101,27 @@ static aa_state_t match_to_local(struct aa_policydb *policy,
102
101
return state ;
103
102
}
104
103
104
+ struct sockaddr_un * aa_sunaddr (const struct unix_sock * u , int * addrlen )
105
+ {
106
+ struct unix_address * addr ;
107
+
108
+ /* memory barrier is sufficient see note in net/unix/af_unix.c */
109
+ addr = smp_load_acquire (& u -> addr );
110
+ if (addr ) {
111
+ * addrlen = addr -> len ;
112
+ return addr -> name ;
113
+ }
114
+ * addrlen = 0 ;
115
+ return NULL ;
116
+ }
117
+
105
118
static aa_state_t match_to_sk (struct aa_policydb * policy ,
106
119
aa_state_t state , u32 request ,
107
120
struct unix_sock * u , struct aa_perms * * p ,
108
121
const char * * info )
109
122
{
110
- struct sockaddr_un * addr = NULL ;
111
- int addrlen = 0 ;
112
-
113
- if (u -> addr ) {
114
- addr = u -> addr -> name ;
115
- addrlen = u -> addr -> len ;
116
- }
123
+ int addrlen ;
124
+ struct sockaddr_un * addr = aa_sunaddr (u , & addrlen );
117
125
118
126
return match_to_local (policy , state , request , u -> sk .sk_type ,
119
127
u -> sk .sk_protocol , addr , addrlen , p , info );
@@ -363,7 +371,8 @@ static int profile_opt_perm(struct aa_profile *profile, u32 request,
363
371
364
372
/* null peer_label is allowed, in which case the peer_sk label is used */
365
373
static int profile_peer_perm (struct aa_profile * profile , u32 request ,
366
- struct sock * sk , struct sock * peer_sk ,
374
+ struct sock * sk , struct sockaddr_un * peer_addr ,
375
+ int peer_addrlen ,
367
376
struct aa_label * peer_label ,
368
377
struct apparmor_audit_data * ad )
369
378
{
@@ -375,26 +384,16 @@ static int profile_peer_perm(struct aa_profile *profile, u32 request,
375
384
AA_BUG (!profile );
376
385
AA_BUG (profile_unconfined (profile ));
377
386
AA_BUG (!sk );
378
- AA_BUG (!peer_sk );
387
+ AA_BUG (!peer_label );
379
388
AA_BUG (!ad );
380
- AA_BUG (is_unix_fs (peer_sk )); /* currently always calls unix_fs_perm */
381
389
382
390
state = RULE_MEDIATES_v9NET (rules );
383
391
if (state ) {
384
- struct aa_sk_ctx * peer_ctx = aa_sock (peer_sk );
385
392
struct aa_profile * peerp ;
386
- struct sockaddr_un * addr = NULL ;
387
- int len = 0 ;
388
393
389
- if (unix_sk (peer_sk )-> addr ) {
390
- addr = unix_sk (peer_sk )-> addr -> name ;
391
- len = unix_sk (peer_sk )-> addr -> len ;
392
- }
393
394
state = match_to_peer (rules -> policy , state , request ,
394
395
unix_sk (sk ),
395
- addr , len , & p , & ad -> info );
396
- if (!peer_label )
397
- peer_label = peer_ctx -> label ;
396
+ peer_addr , peer_addrlen , & p , & ad -> info );
398
397
399
398
return fn_for_each_in_ns (peer_label , peerp ,
400
399
match_label (profile , rules , state , request ,
@@ -422,9 +421,8 @@ int aa_unix_create_perm(struct aa_label *label, int family, int type,
422
421
return 0 ;
423
422
}
424
423
425
- int aa_unix_label_sk_perm (const struct cred * subj_cred ,
426
- struct aa_label * label , const char * op , u32 request ,
427
- struct sock * sk )
424
+ int aa_unix_label_sk_perm (const struct cred * subj_cred , struct aa_label * label ,
425
+ const char * op , u32 request , struct sock * sk )
428
426
{
429
427
if (!unconfined (label )) {
430
428
struct aa_profile * profile ;
@@ -436,35 +434,27 @@ int aa_unix_label_sk_perm(const struct cred *subj_cred,
436
434
return 0 ;
437
435
}
438
436
439
- static int unix_label_sock_perm (const struct cred * subj_cred ,
440
- struct aa_label * label , const char * op ,
441
- u32 request , struct socket * sock )
442
- {
443
- if (unconfined (label ))
444
- return 0 ;
445
- if (is_unix_fs (sock -> sk ))
446
- return unix_fs_perm (op , request , subj_cred , label ,
447
- unix_sk (sock -> sk ));
448
-
449
- return aa_unix_label_sk_perm (subj_cred , label , op , request , sock -> sk );
450
- }
451
-
452
437
/* revalidation, get/set attr, shutdown */
453
438
int aa_unix_sock_perm (const char * op , u32 request , struct socket * sock )
454
439
{
455
440
struct aa_label * label ;
456
441
int error ;
457
442
458
443
label = begin_current_label_crit_section ();
459
- error = unix_label_sock_perm (current_cred (), label , op , request , sock );
444
+ if (is_unix_fs (sock -> sk ))
445
+ error = unix_fs_perm (op , request , current_cred (), label ,
446
+ & unix_sk (sock -> sk )-> path );
447
+ else
448
+ error = aa_unix_label_sk_perm (current_cred (), label , op ,
449
+ request , sock -> sk );
460
450
end_current_label_crit_section (label );
461
451
462
452
return error ;
463
453
}
464
454
465
455
static int valid_addr (struct sockaddr * addr , int addr_len )
466
456
{
467
- struct sockaddr_un * sunaddr = ( struct sockaddr_un * ) addr ;
457
+ struct sockaddr_un * sunaddr = unix_addr ( addr ) ;
468
458
469
459
/* addr_len == offsetof(struct sockaddr_un, sun_path) is autobind */
470
460
if (addr_len < offsetof(struct sockaddr_un , sun_path ) ||
@@ -586,6 +576,22 @@ int aa_unix_opt_perm(const char *op, u32 request, struct socket *sock,
586
576
return error ;
587
577
}
588
578
579
+ static int unix_peer_perm (const struct cred * subj_cred ,
580
+ struct aa_label * label , const char * op , u32 request ,
581
+ struct sock * sk , struct sockaddr_un * peer_addr ,
582
+ int peer_addrlen , struct aa_label * peer_label )
583
+ {
584
+ struct aa_profile * profile ;
585
+ DEFINE_AUDIT_SK (ad , op , subj_cred , sk );
586
+
587
+ ad .net .addr = peer_addr ;
588
+ ad .net .addrlen = peer_addrlen ;
589
+
590
+ return fn_for_each_confined (label , profile ,
591
+ profile_peer_perm (profile , request , sk ,
592
+ peer_addr , peer_addrlen , peer_label , & ad ));
593
+ }
594
+
589
595
/**
590
596
*
591
597
* Requires: lock held on both @sk and @peer_sk
@@ -602,58 +608,37 @@ int aa_unix_peer_perm(const struct cred *subj_cred,
602
608
AA_BUG (!label );
603
609
AA_BUG (!sk );
604
610
AA_BUG (!peer_sk );
611
+ AA_BUG (!peer_label );
605
612
606
613
if (is_unix_fs (aa_unix_sk (peeru ))) {
607
- return unix_fs_perm (op , request , subj_cred , label , peeru );
614
+ return unix_fs_perm (op , request , subj_cred , label ,
615
+ & peeru -> path );
608
616
} else if (is_unix_fs (aa_unix_sk (u ))) {
609
- return unix_fs_perm (op , request , subj_cred , label , u );
617
+ return unix_fs_perm (op , request , subj_cred , label , & u -> path );
610
618
} else if (!unconfined (label )) {
611
- struct aa_profile * profile ;
612
- DEFINE_AUDIT_SK (ad , op , subj_cred , sk );
613
-
614
- ad .net .peer_sk = peer_sk ;
619
+ int plen ;
620
+ struct sockaddr_un * paddr = aa_sunaddr (unix_sk (peer_sk ),
621
+ & plen );
615
622
616
- return fn_for_each_confined (label , profile ,
617
- profile_peer_perm (profile , request , sk ,
618
- peer_sk , peer_label , & ad ));
623
+ return unix_peer_perm (subj_cred , label , op , request ,
624
+ sk , paddr , plen , peer_label );
619
625
}
620
626
621
627
return 0 ;
622
628
}
623
629
624
- static void unix_state_double_lock (struct sock * sk1 , struct sock * sk2 )
625
- {
626
- if (unlikely (sk1 == sk2 ) || !sk2 ) {
627
- unix_state_lock (sk1 );
628
- return ;
629
- }
630
- if (sk1 < sk2 ) {
631
- unix_state_lock (sk1 );
632
- unix_state_lock (sk2 );
633
- } else {
634
- unix_state_lock (sk2 );
635
- unix_state_lock (sk1 );
636
- }
637
- }
638
-
639
- static void unix_state_double_unlock (struct sock * sk1 , struct sock * sk2 )
640
- {
641
- if (unlikely (sk1 == sk2 ) || !sk2 ) {
642
- unix_state_unlock (sk1 );
643
- return ;
644
- }
645
- unix_state_unlock (sk1 );
646
- unix_state_unlock (sk2 );
647
- }
648
-
649
- /* TODO: examine replacing double lock with cached addr */
650
-
630
+ /* This fn is only checked if something has changed in the security
631
+ * boundaries. Otherwise cached info off file is sufficient
632
+ */
651
633
int aa_unix_file_perm (const struct cred * subj_cred , struct aa_label * label ,
652
634
const char * op , u32 request , struct file * file )
653
635
{
654
636
struct socket * sock = (struct socket * ) file -> private_data ;
637
+ struct sockaddr_un * addr , * peer_addr ;
638
+ int addrlen , peer_addrlen ;
655
639
struct sock * peer_sk = NULL ;
656
640
u32 sk_req = request & ~NET_PEER_MASK ;
641
+ struct path path ;
657
642
bool is_sk_fs ;
658
643
int error = 0 ;
659
644
@@ -663,40 +648,60 @@ int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label,
663
648
AA_BUG (sock -> sk -> sk_family != PF_UNIX );
664
649
665
650
/* TODO: update sock label with new task label */
651
+ /* investigate only using lock via unix_peer_get()
652
+ * addr only needs the memory barrier, but need to investigate
653
+ * path
654
+ */
666
655
unix_state_lock (sock -> sk );
667
656
peer_sk = unix_peer (sock -> sk );
668
657
if (peer_sk )
669
658
sock_hold (peer_sk );
670
659
671
660
is_sk_fs = is_unix_fs (sock -> sk );
661
+ addr = aa_sunaddr (unix_sk (sock -> sk ), & addrlen );
662
+ path = unix_sk (sock -> sk )-> path ;
663
+ unix_state_unlock (sock -> sk );
664
+
672
665
if (is_sk_fs && peer_sk )
673
666
sk_req = request ;
674
- if (sk_req )
675
- error = unix_label_sock_perm (subj_cred , label , op , sk_req ,
676
- sock );
677
- unix_state_unlock (sock -> sk );
667
+ if (sk_req ) {
668
+ if (is_sk_fs )
669
+ error = unix_fs_perm (op , sk_req , subj_cred , label ,
670
+ & path );
671
+ else
672
+ error = aa_unix_label_sk_perm (subj_cred , label , op ,
673
+ sk_req , sock -> sk );
674
+ }
678
675
if (!peer_sk )
679
- return error ;
676
+ goto out ;
677
+
678
+ peer_addr = aa_sunaddr (unix_sk (peer_sk ), & peer_addrlen );
680
679
681
- unix_state_double_lock (sock -> sk , peer_sk );
680
+ struct path peer_path ;
681
+
682
+ peer_path = unix_sk (peer_sk )-> path ;
682
683
if (!is_sk_fs && is_unix_fs (peer_sk )) {
683
684
last_error (error ,
684
685
unix_fs_perm (op , request , subj_cred , label ,
685
- unix_sk ( peer_sk ) ));
686
+ & peer_path ));
686
687
} else if (!is_sk_fs ) {
687
688
struct aa_sk_ctx * pctx = aa_sock (peer_sk );
688
689
690
+ /* no fs check of aa_unix_peer_perm because conditions above
691
+ * ensure they will never be done
692
+ */
689
693
last_error (error ,
690
- xcheck (aa_unix_peer_perm (subj_cred , label , op ,
691
- MAY_READ | MAY_WRITE ,
692
- sock -> sk , peer_sk , NULL ),
693
- aa_unix_peer_perm (file -> f_cred , pctx -> label , op ,
694
- MAY_READ | MAY_WRITE ,
695
- peer_sk , sock -> sk , label )));
694
+ xcheck (unix_peer_perm (subj_cred , label , op ,
695
+ MAY_READ | MAY_WRITE , sock -> sk ,
696
+ peer_addr , peer_addrlen ,
697
+ pctx -> label ),
698
+ unix_peer_perm (file -> f_cred , pctx -> label , op ,
699
+ MAY_READ | MAY_WRITE , peer_sk ,
700
+ addr , addrlen , label )));
696
701
}
697
- unix_state_double_unlock (sock -> sk , peer_sk );
698
-
699
702
sock_put (peer_sk );
700
703
704
+ out :
705
+
701
706
return error ;
702
707
}
0 commit comments