Add extended permission support

This commit is contained in:
topjohnwu 2017-04-20 04:04:09 +08:00
parent 272eb37e9a
commit 670397a73e
5 changed files with 238 additions and 5 deletions

15
api.c
View File

@ -31,6 +31,21 @@ int sepol_typetrans(char *s, char *t, char *c, char *d, char *o) {
} }
} }
int sepol_allowxperm(char *s, char *t, char *c, char *range) {
// printf("allowxperm %s %s %s %s\n", s, t, c, range);
return add_xperm_rule(s, t, c, range, AVTAB_XPERMS_ALLOWED, 0);
}
int sepol_auditallowxperm(char *s, char *t, char *c, char *range) {
// printf("auditallowxperm %s %s %s %s\n", s, t, c, range);
return add_xperm_rule(s, t, c, range, AVTAB_XPERMS_AUDITALLOW, 0);
}
int sepol_dontauditxperm(char *s, char *t, char *c, char *range) {
// printf("dontauditxperm %s %s %s %s\n", s, t, c, range);
return add_xperm_rule(s, t, c, range, AVTAB_XPERMS_DONTAUDIT, 0);
}
int sepol_permissive(char *s) { int sepol_permissive(char *s) {
// printf("permissive %s\n", s); // printf("permissive %s\n", s);
return set_domain_state(s, 1); return set_domain_state(s, 1);

View File

@ -26,11 +26,14 @@ static void statements() {
"\"deny #source-class #target-class permission-class #permission\"\n" "\"deny #source-class #target-class permission-class #permission\"\n"
"\"auditallow #source-class #target-class permission-class #permission\"\n" "\"auditallow #source-class #target-class permission-class #permission\"\n"
"\"auditdeny #source-class #target-class permission-class #permission\"\n" "\"auditdeny #source-class #target-class permission-class #permission\"\n"
"\"typetrans source-class target-class permission-class default-class (optional: object-name)\"\n"
"\"allowxperm #source-class #target-class #permission-class ioctl range\"\n"
"\"auditallowxperm #source-class #target-class #permission-class ioctl range\"\n"
"\"dontauditxperm #source-class #target-class #permission-class ioctl range\"\n"
"\"create #class\"\n" "\"create #class\"\n"
"\"permissive #class\"\n" "\"permissive #class\"\n"
"\"enforcing #class\"\n" "\"enforcing #class\"\n"
"\"attradd #class #attribute\"\n" "\"attradd #class #attribute\"\n"
"\"typetrans source-class target-class permission-class default-class (optional: object-name)\"\n"
"\nsource-class and target-class can be attributes (patches the whole group)\n" "\nsource-class and target-class can be attributes (patches the whole group)\n"
"All sections (except typetrans) can be replaced with \'*\' to patch every possible matches\n" "All sections (except typetrans) can be replaced with \'*\' to patch every possible matches\n"
"Sections marked with \'#\' can be replaced with collections in curly brackets\n" "Sections marked with \'#\' can be replaced with collections in curly brackets\n"
@ -263,6 +266,84 @@ static int parse_pattern_4(int action, char* statement) {
return 0; return 0;
} }
// Pattern 5: action { source } { target } { class } ioctl range
static int parse_pattern_5(int action, char* statement) {
int state = 0, in_bracket = 0;
char *tok, *range, *saveptr;
struct vector source, target, class, *temp;
vec_init(&source);
vec_init(&target);
vec_init(&class);
tok = strtok_r(statement, " ", &saveptr);
while (tok != NULL) {
if (tok[0] == '{') {
if (in_bracket || state == 3 || state == 4) return 1;
in_bracket = 1;
if (tok[1]) {
++tok;
continue;
}
} else if (tok[strlen(tok) - 1] == '}') {
if (!in_bracket || state == 3 || state == 4) return 1;
in_bracket = 0;
if (strlen(tok) - 1) {
tok[strlen(tok) - 1] = '\0';
continue;
}
} else {
if (tok[0] == '*') tok = ALL;
switch (state) {
case 0:
temp = &source;
break;
case 1:
temp = ⌖
break;
case 2:
temp = &class;
break;
case 3:
// Should always be ioctl
temp = NULL;
break;
case 4:
temp = NULL;
range = tok;
break;
default:
return 1;
}
vec_push_back(temp, tok);
}
if (!in_bracket) ++state;
tok = strtok_r(NULL, " ", &saveptr);
}
if (state != 5) return 1;
for(int i = 0; i < source.size; ++i)
for (int j = 0; j < target.size; ++j)
for (int k = 0; k < class.size; ++k)
switch (action) {
case 0:
if (sepol_allowxperm(source.data[i], target.data[j], class.data[k], range))
fprintf(stderr, "Error in: allowxperm %s %s %s %s\n", source.data[i], target.data[j], class.data[k], range);
break;
case 1:
if (sepol_auditallowxperm(source.data[i], target.data[j], class.data[k], range))
fprintf(stderr, "Error in: auditallowxperm %s %s %s %s\n", source.data[i], target.data[j], class.data[k], range);
break;
case 2:
if (sepol_dontauditxperm(source.data[i], target.data[j], class.data[k], range))
fprintf(stderr, "Error in: dontauditxperm %s %s %s %s\n", source.data[i], target.data[j], class.data[k], range);
break;
default:
return 1;
}
vec_destroy(&source);
vec_destroy(&target);
vec_destroy(&class);
return 0;
}
static void syntax_error_msg() { static void syntax_error_msg() {
fprintf(stderr, "Syntax error in \"%s\"\n", err_msg); fprintf(stderr, "Syntax error in \"%s\"\n", err_msg);
syntax_err = 1; syntax_err = 1;
@ -339,6 +420,15 @@ int magiskpolicy_main(int argc, char *argv[]) {
} else if (strcmp(tok, "typetrans") == 0) { } else if (strcmp(tok, "typetrans") == 0) {
if (parse_pattern_4(0, rules.data[i] + strlen(tok) + 1)) if (parse_pattern_4(0, rules.data[i] + strlen(tok) + 1))
syntax_error_msg(); syntax_error_msg();
} else if (strcmp(tok, "allowxperm") == 0) {
if (parse_pattern_5(0, rules.data[i] + strlen(tok) + 1))
syntax_error_msg();
} else if (strcmp(tok, "auditallowxperm") == 0) {
if (parse_pattern_5(1, rules.data[i] + strlen(tok) + 1))
syntax_error_msg();
} else if (strcmp(tok, "dontauditxperm") == 0) {
if (parse_pattern_5(2, rules.data[i] + strlen(tok) + 1))
syntax_error_msg();
} else { } else {
syntax_error_msg(); syntax_error_msg();
} }

View File

@ -19,6 +19,9 @@ int sepol_deny(char *s, char *t, char *c, char *p);
int sepol_auditallow(char *s, char *t, char *c, char *p); int sepol_auditallow(char *s, char *t, char *c, char *p);
int sepol_auditdeny(char *s, char *t, char *c, char *p); int sepol_auditdeny(char *s, char *t, char *c, char *p);
int sepol_typetrans(char *s, char *t, char *c, char *d, char *o); int sepol_typetrans(char *s, char *t, char *c, char *d, char *o);
int sepol_allowxperm(char *s, char *t, char *c, char *range);
int sepol_auditallowxperm(char *s, char *t, char *c, char *range);
int sepol_dontauditxperm(char *s, char *t, char *c, char *range);
int sepol_create(char *s); int sepol_create(char *s);
int sepol_permissive(char *s); int sepol_permissive(char *s);
int sepol_enforce(char *s); int sepol_enforce(char *s);

View File

@ -50,7 +50,7 @@ static int set_attr(char *type, int value) {
return 0; return 0;
} }
static int add_irule(int s, int t, int c, int p, int effect, int not) { static int __add_rule(int s, int t, int c, int p, int effect, int not) {
avtab_key_t key; avtab_key_t key;
avtab_datum_t *av; avtab_datum_t *av;
int new_rule = 0; int new_rule = 0;
@ -106,10 +106,90 @@ static int add_rule_auto(type_datum_t *src, type_datum_t *tgt, class_datum_t *cl
} else if (cls == NULL) { } else if (cls == NULL) {
hashtab_for_each(policydb->p_classes.table, &cur) { hashtab_for_each(policydb->p_classes.table, &cur) {
cls = cur->datum; cls = cur->datum;
ret |= add_irule(src->s.value, tgt->s.value, cls->s.value, -1, effect, not); ret |= __add_rule(src->s.value, tgt->s.value, cls->s.value, -1, effect, not);
} }
} else { } else {
return add_irule(src->s.value, tgt->s.value, cls->s.value, perm ? perm->s.value : -1, effect, not); return __add_rule(src->s.value, tgt->s.value, cls->s.value, perm ? perm->s.value : -1, effect, not);
}
return ret;
}
#define ioctl_driver(x) (x>>8 & 0xFF)
#define ioctl_func(x) (x & 0xFF)
static int __add_xperm_rule(int s, int t, int c, uint16_t low, uint16_t high, int effect, int not) {
avtab_key_t key;
avtab_datum_t *av;
int new_rule = 0;
key.source_type = s;
key.target_type = t;
key.target_class = c;
key.specified = effect;
av = avtab_search(&policydb->te_avtab, &key);
if (av == NULL) {
av = cmalloc(sizeof(*av));
av->xperms = cmalloc(sizeof(avtab_extended_perms_t));
new_rule = 1;
if (ioctl_driver(low) != ioctl_driver(high)) {
av->xperms->specified = AVTAB_XPERMS_IOCTLDRIVER;
av->xperms->driver = 0;
} else {
av->xperms->specified = AVTAB_XPERMS_IOCTLFUNCTION;
av->xperms->driver = ioctl_driver(low);
}
}
if (av->xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
for (unsigned i = ioctl_driver(low); i <= ioctl_driver(high); ++i) {
if (not)
xperm_clear(i, av->xperms->perms);
else
xperm_set(i, av->xperms->perms);
}
} else {
for (unsigned i = ioctl_func(low); i <= ioctl_func(high); ++i) {
if (not)
xperm_clear(i, av->xperms->perms);
else
xperm_set(i, av->xperms->perms);
}
}
if (new_rule) {
if (avtab_insert(&policydb->te_avtab, &key, av)) {
fprintf(stderr, "Error inserting into avtab\n");
return 1;
}
free(av);
}
return 0;
}
static int add_xperm_rule_auto(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls,
uint16_t low, uint16_t high, int effect, int not) {
hashtab_ptr_t cur;
int ret = 0;
if (src == NULL) {
hashtab_for_each(policydb->p_types.table, &cur) {
src = cur->datum;
ret |= add_xperm_rule_auto(src, tgt, cls, low, high, effect, not);
}
} else if (tgt == NULL) {
hashtab_for_each(policydb->p_types.table, &cur) {
tgt = cur->datum;
ret |= add_xperm_rule_auto(src, tgt, cls, low, high, effect, not);
}
} else if (cls == NULL) {
hashtab_for_each(policydb->p_classes.table, &cur) {
cls = cur->datum;
ret |= __add_xperm_rule(src->s.value, tgt->s.value, cls->s.value, low, high, effect, not);
}
} else {
return __add_xperm_rule(src->s.value, tgt->s.value, cls->s.value, low, high, effect, not);
} }
return ret; return ret;
} }
@ -307,7 +387,6 @@ int add_transition(char *s, char *t, char *c, char *d) {
key.target_class = cls->s.value; key.target_class = cls->s.value;
key.specified = AVTAB_TRANSITION; key.specified = AVTAB_TRANSITION;
av = avtab_search(&policydb->te_avtab, &key); av = avtab_search(&policydb->te_avtab, &key);
if (av == NULL) { if (av == NULL) {
av = cmalloc(sizeof(*av)); av = cmalloc(sizeof(*av));
new_rule = 1; new_rule = 1;
@ -446,3 +525,48 @@ int add_rule(char *s, char *t, char *c, char *p, int effect, int not) {
} }
return add_rule_auto(src, tgt, cls, perm, effect, not); return add_rule_auto(src, tgt, cls, perm, effect, not);
} }
int add_xperm_rule(char *s, char *t, char *c, char *range, int effect, int not) {
type_datum_t *src = NULL, *tgt = NULL;
class_datum_t *cls = NULL;
if (s) {
src = hashtab_search(policydb->p_types.table, s);
if (src == NULL) {
fprintf(stderr, "source type %s does not exist\n", s);
return 1;
}
}
if (t) {
tgt = hashtab_search(policydb->p_types.table, t);
if (tgt == NULL) {
fprintf(stderr, "target type %s does not exist\n", t);
return 1;
}
}
if (c) {
cls = hashtab_search(policydb->p_classes.table, c);
if (cls == NULL) {
fprintf(stderr, "class %s does not exist\n", c);
return 1;
}
}
uint16_t low, high;
if (range) {
if (strchr(range, '-')){
sscanf(range, "%hx-%hx", &low, &high);
} else {
sscanf(range, "%hx", &low);
high = low;
}
} else {
low = 0;
high = 0xFFFF;
}
return add_xperm_rule_auto(src, tgt, cls, low, high, effect, not);
}

View File

@ -42,6 +42,7 @@ int add_transition(char *s, char *t, char *c, char *d);
int add_file_transition(char *s, char *t, char *c, char *d, char* filename); int add_file_transition(char *s, char *t, char *c, char *d, char* filename);
int add_typeattribute(char *domainS, char *attr); int add_typeattribute(char *domainS, char *attr);
int add_rule(char *s, char *t, char *c, char *p, int effect, int not); int add_rule(char *s, char *t, char *c, char *p, int effect, int not);
int add_xperm_rule(char *s, char *t, char *c, char *range, int effect, int not);
extern int policydb_index_decls(sepol_handle_t * handle, policydb_t * p); extern int policydb_index_decls(sepol_handle_t * handle, policydb_t * p);