Add support for genfscon sepolicy rules

Close #2367
This commit is contained in:
topjohnwu 2020-02-02 01:16:42 +08:00
parent cf589f8c64
commit 6180558068
5 changed files with 118 additions and 10 deletions

View File

@ -28,6 +28,7 @@ int sepol_create(const char *s);
int sepol_permissive(const char *s);
int sepol_enforce(const char *s);
int sepol_attradd(const char *s, const char *a);
int sepol_genfscon(const char *name, const char *path, const char *context);
int sepol_exists(const char *source);
// Built in rules

View File

@ -80,6 +80,11 @@ int sepol_attradd(const char *s, const char *a) {
return add_typeattribute(s, a);
}
int sepol_genfscon(const char *name, const char *path, const char *context) {
vprint("genfscon %s %s %s\n", name, path, context);
return add_genfscon(name, path, context);
}
int sepol_exists(const char *source) {
return hashtab_search(magisk_policydb->p_types.table, source) != nullptr;
}

View File

@ -11,18 +11,25 @@ policydb_t *magisk_policydb = NULL;
extern void *xmalloc(size_t size);
extern void *xcalloc(size_t nmemb, size_t size);
extern void *xrealloc(void *ptr, size_t size);
// Internal libsepol APIs
extern int policydb_index_decls(sepol_handle_t * handle, policydb_t * p);
extern int context_from_string(
sepol_handle_t * handle,
const policydb_t * policydb,
context_struct_t ** cptr,
const char *con_str, size_t con_str_len);
// Generic hash table traversal
#define hash_for_each(node_ptr, n_slots, table, block) \
for (int __i = 0; __i < (table)->n_slots; ++__i) { \
__typeof__(*(table)->node_ptr) node; \
__typeof__(node) __next; \
for (node = (table)->node_ptr[__i]; node; node = __next) { \
__next = node->next; \
block \
} \
for (int __i = 0; __i < (table)->n_slots; ++__i) { \
__typeof__(*(table)->node_ptr) node; \
__typeof__(node) __next; \
for (node = (table)->node_ptr[__i]; node; node = __next) { \
__next = node->next; \
block \
} \
}
// hashtab traversal
#define hashtab_for_each(hashtab, block) \
@ -488,6 +495,66 @@ int add_type_rule(const char *s, const char *t, const char *c, const char *d, in
return 0;
}
int add_genfscon(const char *name, const char *path, const char *context) {
// First try to create context
context_struct_t *ctx;
if (context_from_string(NULL, mpdb, &ctx, context, strlen(context))) {
LOGW("Failed to create context from string [%s]\n", context);
return 1;
}
// Allocate genfs context
ocontext_t *newc = xcalloc(sizeof(*newc), 1);
newc->u.name = strdup(path);
memcpy(&newc->context[0], ctx, sizeof(*ctx));
free(ctx);
// Find or allocate genfs
genfs_t *last_gen = NULL;
genfs_t *newfs = NULL;
for (genfs_t *node = mpdb->genfs; node; node = node->next) {
if (strcmp(node->fstype, name) == 0) {
newfs = node;
break;
}
last_gen = node;
}
if (newfs == NULL) {
newfs = xcalloc(sizeof(*newfs), 1);
newfs->fstype = strdup(name);
// Insert
if (last_gen)
last_gen->next = newfs;
else
mpdb->genfs = newfs;
}
// Insert or replace genfs context
ocontext_t *last_ctx = NULL;
for (ocontext_t *node = newfs->head; node; node = node->next) {
if (strcmp(node->u.name, path) == 0) {
// Unlink
if (last_ctx)
last_ctx->next = node->next;
else
newfs->head = NULL;
// Destroy old node
free(node->u.name);
context_destroy(&node->context[0]);
free(node);
break;
}
last_ctx = node;
}
// Insert
if (last_ctx)
last_ctx->next = newc;
else
newfs->head = newc;
return 0;
}
void strip_dontaudit() {
avtab_for_each(&mpdb->te_avtab, {
if (node->key.specified == AVTAB_AUDITDENY || node->key.specified == AVTAB_XPERMS_DONTAUDIT)

View File

@ -14,6 +14,7 @@ int add_rule(const char *s, const char *t, const char *c, const char *p, int eff
int add_xperm_rule(const char *s, const char *t, const char *c, const char *range, int effect, int n);
int add_type_rule(const char *s, const char *t, const char *c, const char *d, int effect);
int add_filename_trans(const char *s, const char *t, const char *c, const char *d, const char *o);
int add_genfscon(const char *name, const char *path, const char *context);
void strip_dontaudit();
__END_DECLS

View File

@ -44,6 +44,11 @@ R"EOF(Type 6:
"name_transition source_type target_type class default_type object_name"
)EOF";
static const char *type_msg_7 =
R"EOF(Type 7:
"genfscon fs_name partial_path fs_context"
)EOF";
void statement_help() {
fprintf(stderr,
R"EOF(One policy statement should be treated as one parameter;
@ -63,8 +68,9 @@ Supported policy statements:
%s
%s
%s
%s
Notes:
* Type 4 - 6 does not support collections
* Type 4 - 7 does not support collections
* Object classes cannot be collections
* source_type and target_type can also be attributes
@ -76,7 +82,7 @@ allow s1 t2 class { all-permissions }
allow s2 t1 class { all-permissions }
allow s2 t2 class { all-permissions }
)EOF", type_msg_1, type_msg_2, type_msg_3, type_msg_4, type_msg_5, type_msg_6);
)EOF", type_msg_1, type_msg_2, type_msg_3, type_msg_4, type_msg_5, type_msg_6, type_msg_7);
exit(0);
}
@ -371,12 +377,39 @@ static int parse_pattern_6(int action, const char *action_str, char *stmt) {
}
++state;
}
if (state < 4) return 1;
if (state < 5) return 1;
if (sepol_nametrans(source, target, cls, def, filename))
LOGW("Error in: %s %s %s %s %s %s\n", action_str, source, target, cls, def, filename);
return 0;
}
// Pattern 7: action name path context
static int parse_pattern_7(int action, const char *action_str, char *stmt) {
int state = 0;
char *cur;
char *name, *path, *context;
while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) {
switch(state) {
case 0:
name = cur;
break;
case 1:
path = cur;
break;
case 2:
context = cur;
break;
default:
return 1;
}
++state;
}
if (state < 3) return 1;
if (sepol_genfscon(name, path, context))
LOGW("Error in: %s %s %s %s\n", action_str, name, path, context);
return 0;
}
#define add_action(name, type, num) \
else if (strcmp(name, action) == 0) { \
if (parse_pattern_##type(num, name, remain)) \
@ -412,6 +445,7 @@ void parse_statement(const char *statement) {
add_action("type_change", 5, 1)
add_action("type_member", 5, 2)
add_action("name_transition", 6, 0)
add_action("genfscon", 7, 0)
else { LOGW("Unknown statement: '%s'\n\n", statement); }
}