@@ -595,6 +595,40 @@ static const struct file_operations aa_fs_ns_revision_fops = {
595
595
.release = ns_revision_release ,
596
596
};
597
597
598
+ static void profile_query_cb (struct aa_profile * profile , struct aa_perms * perms ,
599
+ const char * match_str , size_t match_len )
600
+ {
601
+ struct aa_perms tmp ;
602
+ struct aa_dfa * dfa ;
603
+ unsigned int state = 0 ;
604
+
605
+ if (unconfined (profile ))
606
+ return ;
607
+ if (profile -> file .dfa && * match_str == AA_CLASS_FILE ) {
608
+ dfa = profile -> file .dfa ;
609
+ state = aa_dfa_match_len (dfa , profile -> file .start ,
610
+ match_str + 1 , match_len - 1 );
611
+ tmp = nullperms ;
612
+ if (state ) {
613
+ struct path_cond cond = { };
614
+
615
+ tmp = aa_compute_fperms (dfa , state , & cond );
616
+ }
617
+ } else if (profile -> policy .dfa ) {
618
+ if (!PROFILE_MEDIATES_SAFE (profile , * match_str ))
619
+ return ; /* no change to current perms */
620
+ dfa = profile -> policy .dfa ;
621
+ state = aa_dfa_match_len (dfa , profile -> policy .start [0 ],
622
+ match_str , match_len );
623
+ if (state )
624
+ aa_compute_perms (dfa , state , & tmp );
625
+ else
626
+ tmp = nullperms ;
627
+ }
628
+ aa_apply_modes_to_perms (profile , & tmp );
629
+ }
630
+
631
+
598
632
/**
599
633
* query_data - queries a policy and writes its data to buf
600
634
* @buf: the resulting data is stored here (NOT NULL)
@@ -673,6 +707,64 @@ static ssize_t query_data(char *buf, size_t buf_len,
673
707
return out - buf ;
674
708
}
675
709
710
+ /**
711
+ * query_label - queries a label and writes permissions to buf
712
+ * @buf: the resulting permissions string is stored here (NOT NULL)
713
+ * @buf_len: size of buf
714
+ * @query: binary query string to match against the dfa
715
+ * @query_len: size of query
716
+ * @view_only: only compute for querier's view
717
+ *
718
+ * The buffers pointed to by buf and query may overlap. The query buffer is
719
+ * parsed before buf is written to.
720
+ *
721
+ * The query should look like "LABEL_NAME\0DFA_STRING" where LABEL_NAME is
722
+ * the name of the label, in the current namespace, that is to be queried and
723
+ * DFA_STRING is a binary string to match against the label(s)'s DFA.
724
+ *
725
+ * LABEL_NAME must be NUL terminated. DFA_STRING may contain NUL characters
726
+ * but must *not* be NUL terminated.
727
+ *
728
+ * Returns: number of characters written to buf or -errno on failure
729
+ */
730
+ static ssize_t query_label (char * buf , size_t buf_len ,
731
+ char * query , size_t query_len , bool view_only )
732
+ {
733
+ struct aa_profile * profile , * curr ;
734
+ char * label_name , * match_str ;
735
+ size_t label_name_len , match_len ;
736
+ struct aa_perms perms ;
737
+
738
+ if (!query_len )
739
+ return - EINVAL ;
740
+
741
+ label_name = query ;
742
+ label_name_len = strnlen (query , query_len );
743
+ if (!label_name_len || label_name_len == query_len )
744
+ return - EINVAL ;
745
+
746
+ /**
747
+ * The extra byte is to account for the null byte between the
748
+ * profile name and dfa string. profile_name_len is greater
749
+ * than zero and less than query_len, so a byte can be safely
750
+ * added or subtracted.
751
+ */
752
+ match_str = label_name + label_name_len + 1 ;
753
+ match_len = query_len - label_name_len - 1 ;
754
+
755
+ curr = aa_current_profile ();
756
+ profile = aa_fqlookupn_profile (curr , label_name , label_name_len );
757
+ if (!profile )
758
+ return - ENOENT ;
759
+
760
+ perms = allperms ;
761
+ profile_query_cb (profile , & perms , match_str , match_len );
762
+
763
+ return scnprintf (buf , buf_len ,
764
+ "allow 0x%08x\ndeny 0x%08x\naudit 0x%08x\nquiet 0x%08x\n" ,
765
+ perms .allow , perms .deny , perms .audit , perms .quiet );
766
+ }
767
+
676
768
/*
677
769
* Transaction based IO.
678
770
* The file expects a write which triggers the transaction, and then
@@ -773,6 +865,9 @@ static int multi_transaction_release(struct inode *inode, struct file *file)
773
865
return 0 ;
774
866
}
775
867
868
+ #define QUERY_CMD_PROFILE "profile\0"
869
+ #define QUERY_CMD_PROFILE_LEN 8
870
+
776
871
#define QUERY_CMD_DATA "data\0"
777
872
#define QUERY_CMD_DATA_LEN 5
778
873
@@ -810,7 +905,12 @@ static ssize_t aa_write_access(struct file *file, const char __user *ubuf,
810
905
if (IS_ERR (t ))
811
906
return PTR_ERR (t );
812
907
813
- if (count > QUERY_CMD_DATA_LEN &&
908
+ if (count > QUERY_CMD_PROFILE_LEN &&
909
+ !memcmp (t -> data , QUERY_CMD_PROFILE , QUERY_CMD_PROFILE_LEN )) {
910
+ len = query_label (t -> data , MULTI_TRANSACTION_LIMIT ,
911
+ t -> data + QUERY_CMD_PROFILE_LEN ,
912
+ count - QUERY_CMD_PROFILE_LEN , true);
913
+ } else if (count > QUERY_CMD_DATA_LEN &&
814
914
!memcmp (t -> data , QUERY_CMD_DATA , QUERY_CMD_DATA_LEN )) {
815
915
len = query_data (t -> data , MULTI_TRANSACTION_LIMIT ,
816
916
t -> data + QUERY_CMD_DATA_LEN ,
@@ -1952,6 +2052,7 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = {
1952
2052
};
1953
2053
1954
2054
static struct aa_sfs_entry aa_sfs_entry_query_label [] = {
2055
+ AA_SFS_FILE_STRING ("perms" , "allow deny audit quiet" ),
1955
2056
AA_SFS_FILE_BOOLEAN ("data" , 1 ),
1956
2057
AA_SFS_FILE_BOOLEAN ("multi_transaction" , 1 ),
1957
2058
{ }
0 commit comments