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:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user