Add extended permission support
This commit is contained in:
parent
272eb37e9a
commit
670397a73e
15
api.c
15
api.c
@ -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) {
|
||||
// printf("permissive %s\n", s);
|
||||
return set_domain_state(s, 1);
|
||||
|
@ -26,11 +26,14 @@ static void statements() {
|
||||
"\"deny #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"
|
||||
"\"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"
|
||||
"\"permissive #class\"\n"
|
||||
"\"enforcing #class\"\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"
|
||||
"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"
|
||||
@ -263,6 +266,84 @@ static int parse_pattern_4(int action, char* statement) {
|
||||
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() {
|
||||
fprintf(stderr, "Syntax error in \"%s\"\n", err_msg);
|
||||
syntax_err = 1;
|
||||
@ -339,6 +420,15 @@ int magiskpolicy_main(int argc, char *argv[]) {
|
||||
} else if (strcmp(tok, "typetrans") == 0) {
|
||||
if (parse_pattern_4(0, rules.data[i] + strlen(tok) + 1))
|
||||
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 {
|
||||
syntax_error_msg();
|
||||
}
|
||||
|
@ -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_auditdeny(char *s, char *t, char *c, char *p);
|
||||
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_permissive(char *s);
|
||||
int sepol_enforce(char *s);
|
||||
|
132
sepolicy.c
132
sepolicy.c
@ -50,7 +50,7 @@ static int set_attr(char *type, int value) {
|
||||
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_datum_t *av;
|
||||
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) {
|
||||
hashtab_for_each(policydb->p_classes.table, &cur) {
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
@ -307,7 +387,6 @@ int add_transition(char *s, char *t, char *c, char *d) {
|
||||
key.target_class = cls->s.value;
|
||||
key.specified = AVTAB_TRANSITION;
|
||||
av = avtab_search(&policydb->te_avtab, &key);
|
||||
|
||||
if (av == NULL) {
|
||||
av = cmalloc(sizeof(*av));
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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_typeattribute(char *domainS, char *attr);
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user