Skip to content

Commit b221654

Browse files
committed
1
1 parent 6c97d1d commit b221654

5 files changed

Lines changed: 387 additions & 0 deletions

File tree

kernel/selinux/rules.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@ static int sepol_expected_argc(u32 cmd)
255255
return 4;
256256
case KSU_SEPOLICY_CMD_GENFSCON:
257257
return 3;
258+
case KSU_SEPOLICY_CMD_CLONE_TYPE:
259+
return 2;
258260
default:
259261
return -EINVAL;
260262
}
@@ -423,6 +425,20 @@ static int apply_one_sepolicy_cmd(struct policydb *db, const struct sepol_data *
423425
}
424426
return 0;
425427

428+
case KSU_SEPOLICY_CMD_CLONE_TYPE:
429+
ret = sepol_require_not_all(args[0], "src");
430+
if (ret < 0)
431+
return ret;
432+
ret = sepol_require_not_all(args[1], "dst");
433+
if (ret < 0)
434+
return ret;
435+
436+
if (!ksu_clone_type(db, args[0], args[1])) {
437+
pr_err("sepol: clone_type failed.\n");
438+
return -EINVAL;
439+
}
440+
return 0;
441+
426442
default:
427443
pr_err("sepol: unknown cmd: %d\n", header->cmd);
428444
return -EINVAL;

kernel/selinux/sepolicy.c

Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,19 @@ static void add_typeattribute_raw(struct policydb *db, struct type_datum *type,
5353

5454
static 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
8061127
bool ksu_allow(struct policydb *db, const char *src, const char *tgt, const char *cls, const char *perm)
8071128
{

kernel/selinux/sepolicy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ bool ksu_permissive(struct policydb *db, const char *type);
1616
bool ksu_enforce(struct policydb *db, const char *type);
1717
bool ksu_typeattribute(struct policydb *db, const char *type, const char *attr);
1818
bool ksu_exists(struct policydb *db, const char *type);
19+
bool ksu_clone_type(struct policydb *db, const char *src, const char *dst);
1920

2021
// Access vector rules
2122
bool ksu_allow(struct policydb *db, const char *src, const char *tgt, const char *cls, const char *perm);

uapi/selinux.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ static const __u32 KSU_SEPOLICY_CMD_ATTR = 6;
1212
static const __u32 KSU_SEPOLICY_CMD_TYPE_TRANSITION = 7;
1313
static const __u32 KSU_SEPOLICY_CMD_TYPE_CHANGE = 8;
1414
static const __u32 KSU_SEPOLICY_CMD_GENFSCON = 9;
15+
static const __u32 KSU_SEPOLICY_CMD_CLONE_TYPE = 10;
1516

1617
static const __u32 KSU_SEPOLICY_SUBCMD_NORMAL_PERM_ALLOW = 1;
1718
static const __u32 KSU_SEPOLICY_SUBCMD_NORMAL_PERM_DENY = 2;

0 commit comments

Comments
 (0)