@@ -53,6 +53,19 @@ static void add_typeattribute_raw(struct policydb *db, struct type_datum *type,
5353
5454static bool add_typeattribute (struct policydb * db , const char * type , const char * attr );
5555
56+ static bool clone_type_attributes (struct policydb * db , struct type_datum * src , struct type_datum * dst , u32 * copied );
57+
58+ static bool clone_type_roles (struct policydb * db , struct type_datum * src , struct type_datum * dst );
59+
60+ static bool clone_type_constraints (struct policydb * db , struct type_datum * src , struct type_datum * dst , u32 * copied );
61+
62+ static bool clone_type_permissive (struct policydb * db , struct type_datum * src , struct type_datum * dst , bool * copied );
63+
64+ static bool clone_avtab_rules (struct policydb * db , struct type_datum * src , struct type_datum * dst , u32 * copied );
65+
66+ static bool clone_filename_trans_rules (struct policydb * db , struct type_datum * src , struct type_datum * dst ,
67+ u32 * copied );
68+
5669//////////////////////////////////////////////////////
5770// Implementation
5871//////////////////////////////////////////////////////
@@ -769,6 +782,257 @@ static bool add_typeattribute(struct policydb *db, const char *type, const char
769782 return true;
770783}
771784
785+ static bool clone_type_attributes (struct policydb * db , struct type_datum * src , struct type_datum * dst , u32 * copied )
786+ {
787+ struct ebitmap * src_attrs = & db -> type_attr_map_array [src -> value - 1 ];
788+ u32 bit ;
789+
790+ for (bit = 0 ; bit <= src_attrs -> highbit ; bit ++ ) {
791+ struct type_datum * attr ;
792+
793+ if (!ebitmap_get_bit (src_attrs , bit ))
794+ continue ;
795+
796+ attr = db -> type_val_to_struct [bit ];
797+ if (!attr || !attr -> attribute )
798+ continue ;
799+
800+ add_typeattribute_raw (db , dst , attr );
801+ (* copied )++ ;
802+ }
803+
804+ return true;
805+ }
806+
807+ static bool clone_type_roles (struct policydb * db , struct type_datum * src , struct type_datum * dst )
808+ {
809+ int i ;
810+
811+ for (i = 0 ; i < db -> p_roles .nprim ; i ++ ) {
812+ struct role_datum * role = db -> role_val_to_struct [i ];
813+ bool has_src ;
814+
815+ if (!role )
816+ continue ;
817+
818+ has_src = ebitmap_get_bit (& role -> types , src -> value - 1 );
819+ if (ebitmap_set_bit (& role -> types , dst -> value - 1 , has_src ? 1 : 0 ))
820+ return false;
821+ }
822+
823+ return true;
824+ }
825+
826+ static bool clone_type_constraints (struct policydb * db , struct type_datum * src , struct type_datum * dst , u32 * copied )
827+ {
828+ struct hashtab_node * node ;
829+
830+ ksu_hashtab_for_each (db -> p_classes .table , node )
831+ {
832+ struct class_datum * cls = (struct class_datum * )node -> datum ;
833+ struct constraint_node * n ;
834+
835+ for (n = cls -> constraints ; n ; n = n -> next ) {
836+ struct constraint_expr * e ;
837+
838+ for (e = n -> expr ; e ; e = e -> next ) {
839+ if (e -> expr_type == CEXPR_NAMES && ebitmap_get_bit (& e -> names , src -> value - 1 ) &&
840+ ebitmap_set_bit (& e -> names , dst -> value - 1 , 1 )) {
841+ return false;
842+ } else if (e -> expr_type == CEXPR_NAMES && ebitmap_get_bit (& e -> names , src -> value - 1 )) {
843+ (* copied )++ ;
844+ }
845+ }
846+ }
847+
848+ for (n = cls -> validatetrans ; n ; n = n -> next ) {
849+ struct constraint_expr * e ;
850+
851+ for (e = n -> expr ; e ; e = e -> next ) {
852+ if (e -> expr_type == CEXPR_NAMES && ebitmap_get_bit (& e -> names , src -> value - 1 ) &&
853+ ebitmap_set_bit (& e -> names , dst -> value - 1 , 1 )) {
854+ return false;
855+ } else if (e -> expr_type == CEXPR_NAMES && ebitmap_get_bit (& e -> names , src -> value - 1 )) {
856+ (* copied )++ ;
857+ }
858+ }
859+ }
860+ }
861+
862+ return true;
863+ }
864+
865+ static bool clone_type_permissive (struct policydb * db , struct type_datum * src , struct type_datum * dst , bool * copied )
866+ {
867+ if (!ebitmap_get_bit (& db -> permissive_map , src -> value ))
868+ return true;
869+
870+ * copied = true;
871+ return ebitmap_set_bit (& db -> permissive_map , dst -> value , 1 ) == 0 ;
872+ }
873+
874+ static bool clone_avtab_rules (struct policydb * db , struct type_datum * src , struct type_datum * dst , u32 * copied )
875+ {
876+ struct avtab_node * * snapshot ;
877+ struct avtab_node * node ;
878+ u32 idx = 0 ;
879+ u32 count = db -> te_avtab .nel ;
880+
881+ if (count == 0 )
882+ return true;
883+
884+ snapshot = kvcalloc (count , sizeof (* snapshot ), GFP_KERNEL );
885+ if (!snapshot )
886+ return false;
887+
888+ avtab_for_each (db -> te_avtab , node )
889+ {
890+ snapshot [idx ++ ] = node ;
891+ }
892+
893+ count = idx ;
894+ for (idx = 0 ; idx < count ; idx ++ ) {
895+ struct avtab_key key ;
896+ struct avtab_node * new_node ;
897+ struct avtab_extended_perms * new_xperms = NULL ;
898+ struct avtab_node * old_node = snapshot [idx ];
899+
900+ if (old_node -> key .source_type != src -> value && old_node -> key .target_type != src -> value )
901+ continue ;
902+
903+ key = old_node -> key ;
904+ if (key .source_type == src -> value )
905+ key .source_type = dst -> value ;
906+ if (key .target_type == src -> value )
907+ key .target_type = dst -> value ;
908+
909+ if (key .specified & AVTAB_XPERMS ) {
910+ new_xperms = kmemdup (old_node -> datum .u .xperms , sizeof (* new_xperms ), GFP_KERNEL );
911+ if (!new_xperms )
912+ goto err ;
913+ new_node = get_avtab_node (db , & key , new_xperms );
914+ if (!new_node )
915+ goto err ;
916+ if (new_node -> datum .u .xperms != new_xperms ) {
917+ kfree (new_xperms );
918+ new_node -> datum .u .xperms = kmemdup (old_node -> datum .u .xperms , sizeof (* new_xperms ), GFP_KERNEL );
919+ if (!new_node -> datum .u .xperms )
920+ goto err ;
921+ }
922+ (* copied )++ ;
923+ } else {
924+ new_node = get_avtab_node (db , & key , NULL );
925+ if (!new_node )
926+ goto err ;
927+ new_node -> datum .u .data = old_node -> datum .u .data ;
928+ if ((key .specified & AVTAB_TYPE ) && new_node -> datum .u .data == src -> value )
929+ new_node -> datum .u .data = dst -> value ;
930+ (* copied )++ ;
931+ }
932+ }
933+
934+ kvfree (snapshot );
935+ return true;
936+
937+ err :
938+ kvfree (snapshot );
939+ return false;
940+ }
941+
942+ static bool clone_filename_trans_rules (struct policydb * db , struct type_datum * src , struct type_datum * dst , u32 * copied )
943+ {
944+ struct filename_trans_datum * * datums ;
945+ struct filename_trans_key * * keys ;
946+ struct hashtab_node * node ;
947+ u32 idx = 0 ;
948+ u32 count = 0 ;
949+ int slot ;
950+
951+ for (slot = 0 ; slot < db -> filename_trans .size ; slot ++ ) {
952+ for (node = db -> filename_trans .htable [slot ]; node ; node = node -> next ) {
953+ struct filename_trans_datum * datum = node -> datum ;
954+ while (datum ) {
955+ count ++ ;
956+ datum = datum -> next ;
957+ }
958+ }
959+ }
960+
961+ if (count == 0 )
962+ return true;
963+
964+ datums = kvcalloc (count , sizeof (* datums ), GFP_KERNEL );
965+ if (!datums )
966+ return false;
967+ keys = kvcalloc (count , sizeof (* keys ), GFP_KERNEL );
968+ if (!keys ) {
969+ kvfree (datums );
970+ return false;
971+ }
972+
973+ for (slot = 0 ; slot < db -> filename_trans .size ; slot ++ ) {
974+ for (node = db -> filename_trans .htable [slot ]; node ; node = node -> next ) {
975+ struct filename_trans_key * key = node -> key ;
976+ struct filename_trans_datum * datum = node -> datum ;
977+ while (datum ) {
978+ if (idx >= count )
979+ break ;
980+ keys [idx ] = key ;
981+ datums [idx ] = datum ;
982+ idx ++ ;
983+ datum = datum -> next ;
984+ }
985+ }
986+ }
987+
988+ count = idx ;
989+ for (idx = 0 ; idx < count ; idx ++ ) {
990+ struct filename_trans_key * key = keys [idx ];
991+ struct filename_trans_datum * datum = datums [idx ];
992+ const char * src_name ;
993+ const char * tgt_name ;
994+ const char * def_name ;
995+ u32 bit ;
996+
997+ if (key -> ttype != src -> value && datum -> otype != src -> value && !ebitmap_get_bit (& datum -> stypes , src -> value - 1 ))
998+ continue ;
999+
1000+ tgt_name = sym_name (db , SYM_TYPES , (key -> ttype == src -> value ? dst -> value : key -> ttype ) - 1 );
1001+ def_name = sym_name (db , SYM_TYPES , (datum -> otype == src -> value ? dst -> value : datum -> otype ) - 1 );
1002+ if (!tgt_name || !def_name )
1003+ goto err ;
1004+
1005+ for (bit = 0 ; bit <= datum -> stypes .highbit ; bit ++ ) {
1006+ u32 source_type ;
1007+
1008+ if (!ebitmap_get_bit (& datum -> stypes , bit ))
1009+ continue ;
1010+
1011+ source_type = bit + 1 ;
1012+ if (source_type == src -> value )
1013+ src_name = sym_name (db , SYM_TYPES , dst -> value - 1 );
1014+ else
1015+ src_name = sym_name (db , SYM_TYPES , source_type - 1 );
1016+ if (!src_name )
1017+ goto err ;
1018+
1019+ if (!add_filename_trans (db , src_name , tgt_name , sym_name (db , SYM_CLASSES , key -> tclass - 1 ), def_name ,
1020+ key -> name ))
1021+ goto err ;
1022+ (* copied )++ ;
1023+ }
1024+ }
1025+
1026+ kvfree (keys );
1027+ kvfree (datums );
1028+ return true;
1029+
1030+ err :
1031+ kvfree (keys );
1032+ kvfree (datums );
1033+ return false;
1034+ }
1035+
7721036//////////////////////////////////////////////////////////////////////////
7731037
7741038// Operation on types
@@ -802,6 +1066,63 @@ bool ksu_exists(struct policydb *db, const char *type)
8021066 return symtab_search (& db -> p_types , type ) != NULL ;
8031067}
8041068
1069+ bool ksu_clone_type (struct policydb * db , const char * src , const char * dst )
1070+ {
1071+ struct type_datum * src_d ;
1072+ struct type_datum * dst_d ;
1073+ u32 attr_count = 0 ;
1074+ u32 constraint_count = 0 ;
1075+ u32 avtab_count = 0 ;
1076+ u32 filename_trans_count = 0 ;
1077+ bool permissive_copied = false;
1078+
1079+ if (!src || !dst ) {
1080+ pr_err ("clone_type: source/destination cannot be NULL\n" );
1081+ return false;
1082+ }
1083+
1084+ if (!strcmp (src , dst )) {
1085+ pr_err ("clone_type: source and destination must differ (%s)\n" , src );
1086+ return false;
1087+ }
1088+
1089+ src_d = symtab_search (& db -> p_types , src );
1090+ if (!src_d || src_d -> attribute ) {
1091+ pr_err ("clone_type: invalid source type %s\n" , src );
1092+ return false;
1093+ }
1094+
1095+ if (symtab_search (& db -> p_types , dst ) != NULL ) {
1096+ pr_err ("clone_type: destination type %s already exists\n" , dst );
1097+ return false;
1098+ }
1099+
1100+ if (!add_type (db , dst , false))
1101+ return false;
1102+
1103+ dst_d = symtab_search (& db -> p_types , dst );
1104+ if (!dst_d || dst_d -> attribute )
1105+ return false;
1106+
1107+ if (!clone_type_attributes (db , src_d , dst_d , & attr_count ))
1108+ return false;
1109+ if (!clone_type_roles (db , src_d , dst_d ))
1110+ return false;
1111+ if (!clone_type_constraints (db , src_d , dst_d , & constraint_count ))
1112+ return false;
1113+ if (!clone_type_permissive (db , src_d , dst_d , & permissive_copied ))
1114+ return false;
1115+ if (!clone_avtab_rules (db , src_d , dst_d , & avtab_count ))
1116+ return false;
1117+ if (!clone_filename_trans_rules (db , src_d , dst_d , & filename_trans_count ))
1118+ return false;
1119+
1120+ pr_info ("clone_type: %s -> %s attrs=%u constraints=%u avtab=%u filename_trans=%u permissive=%d\n" , src , dst ,
1121+ attr_count , constraint_count , avtab_count , filename_trans_count , permissive_copied ? 1 : 0 );
1122+
1123+ return true;
1124+ }
1125+
8051126// Access vector rules
8061127bool ksu_allow (struct policydb * db , const char * src , const char * tgt , const char * cls , const char * perm )
8071128{
0 commit comments