Commit 6f442d42 authored by John Johansen's avatar John Johansen

apparmor: fix profile verification and enable it

The transition table size was not being set by compat mappings
resulting in the profile verification code not being run. Unfortunately
the checks were also buggy not being correctly updated from the old
accept perms, to the new layout.

Also indicate to userspace that the kernel has the permstable verification
fixes.

BugLink: http://bugs.launchpad.net/bugs/2017903
Fixes: 670f3177 ("apparmor: verify permission table indexes")
Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
Reviewed-by: default avatarJon Tourville <jontourville@me.com>
parent 0bac2002
...@@ -146,7 +146,8 @@ static struct aa_perms compute_fperms_other(struct aa_dfa *dfa, ...@@ -146,7 +146,8 @@ static struct aa_perms compute_fperms_other(struct aa_dfa *dfa,
* *
* Returns: remapped perm table * Returns: remapped perm table
*/ */
static struct aa_perms *compute_fperms(struct aa_dfa *dfa) static struct aa_perms *compute_fperms(struct aa_dfa *dfa,
u32 *size)
{ {
aa_state_t state; aa_state_t state;
unsigned int state_count; unsigned int state_count;
...@@ -159,6 +160,7 @@ static struct aa_perms *compute_fperms(struct aa_dfa *dfa) ...@@ -159,6 +160,7 @@ static struct aa_perms *compute_fperms(struct aa_dfa *dfa)
table = kvcalloc(state_count * 2, sizeof(struct aa_perms), GFP_KERNEL); table = kvcalloc(state_count * 2, sizeof(struct aa_perms), GFP_KERNEL);
if (!table) if (!table)
return NULL; return NULL;
*size = state_count * 2;
/* zero init so skip the trap state (state == 0) */ /* zero init so skip the trap state (state == 0) */
for (state = 1; state < state_count; state++) { for (state = 1; state < state_count; state++) {
...@@ -169,7 +171,8 @@ static struct aa_perms *compute_fperms(struct aa_dfa *dfa) ...@@ -169,7 +171,8 @@ static struct aa_perms *compute_fperms(struct aa_dfa *dfa)
return table; return table;
} }
static struct aa_perms *compute_xmatch_perms(struct aa_dfa *xmatch) static struct aa_perms *compute_xmatch_perms(struct aa_dfa *xmatch,
u32 *size)
{ {
struct aa_perms *perms; struct aa_perms *perms;
int state; int state;
...@@ -182,6 +185,7 @@ static struct aa_perms *compute_xmatch_perms(struct aa_dfa *xmatch) ...@@ -182,6 +185,7 @@ static struct aa_perms *compute_xmatch_perms(struct aa_dfa *xmatch)
perms = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL); perms = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL);
if (!perms) if (!perms)
return NULL; return NULL;
*size = state_count;
/* zero init so skip the trap state (state == 0) */ /* zero init so skip the trap state (state == 0) */
for (state = 1; state < state_count; state++) for (state = 1; state < state_count; state++)
...@@ -242,7 +246,8 @@ static struct aa_perms compute_perms_entry(struct aa_dfa *dfa, ...@@ -242,7 +246,8 @@ static struct aa_perms compute_perms_entry(struct aa_dfa *dfa,
return perms; return perms;
} }
static struct aa_perms *compute_perms(struct aa_dfa *dfa, u32 version) static struct aa_perms *compute_perms(struct aa_dfa *dfa, u32 version,
u32 *size)
{ {
unsigned int state; unsigned int state;
unsigned int state_count; unsigned int state_count;
...@@ -255,6 +260,7 @@ static struct aa_perms *compute_perms(struct aa_dfa *dfa, u32 version) ...@@ -255,6 +260,7 @@ static struct aa_perms *compute_perms(struct aa_dfa *dfa, u32 version)
table = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL); table = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL);
if (!table) if (!table)
return NULL; return NULL;
*size = state_count;
/* zero init so skip the trap state (state == 0) */ /* zero init so skip the trap state (state == 0) */
for (state = 1; state < state_count; state++) for (state = 1; state < state_count; state++)
...@@ -289,7 +295,7 @@ static void remap_dfa_accept(struct aa_dfa *dfa, unsigned int factor) ...@@ -289,7 +295,7 @@ static void remap_dfa_accept(struct aa_dfa *dfa, unsigned int factor)
/* TODO: merge different dfa mappings into single map_policy fn */ /* TODO: merge different dfa mappings into single map_policy fn */
int aa_compat_map_xmatch(struct aa_policydb *policy) int aa_compat_map_xmatch(struct aa_policydb *policy)
{ {
policy->perms = compute_xmatch_perms(policy->dfa); policy->perms = compute_xmatch_perms(policy->dfa, &policy->size);
if (!policy->perms) if (!policy->perms)
return -ENOMEM; return -ENOMEM;
...@@ -300,7 +306,7 @@ int aa_compat_map_xmatch(struct aa_policydb *policy) ...@@ -300,7 +306,7 @@ int aa_compat_map_xmatch(struct aa_policydb *policy)
int aa_compat_map_policy(struct aa_policydb *policy, u32 version) int aa_compat_map_policy(struct aa_policydb *policy, u32 version)
{ {
policy->perms = compute_perms(policy->dfa, version); policy->perms = compute_perms(policy->dfa, version, &policy->size);
if (!policy->perms) if (!policy->perms)
return -ENOMEM; return -ENOMEM;
...@@ -311,7 +317,7 @@ int aa_compat_map_policy(struct aa_policydb *policy, u32 version) ...@@ -311,7 +317,7 @@ int aa_compat_map_policy(struct aa_policydb *policy, u32 version)
int aa_compat_map_file(struct aa_policydb *policy) int aa_compat_map_file(struct aa_policydb *policy)
{ {
policy->perms = compute_fperms(policy->dfa); policy->perms = compute_fperms(policy->dfa, &policy->size);
if (!policy->perms) if (!policy->perms)
return -ENOMEM; return -ENOMEM;
......
...@@ -1135,22 +1135,16 @@ static int verify_header(struct aa_ext *e, int required, const char **ns) ...@@ -1135,22 +1135,16 @@ static int verify_header(struct aa_ext *e, int required, const char **ns)
return 0; return 0;
} }
static bool verify_xindex(int xindex, int table_size) /**
{ * verify_dfa_accept_xindex - verify accept indexes are in range of perms table
int index, xtype; * @dfa: the dfa to check accept indexes are in range
xtype = xindex & AA_X_TYPE_MASK; * table_size: the permission table size the indexes should be within
index = xindex & AA_X_INDEX_MASK; */
if (xtype == AA_X_TABLE && index >= table_size) static bool verify_dfa_accept_index(struct aa_dfa *dfa, int table_size)
return false;
return true;
}
/* verify dfa xindexes are in range of transition tables */
static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size)
{ {
int i; int i;
for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) { for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
if (!verify_xindex(ACCEPT_TABLE(dfa)[i], table_size)) if (ACCEPT_TABLE(dfa)[i] >= table_size)
return false; return false;
} }
return true; return true;
...@@ -1187,11 +1181,13 @@ static bool verify_perms(struct aa_policydb *pdb) ...@@ -1187,11 +1181,13 @@ static bool verify_perms(struct aa_policydb *pdb)
if (!verify_perm(&pdb->perms[i])) if (!verify_perm(&pdb->perms[i]))
return false; return false;
/* verify indexes into str table */ /* verify indexes into str table */
if (pdb->perms[i].xindex >= pdb->trans.size) if ((pdb->perms[i].xindex & AA_X_TYPE_MASK) == AA_X_TABLE &&
(pdb->perms[i].xindex & AA_X_INDEX_MASK) >= pdb->trans.size)
return false; return false;
if (pdb->perms[i].tag >= pdb->trans.size) if (pdb->perms[i].tag && pdb->perms[i].tag >= pdb->trans.size)
return false; return false;
if (pdb->perms[i].label >= pdb->trans.size) if (pdb->perms[i].label &&
pdb->perms[i].label >= pdb->trans.size)
return false; return false;
} }
...@@ -1213,10 +1209,10 @@ static int verify_profile(struct aa_profile *profile) ...@@ -1213,10 +1209,10 @@ static int verify_profile(struct aa_profile *profile)
if (!rules) if (!rules)
return 0; return 0;
if ((rules->file.dfa && !verify_dfa_xindex(rules->file.dfa, if ((rules->file.dfa && !verify_dfa_accept_index(rules->file.dfa,
rules->file.trans.size)) || rules->file.size)) ||
(rules->policy.dfa && (rules->policy.dfa &&
!verify_dfa_xindex(rules->policy.dfa, rules->policy.trans.size))) { !verify_dfa_accept_index(rules->policy.dfa, rules->policy.size))) {
audit_iface(profile, NULL, NULL, audit_iface(profile, NULL, NULL,
"Unpack: Invalid named transition", NULL, -EPROTO); "Unpack: Invalid named transition", NULL, -EPROTO);
return -EPROTO; return -EPROTO;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment