mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
apparmor: group dfa policydb unpacking
There are currently three policydb rule groupings (xmatch, file, policydb) that each do their own slightly different thing. Group them into a single routine and unify. This extends/unifies dfa features by - all dfas are allowed having an optional start field - all dfas are allowed having a string/transition table Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
a0792e2ced
commit
ad596ea74e
@ -648,6 +648,54 @@ fail:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy,
|
||||||
|
bool required_dfa, bool required_trans,
|
||||||
|
const char **info)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
policy->dfa = unpack_dfa(e);
|
||||||
|
if (IS_ERR(policy->dfa)) {
|
||||||
|
int error = PTR_ERR(policy->dfa);
|
||||||
|
|
||||||
|
policy->dfa = NULL;
|
||||||
|
*info = "failed to unpack - dfa";
|
||||||
|
return error;
|
||||||
|
} else if (!policy->dfa) {
|
||||||
|
if (required_dfa) {
|
||||||
|
*info = "missing required dfa";
|
||||||
|
return -EPROTO;
|
||||||
|
}
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* only unpack the following if a dfa is present
|
||||||
|
*
|
||||||
|
* sadly start was given different names for file and policydb
|
||||||
|
* but since it is optional we can try both
|
||||||
|
*/
|
||||||
|
if (!unpack_u32(e, &policy->start[0], "start"))
|
||||||
|
/* default start state */
|
||||||
|
policy->start[0] = DFA_START;
|
||||||
|
if (!unpack_u32(e, &policy->start[AA_CLASS_FILE], "dfa_start")) {
|
||||||
|
/* default start state for xmatch and file dfa */
|
||||||
|
policy->start[AA_CLASS_FILE] = DFA_START;
|
||||||
|
} /* setup class index */
|
||||||
|
for (i = AA_CLASS_FILE + 1; i <= AA_CLASS_LAST; i++) {
|
||||||
|
policy->start[i] = aa_dfa_next(policy->dfa, policy->start[0],
|
||||||
|
i);
|
||||||
|
}
|
||||||
|
if (!unpack_trans_table(e, &policy->trans) && required_trans) {
|
||||||
|
*info = "failed to unpack profile transition table";
|
||||||
|
return -EPROTO;
|
||||||
|
}
|
||||||
|
/* TODO: move compat mapping here, requires dfa merging first */
|
||||||
|
|
||||||
|
out:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static u32 strhash(const void *data, u32 len, u32 seed)
|
static u32 strhash(const void *data, u32 len, u32 seed)
|
||||||
{
|
{
|
||||||
const char * const *key = data;
|
const char * const *key = data;
|
||||||
@ -679,7 +727,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
|
|||||||
struct rhashtable_params params = { 0 };
|
struct rhashtable_params params = { 0 };
|
||||||
char *key = NULL;
|
char *key = NULL;
|
||||||
struct aa_data *data;
|
struct aa_data *data;
|
||||||
int i, error = -EPROTO;
|
int error = -EPROTO;
|
||||||
kernel_cap_t tmpcap;
|
kernel_cap_t tmpcap;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
@ -714,13 +762,10 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
|
|||||||
(void) unpack_str(e, &profile->attach, "attach");
|
(void) unpack_str(e, &profile->attach, "attach");
|
||||||
|
|
||||||
/* xmatch is optional and may be NULL */
|
/* xmatch is optional and may be NULL */
|
||||||
profile->xmatch.dfa = unpack_dfa(e);
|
error = unpack_pdb(e, &profile->xmatch, false, false, &info);
|
||||||
if (IS_ERR(profile->xmatch.dfa)) {
|
if (error)
|
||||||
error = PTR_ERR(profile->xmatch.dfa);
|
|
||||||
profile->xmatch.dfa = NULL;
|
|
||||||
info = "bad xmatch";
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
|
||||||
/* neither xmatch_len not xmatch_perms are optional if xmatch is set */
|
/* neither xmatch_len not xmatch_perms are optional if xmatch is set */
|
||||||
if (profile->xmatch.dfa) {
|
if (profile->xmatch.dfa) {
|
||||||
if (!unpack_u32(e, &tmp, NULL)) {
|
if (!unpack_u32(e, &tmp, NULL)) {
|
||||||
@ -838,25 +883,16 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
|
|||||||
if (unpack_nameX(e, AA_STRUCT, "policydb")) {
|
if (unpack_nameX(e, AA_STRUCT, "policydb")) {
|
||||||
/* generic policy dfa - optional and may be NULL */
|
/* generic policy dfa - optional and may be NULL */
|
||||||
info = "failed to unpack policydb";
|
info = "failed to unpack policydb";
|
||||||
profile->policy.dfa = unpack_dfa(e);
|
error = unpack_pdb(e, &profile->policy, true, false, &info);
|
||||||
if (IS_ERR(profile->policy.dfa)) {
|
if (error)
|
||||||
error = PTR_ERR(profile->policy.dfa);
|
|
||||||
profile->policy.dfa = NULL;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
} else if (!profile->policy.dfa) {
|
/* Fixup: drop when we get rid of start array */
|
||||||
error = -EPROTO;
|
if (aa_dfa_next(profile->policy.dfa, profile->policy.start[0],
|
||||||
goto fail;
|
AA_CLASS_FILE))
|
||||||
}
|
profile->policy.start[AA_CLASS_FILE] =
|
||||||
if (!unpack_u32(e, &profile->policy.start[0], "start"))
|
aa_dfa_next(profile->policy.dfa,
|
||||||
/* default start state */
|
profile->policy.start[0],
|
||||||
profile->policy.start[0] = DFA_START;
|
AA_CLASS_FILE);
|
||||||
/* setup class index */
|
|
||||||
for (i = AA_CLASS_FILE; i <= AA_CLASS_LAST; i++) {
|
|
||||||
profile->policy.start[i] =
|
|
||||||
aa_dfa_next(profile->policy.dfa,
|
|
||||||
profile->policy.start[0],
|
|
||||||
i);
|
|
||||||
}
|
|
||||||
if (!unpack_nameX(e, AA_STRUCTEND, NULL))
|
if (!unpack_nameX(e, AA_STRUCTEND, NULL))
|
||||||
goto fail;
|
goto fail;
|
||||||
if (aa_compat_map_policy(&profile->policy, e->version)) {
|
if (aa_compat_map_policy(&profile->policy, e->version)) {
|
||||||
@ -867,25 +903,14 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
|
|||||||
profile->policy.dfa = aa_get_dfa(nulldfa);
|
profile->policy.dfa = aa_get_dfa(nulldfa);
|
||||||
|
|
||||||
/* get file rules */
|
/* get file rules */
|
||||||
profile->file.dfa = unpack_dfa(e);
|
error = unpack_pdb(e, &profile->file, false, true, &info);
|
||||||
if (IS_ERR(profile->file.dfa)) {
|
if (error) {
|
||||||
error = PTR_ERR(profile->file.dfa);
|
|
||||||
profile->file.dfa = NULL;
|
|
||||||
info = "failed to unpack profile file rules";
|
|
||||||
goto fail;
|
goto fail;
|
||||||
} else if (profile->file.dfa) {
|
} else if (profile->file.dfa) {
|
||||||
if (!unpack_u32(e, &profile->file.start[AA_CLASS_FILE],
|
|
||||||
"dfa_start"))
|
|
||||||
/* default start state */
|
|
||||||
profile->file.start[AA_CLASS_FILE] = DFA_START;
|
|
||||||
if (aa_compat_map_file(&profile->file)) {
|
if (aa_compat_map_file(&profile->file)) {
|
||||||
info = "failed to remap file permission table";
|
info = "failed to remap file permission table";
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (!unpack_trans_table(e, &profile->file.trans)) {
|
|
||||||
info = "failed to unpack profile transition table";
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
} else if (profile->policy.dfa &&
|
} else if (profile->policy.dfa &&
|
||||||
profile->policy.start[AA_CLASS_FILE]) {
|
profile->policy.start[AA_CLASS_FILE]) {
|
||||||
profile->file.dfa = aa_get_dfa(profile->policy.dfa);
|
profile->file.dfa = aa_get_dfa(profile->policy.dfa);
|
||||||
|
Loading…
Reference in New Issue
Block a user