mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-09-01 06:39:05 +00:00
apparmor: carry mediation check on label
In order to speed up the mediated check, precompute and store the result as a bit per class type. This will not only allow us to speed up the mediation check but is also a step to removing the unconfined special cases as the unconfined check can be replaced with the generic label_mediates() check. Note: label check does not currently work for capabilities and resources which need to have their mediation updated first. Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
34d31f2338
commit
de4754c801
@ -38,6 +38,7 @@
|
|||||||
#define AA_CLASS_X 31
|
#define AA_CLASS_X 31
|
||||||
#define AA_CLASS_DBUS 32
|
#define AA_CLASS_DBUS 32
|
||||||
|
|
||||||
|
/* NOTE: if AA_CLASS_LAST > 63 need to update label->mediates */
|
||||||
#define AA_CLASS_LAST AA_CLASS_DBUS
|
#define AA_CLASS_LAST AA_CLASS_DBUS
|
||||||
|
|
||||||
/* Control parameters settable through module/boot flags */
|
/* Control parameters settable through module/boot flags */
|
||||||
|
@ -129,6 +129,7 @@ struct aa_label {
|
|||||||
long flags;
|
long flags;
|
||||||
u32 secid;
|
u32 secid;
|
||||||
int size;
|
int size;
|
||||||
|
u64 mediates;
|
||||||
struct aa_profile *vec[];
|
struct aa_profile *vec[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -231,20 +232,17 @@ int aa_label_next_confined(struct aa_label *l, int i);
|
|||||||
#define fn_for_each_not_in_set(L1, L2, P, FN) \
|
#define fn_for_each_not_in_set(L1, L2, P, FN) \
|
||||||
fn_for_each2_XXX((L1), (L2), P, FN, _not_in_set)
|
fn_for_each2_XXX((L1), (L2), P, FN, _not_in_set)
|
||||||
|
|
||||||
#define LABEL_MEDIATES(L, C) \
|
static inline bool label_mediates(struct aa_label *L, unsigned char C)
|
||||||
({ \
|
{
|
||||||
struct aa_profile *profile; \
|
return (L)->mediates & (((u64) 1) << (C));
|
||||||
struct label_it i; \
|
}
|
||||||
int ret = 0; \
|
|
||||||
label_for_each(i, (L), profile) { \
|
|
||||||
if (RULE_MEDIATES(&profile->rules, (C))) { \
|
|
||||||
ret = 1; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
ret; \
|
|
||||||
})
|
|
||||||
|
|
||||||
|
static inline bool label_mediates_safe(struct aa_label *L, unsigned char C)
|
||||||
|
{
|
||||||
|
if (C > AA_CLASS_LAST)
|
||||||
|
return false;
|
||||||
|
return label_mediates(L, C);
|
||||||
|
}
|
||||||
|
|
||||||
void aa_labelset_destroy(struct aa_labelset *ls);
|
void aa_labelset_destroy(struct aa_labelset *ls);
|
||||||
void aa_labelset_init(struct aa_labelset *ls);
|
void aa_labelset_init(struct aa_labelset *ls);
|
||||||
|
@ -318,6 +318,19 @@ static inline aa_state_t ANY_RULE_MEDIATES(struct list_head *head,
|
|||||||
return RULE_MEDIATES(rule, class);
|
return RULE_MEDIATES(rule, class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aa_compute_profile_mediates(struct aa_profile *profile);
|
||||||
|
static inline bool profile_mediates(struct aa_profile *profile,
|
||||||
|
unsigned char class)
|
||||||
|
{
|
||||||
|
return label_mediates(&profile->label, class);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool profile_mediates_safe(struct aa_profile *profile,
|
||||||
|
unsigned char class)
|
||||||
|
{
|
||||||
|
return label_mediates_safe(&profile->label, class);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* aa_get_profile - increment refcount on profile @p
|
* aa_get_profile - increment refcount on profile @p
|
||||||
* @p: profile (MAYBE NULL)
|
* @p: profile (MAYBE NULL)
|
||||||
|
@ -198,21 +198,25 @@ static bool vec_is_stale(struct aa_profile **vec, int n)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long accum_vec_flags(struct aa_profile **vec, int n)
|
static void accum_label_info(struct aa_label *new)
|
||||||
{
|
{
|
||||||
long u = FLAG_UNCONFINED;
|
long u = FLAG_UNCONFINED;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
AA_BUG(!vec);
|
AA_BUG(!new->vec);
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
/* size == 1 is a profile and flags must be set as part of creation */
|
||||||
u |= vec[i]->label.flags & (FLAG_DEBUG1 | FLAG_DEBUG2 |
|
if (new->size == 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < new->size; i++) {
|
||||||
|
u |= new->vec[i]->label.flags & (FLAG_DEBUG1 | FLAG_DEBUG2 |
|
||||||
FLAG_STALE);
|
FLAG_STALE);
|
||||||
if (!(u & vec[i]->label.flags & FLAG_UNCONFINED))
|
if (!(u & new->vec[i]->label.flags & FLAG_UNCONFINED))
|
||||||
u &= ~FLAG_UNCONFINED;
|
u &= ~FLAG_UNCONFINED;
|
||||||
|
new->mediates |= new->vec[i]->label.mediates;
|
||||||
}
|
}
|
||||||
|
new->flags |= u;
|
||||||
return u;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sort_cmp(const void *a, const void *b)
|
static int sort_cmp(const void *a, const void *b)
|
||||||
@ -645,7 +649,7 @@ static bool __label_replace(struct aa_label *old, struct aa_label *new)
|
|||||||
rb_replace_node(&old->node, &new->node, &ls->root);
|
rb_replace_node(&old->node, &new->node, &ls->root);
|
||||||
old->flags &= ~FLAG_IN_TREE;
|
old->flags &= ~FLAG_IN_TREE;
|
||||||
new->flags |= FLAG_IN_TREE;
|
new->flags |= FLAG_IN_TREE;
|
||||||
new->flags |= accum_vec_flags(new->vec, new->size);
|
accum_label_info(new);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,7 +710,7 @@ static struct aa_label *__label_insert(struct aa_labelset *ls,
|
|||||||
rb_link_node(&label->node, parent, new);
|
rb_link_node(&label->node, parent, new);
|
||||||
rb_insert_color(&label->node, &ls->root);
|
rb_insert_color(&label->node, &ls->root);
|
||||||
label->flags |= FLAG_IN_TREE;
|
label->flags |= FLAG_IN_TREE;
|
||||||
label->flags |= accum_vec_flags(label->vec, label->size);
|
accum_label_info(label);
|
||||||
|
|
||||||
return aa_get_label(label);
|
return aa_get_label(label);
|
||||||
}
|
}
|
||||||
|
@ -373,6 +373,30 @@ struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* set of rules that are mediated by unconfined */
|
||||||
|
static int unconfined_mediates[] = { AA_CLASS_NS, AA_CLASS_IO_URING, 0 };
|
||||||
|
|
||||||
|
/* must be called after profile rulesets and start information is setup */
|
||||||
|
void aa_compute_profile_mediates(struct aa_profile *profile)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if (profile_unconfined(profile)) {
|
||||||
|
int *pos;
|
||||||
|
|
||||||
|
for (pos = unconfined_mediates; *pos; pos++) {
|
||||||
|
if (ANY_RULE_MEDIATES(&profile->rules, AA_CLASS_NS) !=
|
||||||
|
DFA_NOMATCH)
|
||||||
|
profile->label.mediates |= ((u64) 1) << AA_CLASS_NS;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (c = 0; c <= AA_CLASS_LAST; c++) {
|
||||||
|
if (ANY_RULE_MEDIATES(&profile->rules, c) != DFA_NOMATCH)
|
||||||
|
profile->label.mediates |= ((u64) 1) << c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: profile accounting - setup in remove */
|
/* TODO: profile accounting - setup in remove */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -624,10 +648,12 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name,
|
|||||||
rules = list_first_entry(&profile->rules, typeof(*rules), list);
|
rules = list_first_entry(&profile->rules, typeof(*rules), list);
|
||||||
rules->file = aa_get_pdb(nullpdb);
|
rules->file = aa_get_pdb(nullpdb);
|
||||||
rules->policy = aa_get_pdb(nullpdb);
|
rules->policy = aa_get_pdb(nullpdb);
|
||||||
|
aa_compute_profile_mediates(profile);
|
||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
profile->path_flags = parent->path_flags;
|
profile->path_flags = parent->path_flags;
|
||||||
|
/* override/inherit what is mediated from parent */
|
||||||
|
profile->label.mediates = parent->label.mediates;
|
||||||
/* released on free_profile */
|
/* released on free_profile */
|
||||||
rcu_assign_pointer(profile->parent, aa_get_profile(parent));
|
rcu_assign_pointer(profile->parent, aa_get_profile(parent));
|
||||||
profile->ns = aa_get_ns(parent->ns);
|
profile->ns = aa_get_ns(parent->ns);
|
||||||
|
@ -1101,6 +1101,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aa_compute_profile_mediates(profile);
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
Loading…
Reference in New Issue
Block a user