mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-28 18:10:32 +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_DBUS 32
|
||||
|
||||
/* NOTE: if AA_CLASS_LAST > 63 need to update label->mediates */
|
||||
#define AA_CLASS_LAST AA_CLASS_DBUS
|
||||
|
||||
/* Control parameters settable through module/boot flags */
|
||||
|
@ -129,6 +129,7 @@ struct aa_label {
|
||||
long flags;
|
||||
u32 secid;
|
||||
int size;
|
||||
u64 mediates;
|
||||
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) \
|
||||
fn_for_each2_XXX((L1), (L2), P, FN, _not_in_set)
|
||||
|
||||
#define LABEL_MEDIATES(L, C) \
|
||||
({ \
|
||||
struct aa_profile *profile; \
|
||||
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(struct aa_label *L, unsigned char C)
|
||||
{
|
||||
return (L)->mediates & (((u64) 1) << (C));
|
||||
}
|
||||
|
||||
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_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);
|
||||
}
|
||||
|
||||
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
|
||||
* @p: profile (MAYBE NULL)
|
||||
|
@ -198,21 +198,25 @@ static bool vec_is_stale(struct aa_profile **vec, int n)
|
||||
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;
|
||||
int i;
|
||||
|
||||
AA_BUG(!vec);
|
||||
AA_BUG(!new->vec);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
u |= vec[i]->label.flags & (FLAG_DEBUG1 | FLAG_DEBUG2 |
|
||||
FLAG_STALE);
|
||||
if (!(u & vec[i]->label.flags & FLAG_UNCONFINED))
|
||||
/* size == 1 is a profile and flags must be set as part of creation */
|
||||
if (new->size == 1)
|
||||
return;
|
||||
|
||||
for (i = 0; i < new->size; i++) {
|
||||
u |= new->vec[i]->label.flags & (FLAG_DEBUG1 | FLAG_DEBUG2 |
|
||||
FLAG_STALE);
|
||||
if (!(u & new->vec[i]->label.flags & FLAG_UNCONFINED))
|
||||
u &= ~FLAG_UNCONFINED;
|
||||
new->mediates |= new->vec[i]->label.mediates;
|
||||
}
|
||||
|
||||
return u;
|
||||
new->flags |= u;
|
||||
}
|
||||
|
||||
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);
|
||||
old->flags &= ~FLAG_IN_TREE;
|
||||
new->flags |= FLAG_IN_TREE;
|
||||
new->flags |= accum_vec_flags(new->vec, new->size);
|
||||
accum_label_info(new);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -706,7 +710,7 @@ static struct aa_label *__label_insert(struct aa_labelset *ls,
|
||||
rb_link_node(&label->node, parent, new);
|
||||
rb_insert_color(&label->node, &ls->root);
|
||||
label->flags |= FLAG_IN_TREE;
|
||||
label->flags |= accum_vec_flags(label->vec, label->size);
|
||||
accum_label_info(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;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
||||
/**
|
||||
@ -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->file = aa_get_pdb(nullpdb);
|
||||
rules->policy = aa_get_pdb(nullpdb);
|
||||
aa_compute_profile_mediates(profile);
|
||||
|
||||
if (parent) {
|
||||
profile->path_flags = parent->path_flags;
|
||||
|
||||
/* override/inherit what is mediated from parent */
|
||||
profile->label.mediates = parent->label.mediates;
|
||||
/* released on free_profile */
|
||||
rcu_assign_pointer(profile->parent, aa_get_profile(parent));
|
||||
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;
|
||||
}
|
||||
|
||||
aa_compute_profile_mediates(profile);
|
||||
|
||||
return profile;
|
||||
|
||||
fail:
|
||||
|
Loading…
Reference in New Issue
Block a user