summaryrefslogtreecommitdiff
path: root/security/apparmor/policy_unpack.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/policy_unpack.c')
-rw-r--r--security/apparmor/policy_unpack.c152
1 files changed, 74 insertions, 78 deletions
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 913ec8d0eb63..47ec097d6741 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -34,17 +34,18 @@
static void audit_cb(struct audit_buffer *ab, void *va)
{
struct common_audit_data *sa = va;
+ struct apparmor_audit_data *ad = aad(sa);
- if (aad(sa)->iface.ns) {
+ if (ad->iface.ns) {
audit_log_format(ab, " ns=");
- audit_log_untrustedstring(ab, aad(sa)->iface.ns);
+ audit_log_untrustedstring(ab, ad->iface.ns);
}
- if (aad(sa)->name) {
+ if (ad->name) {
audit_log_format(ab, " name=");
- audit_log_untrustedstring(ab, aad(sa)->name);
+ audit_log_untrustedstring(ab, ad->name);
}
- if (aad(sa)->iface.pos)
- audit_log_format(ab, " offset=%ld", aad(sa)->iface.pos);
+ if (ad->iface.pos)
+ audit_log_format(ab, " offset=%ld", ad->iface.pos);
}
/**
@@ -63,18 +64,18 @@ static int audit_iface(struct aa_profile *new, const char *ns_name,
int error)
{
struct aa_profile *profile = labels_profile(aa_current_raw_label());
- DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL);
+ DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL);
if (e)
- aad(&sa)->iface.pos = e->pos - e->start;
- aad(&sa)->iface.ns = ns_name;
+ ad.iface.pos = e->pos - e->start;
+ ad.iface.ns = ns_name;
if (new)
- aad(&sa)->name = new->base.hname;
+ ad.name = new->base.hname;
else
- aad(&sa)->name = name;
- aad(&sa)->info = info;
- aad(&sa)->error = error;
+ ad.name = name;
+ ad.info = info;
+ ad.error = error;
- return aa_audit(AUDIT_APPARMOR_STATUS, profile, &sa, audit_cb);
+ return aa_audit(AUDIT_APPARMOR_STATUS, profile, &ad, audit_cb);
}
void __aa_loaddata_update(struct aa_loaddata *data, long revision)
@@ -705,24 +706,29 @@ fail_reset:
return -EPROTO;
}
-static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy,
+static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy,
bool required_dfa, bool required_trans,
const char **info)
{
+ struct aa_policydb *pdb;
void *pos = e->pos;
int i, flags, error = -EPROTO;
ssize_t size;
- size = unpack_perms_table(e, &policy->perms);
+ pdb = aa_alloc_pdb(GFP_KERNEL);
+ if (!pdb)
+ return -ENOMEM;
+
+ size = unpack_perms_table(e, &pdb->perms);
if (size < 0) {
error = size;
- policy->perms = NULL;
+ pdb->perms = NULL;
*info = "failed to unpack - perms";
goto fail;
}
- policy->size = size;
+ pdb->size = size;
- if (policy->perms) {
+ if (pdb->perms) {
/* perms table present accept is index */
flags = TO_ACCEPT1_FLAG(YYTD_DATA32);
} else {
@@ -731,13 +737,13 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy,
TO_ACCEPT2_FLAG(YYTD_DATA32);
}
- policy->dfa = unpack_dfa(e, flags);
- if (IS_ERR(policy->dfa)) {
- error = PTR_ERR(policy->dfa);
- policy->dfa = NULL;
+ pdb->dfa = unpack_dfa(e, flags);
+ if (IS_ERR(pdb->dfa)) {
+ error = PTR_ERR(pdb->dfa);
+ pdb->dfa = NULL;
*info = "failed to unpack - dfa";
goto fail;
- } else if (!policy->dfa) {
+ } else if (!pdb->dfa) {
if (required_dfa) {
*info = "missing required dfa";
goto fail;
@@ -751,18 +757,18 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy,
* sadly start was given different names for file and policydb
* but since it is optional we can try both
*/
- if (!aa_unpack_u32(e, &policy->start[0], "start"))
+ if (!aa_unpack_u32(e, &pdb->start[0], "start"))
/* default start state */
- policy->start[0] = DFA_START;
- if (!aa_unpack_u32(e, &policy->start[AA_CLASS_FILE], "dfa_start")) {
+ pdb->start[0] = DFA_START;
+ if (!aa_unpack_u32(e, &pdb->start[AA_CLASS_FILE], "dfa_start")) {
/* default start state for xmatch and file dfa */
- policy->start[AA_CLASS_FILE] = DFA_START;
+ pdb->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],
+ pdb->start[i] = aa_dfa_next(pdb->dfa, pdb->start[0],
i);
}
- if (!unpack_trans_table(e, &policy->trans) && required_trans) {
+ if (!unpack_trans_table(e, &pdb->trans) && required_trans) {
*info = "failed to unpack profile transition table";
goto fail;
}
@@ -770,9 +776,11 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy,
/* TODO: move compat mapping here, requires dfa merging first */
/* TODO: move verify here, it has to be done after compat mappings */
out:
+ *policy = pdb;
return 0;
fail:
+ aa_put_pdb(pdb);
e->pos = pos;
return error;
}
@@ -807,7 +815,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
const char *info = "failed to unpack profile";
size_t ns_len;
struct rhashtable_params params = { 0 };
- char *key = NULL;
+ char *key = NULL, *disconnected = NULL;
struct aa_data *data;
int error = -EPROTO;
kernel_cap_t tmpcap;
@@ -856,15 +864,15 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
}
/* neither xmatch_len not xmatch_perms are optional if xmatch is set */
- if (profile->attach.xmatch.dfa) {
+ if (profile->attach.xmatch->dfa) {
if (!aa_unpack_u32(e, &tmp, NULL)) {
info = "missing xmatch len";
goto fail;
}
profile->attach.xmatch_len = tmp;
- profile->attach.xmatch.start[AA_CLASS_XMATCH] = DFA_START;
- if (!profile->attach.xmatch.perms) {
- error = aa_compat_map_xmatch(&profile->attach.xmatch);
+ profile->attach.xmatch->start[AA_CLASS_XMATCH] = DFA_START;
+ if (!profile->attach.xmatch->perms) {
+ error = aa_compat_map_xmatch(profile->attach.xmatch);
if (error) {
info = "failed to convert xmatch permission table";
goto fail;
@@ -873,7 +881,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
}
/* disconnected attachment string is optional */
- (void) aa_unpack_str(e, &profile->disconnected, "disconnected");
+ (void) aa_unpack_strdup(e, &disconnected, "disconnected");
+ profile->disconnected = disconnected;
/* per profile debug flags (complain, audit) */
if (!aa_unpack_nameX(e, AA_STRUCT, "flags")) {
@@ -980,16 +989,16 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
if (error)
goto fail;
/* Fixup: drop when we get rid of start array */
- if (aa_dfa_next(rules->policy.dfa, rules->policy.start[0],
+ if (aa_dfa_next(rules->policy->dfa, rules->policy->start[0],
AA_CLASS_FILE))
- rules->policy.start[AA_CLASS_FILE] =
- aa_dfa_next(rules->policy.dfa,
- rules->policy.start[0],
+ rules->policy->start[AA_CLASS_FILE] =
+ aa_dfa_next(rules->policy->dfa,
+ rules->policy->start[0],
AA_CLASS_FILE);
if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL))
goto fail;
- if (!rules->policy.perms) {
- error = aa_compat_map_policy(&rules->policy,
+ if (!rules->policy->perms) {
+ error = aa_compat_map_policy(rules->policy,
e->version);
if (error) {
info = "failed to remap policydb permission table";
@@ -997,44 +1006,25 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
}
}
} else {
- rules->policy.dfa = aa_get_dfa(nulldfa);
- rules->policy.perms = kcalloc(2, sizeof(struct aa_perms),
- GFP_KERNEL);
- if (!rules->policy.perms)
- goto fail;
- rules->policy.size = 2;
+ rules->policy = aa_get_pdb(nullpdb);
}
/* get file rules */
error = unpack_pdb(e, &rules->file, false, true, &info);
if (error) {
goto fail;
- } else if (rules->file.dfa) {
- if (!rules->file.perms) {
- error = aa_compat_map_file(&rules->file);
+ } else if (rules->file->dfa) {
+ if (!rules->file->perms) {
+ error = aa_compat_map_file(rules->file);
if (error) {
info = "failed to remap file permission table";
goto fail;
}
}
- } else if (rules->policy.dfa &&
- rules->policy.start[AA_CLASS_FILE]) {
- rules->file.dfa = aa_get_dfa(rules->policy.dfa);
- rules->file.start[AA_CLASS_FILE] = rules->policy.start[AA_CLASS_FILE];
- rules->file.perms = kcalloc(rules->policy.size,
- sizeof(struct aa_perms),
- GFP_KERNEL);
- if (!rules->file.perms)
- goto fail;
- memcpy(rules->file.perms, rules->policy.perms,
- rules->policy.size * sizeof(struct aa_perms));
- rules->file.size = rules->policy.size;
+ } else if (rules->policy->dfa &&
+ rules->policy->start[AA_CLASS_FILE]) {
+ rules->file = aa_get_pdb(rules->policy);
} else {
- rules->file.dfa = aa_get_dfa(nulldfa);
- rules->file.perms = kcalloc(2, sizeof(struct aa_perms),
- GFP_KERNEL);
- if (!rules->file.perms)
- goto fail;
- rules->file.size = 2;
+ rules->file = aa_get_pdb(nullpdb);
}
error = -EPROTO;
if (aa_unpack_nameX(e, AA_STRUCT, "data")) {
@@ -1170,7 +1160,7 @@ static int verify_header(struct aa_ext *e, int required, const char **ns)
/**
* verify_dfa_accept_index - verify accept indexes are in range of perms table
* @dfa: the dfa to check accept indexes are in range
- * table_size: the permission table size the indexes should be within
+ * @table_size: the permission table size the indexes should be within
*/
static bool verify_dfa_accept_index(struct aa_dfa *dfa, int table_size)
{
@@ -1241,26 +1231,32 @@ static int verify_profile(struct aa_profile *profile)
if (!rules)
return 0;
- if ((rules->file.dfa && !verify_dfa_accept_index(rules->file.dfa,
- rules->file.size)) ||
- (rules->policy.dfa &&
- !verify_dfa_accept_index(rules->policy.dfa, rules->policy.size))) {
+ if (rules->file->dfa && !verify_dfa_accept_index(rules->file->dfa,
+ rules->file->size)) {
+ audit_iface(profile, NULL, NULL,
+ "Unpack: file Invalid named transition", NULL,
+ -EPROTO);
+ return -EPROTO;
+ }
+ if (rules->policy->dfa &&
+ !verify_dfa_accept_index(rules->policy->dfa, rules->policy->size)) {
audit_iface(profile, NULL, NULL,
- "Unpack: Invalid named transition", NULL, -EPROTO);
+ "Unpack: policy Invalid named transition", NULL,
+ -EPROTO);
return -EPROTO;
}
- if (!verify_perms(&rules->file)) {
+ if (!verify_perms(rules->file)) {
audit_iface(profile, NULL, NULL,
"Unpack: Invalid perm index", NULL, -EPROTO);
return -EPROTO;
}
- if (!verify_perms(&rules->policy)) {
+ if (!verify_perms(rules->policy)) {
audit_iface(profile, NULL, NULL,
"Unpack: Invalid perm index", NULL, -EPROTO);
return -EPROTO;
}
- if (!verify_perms(&profile->attach.xmatch)) {
+ if (!verify_perms(profile->attach.xmatch)) {
audit_iface(profile, NULL, NULL,
"Unpack: Invalid perm index", NULL, -EPROTO);
return -EPROTO;