apparmor: add a default null dfa

Instead of testing whether a given dfa exists in every code path, have
a default null dfa that is used when loaded policy doesn't provide a
dfa.

This will let us get rid of special casing and avoid dereference bugs
when special casing is missed.

Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
John Johansen 2017-01-16 00:42:42 -08:00
parent 6604d4c1c1
commit 11c236b89d
6 changed files with 46 additions and 2 deletions

View file

@ -100,6 +100,8 @@ struct aa_dfa {
struct table_header *tables[YYTD_ID_TSIZE];
};
extern struct aa_dfa *nulldfa;
#define byte_to_byte(X) (X)
#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
@ -117,6 +119,9 @@ static inline size_t table_size(size_t len, size_t el_size)
return ALIGN(sizeof(struct table_header) + len * el_size, 8);
}
int aa_setup_dfa_engine(void);
void aa_teardown_dfa_engine(void);
struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags);
unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
const char *str, int len);

View file

@ -878,6 +878,12 @@ static int __init apparmor_init(void)
return 0;
}
error = aa_setup_dfa_engine();
if (error) {
AA_ERROR("Unable to setup dfa engine\n");
goto alloc_out;
}
error = aa_alloc_root_ns();
if (error) {
AA_ERROR("Unable to allocate default profile namespace\n");
@ -905,6 +911,7 @@ static int __init apparmor_init(void)
alloc_out:
aa_destroy_aafs();
aa_teardown_dfa_engine();
apparmor_enabled = 0;
return error;

View file

@ -25,6 +25,33 @@
#define base_idx(X) ((X) & 0xffffff)
static char nulldfa_src[] = {
#include "nulldfa.in"
};
struct aa_dfa *nulldfa;
int aa_setup_dfa_engine(void)
{
int error;
nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src),
TO_ACCEPT1_FLAG(YYTD_DATA32) |
TO_ACCEPT2_FLAG(YYTD_DATA32));
if (!IS_ERR(nulldfa))
return 0;
error = PTR_ERR(nulldfa);
nulldfa = NULL;
return error;
}
void aa_teardown_dfa_engine(void)
{
aa_put_dfa(nulldfa);
nulldfa = NULL;
}
/**
* unpack_table - unpack a dfa table (one of accept, default, base, next check)
* @blob: data to unpack (NOT NULL)

File diff suppressed because one or more lines are too long

View file

@ -348,6 +348,8 @@ name:
/* released on free_profile */
rcu_assign_pointer(profile->parent, aa_get_profile(parent));
profile->ns = aa_get_ns(parent->ns);
profile->file.dfa = aa_get_dfa(nulldfa);
profile->policy.dfa = aa_get_dfa(nulldfa);
mutex_lock(&profile->ns->lock);
__list_add_profile(&parent->base.profiles, profile);

View file

@ -603,7 +603,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
}
if (!unpack_nameX(e, AA_STRUCTEND, NULL))
goto fail;
}
} else
profile->policy.dfa = aa_get_dfa(nulldfa);
/* get file rules */
profile->file.dfa = unpack_dfa(e);
@ -619,7 +620,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
profile->policy.start[AA_CLASS_FILE]) {
profile->file.dfa = aa_get_dfa(profile->policy.dfa);
profile->file.start = profile->policy.start[AA_CLASS_FILE];
}
} else
profile->file.dfa = aa_get_dfa(nulldfa);
if (!unpack_trans_table(e, profile))
goto fail;