apparmor: refcount the pdb

With the move to permission tables the dfa is no longer a stand
alone entity when used, needing a minimum of a permission table.
However it still could be shared among different pdbs each using
a different permission table.

Instead of duping the permission table when sharing a pdb, add a
refcount to the pdb so it can be easily shared.

Reviewed-by: Georgia Garcia <georgia.garcia@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
John Johansen
2023-04-28 05:32:52 -07:00
parent 75c77e9e07
commit 98b824ff89
15 changed files with 261 additions and 211 deletions
+2
View File
@@ -16,6 +16,8 @@
#include "match.h"
extern struct aa_dfa *stacksplitdfa;
/*
* DEBUG remains global (no per profile flag) since it is mostly used in sysctl
* which is not related to profile accesses.
-6
View File
@@ -102,9 +102,6 @@ struct aa_dfa {
struct table_header *tables[YYTD_ID_TSIZE];
};
extern struct aa_dfa *nulldfa;
extern struct aa_dfa *stacksplitdfa;
#define byte_to_byte(X) (X)
#define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX) \
@@ -122,9 +119,6 @@ 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);
#define aa_state_t unsigned int
struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags);
+38 -13
View File
@@ -74,12 +74,14 @@ enum profile_mode {
/* struct aa_policydb - match engine for a policy
* count: refcount for the pdb
* dfa: dfa pattern match
* perms: table of permissions
* strs: table of strings, index by x
* start: set of start states for the different classes of data
*/
struct aa_policydb {
struct kref count;
struct aa_dfa *dfa;
struct {
struct aa_perms *perms;
@@ -89,13 +91,36 @@ struct aa_policydb {
aa_state_t start[AA_CLASS_LAST + 1];
};
static inline void aa_destroy_policydb(struct aa_policydb *policy)
{
aa_put_dfa(policy->dfa);
if (policy->perms)
kvfree(policy->perms);
aa_free_str_table(&policy->trans);
extern struct aa_policydb *nullpdb;
struct aa_policydb *aa_alloc_pdb(gfp_t gfp);
void aa_pdb_free_kref(struct kref *kref);
/**
* aa_get_pdb - increment refcount on @pdb
* @pdb: policydb (MAYBE NULL)
*
* Returns: pointer to @pdb if @pdb is NULL will return NULL
* Requires: @pdb must be held with valid refcount when called
*/
static inline struct aa_policydb *aa_get_pdb(struct aa_policydb *pdb)
{
if (pdb)
kref_get(&(pdb->count));
return pdb;
}
/**
* aa_put_pdb - put a pdb refcount
* @pdb: pdb to put refcount (MAYBE NULL)
*
* Requires: if @pdb != NULL that a valid refcount be held
*/
static inline void aa_put_pdb(struct aa_policydb *pdb)
{
if (pdb)
kref_put(&pdb->count, aa_pdb_free_kref);
}
static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy,
@@ -139,8 +164,8 @@ struct aa_ruleset {
int size;
/* TODO: merge policy and file */
struct aa_policydb policy;
struct aa_policydb file;
struct aa_policydb *policy;
struct aa_policydb *file;
struct aa_caps caps;
struct aa_rlimit rlimits;
@@ -159,7 +184,7 @@ struct aa_ruleset {
*/
struct aa_attachment {
const char *xmatch_str;
struct aa_policydb xmatch;
struct aa_policydb *xmatch;
unsigned int xmatch_len;
int xattr_count;
char **xattrs;
@@ -267,10 +292,10 @@ static inline aa_state_t RULE_MEDIATES(struct aa_ruleset *rules,
unsigned char class)
{
if (class <= AA_CLASS_LAST)
return rules->policy.start[class];
return rules->policy->start[class];
else
return aa_dfa_match_len(rules->policy.dfa,
rules->policy.start[0], &class, 1);
return aa_dfa_match_len(rules->policy->dfa,
rules->policy->start[0], &class, 1);
}
static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF)
@@ -280,7 +305,7 @@ static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF)
if (!state)
return DFA_NOMATCH;
return aa_dfa_match_len(rules->policy.dfa, state, (char *) &be_af, 2);
return aa_dfa_match_len(rules->policy->dfa, state, (char *) &be_af, 2);
}
static inline aa_state_t ANY_RULE_MEDIATES(struct list_head *head,