UBUNTU: SAUCE: apparmor4.0.0 [55/90]: prompt - add refcount to audit_node in prep or reuse and delete

BugLink: http://bugs.launchpad.net/bugs/2028253

The audit_node needs to be shared for asynchronous notifications to
multiple listeners. So add a refcount to enable sharing.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from https://gitlab.com/jjohansen/apparmor-kernel)
Signed-off-by: Andrea Righi <andrea.righi@canonical.com>
(cherry picked from commit bbebba69241db7470d5b389ae0bbb3524b02c04c
https://git.launchpad.net/~apparmor-dev/ubuntu-kernel-next)
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
This commit is contained in:
John Johansen
2023-04-30 01:27:57 -07:00
committed by Paolo Pisati
parent c5f3b6ece9
commit 443431be30
4 changed files with 58 additions and 25 deletions
+21 -5
View File
@@ -207,6 +207,7 @@ struct aa_audit_rule {
};
/****************************** audit rules *******************************/
void aa_audit_rule_free(void *vrule, int lsmid)
{
struct aa_audit_rule *rule = vrule;
@@ -350,7 +351,7 @@ long aa_audit_data_cmp(struct apparmor_audit_data *lhs,
return 0;
}
void aa_audit_node_free(struct aa_audit_node *node)
static void audit_node_free(struct aa_audit_node *node)
{
if (!node)
return;
@@ -373,6 +374,13 @@ void aa_audit_node_free(struct aa_audit_node *node)
kmem_cache_free(aa_audit_slab, node);
}
void aa_audit_node_free_kref(struct kref *kref)
{
struct aa_audit_node *node = container_of(kref, struct aa_audit_node,
count);
audit_node_free(node);
}
struct aa_audit_node *aa_dup_audit_data(struct apparmor_audit_data *orig,
gfp_t gfp)
{
@@ -381,6 +389,7 @@ struct aa_audit_node *aa_dup_audit_data(struct apparmor_audit_data *orig,
copy = kmem_cache_zalloc(aa_audit_slab, gfp);
if (!copy)
return NULL;
kref_init(&copy->count);
copy->knotif.ad = &copy->data;
INIT_LIST_HEAD(&copy->list);
@@ -457,7 +466,7 @@ struct aa_audit_node *aa_dup_audit_data(struct apparmor_audit_data *orig,
return copy;
fail:
aa_audit_node_free(copy);
audit_node_free(copy);
return NULL;
}
@@ -473,6 +482,7 @@ __out_skip: \
__node; \
})
// increments refcount on node
struct aa_audit_node *aa_audit_cache_find(struct aa_audit_cache *cache,
struct apparmor_audit_data *ad)
{
@@ -480,6 +490,7 @@ struct aa_audit_node *aa_audit_cache_find(struct aa_audit_cache *cache,
rcu_read_lock();
node = __audit_cache_find(cache, ad);
aa_get_audit_node(node);
rcu_read_unlock();
return node;
@@ -490,9 +501,12 @@ struct aa_audit_node *aa_audit_cache_find(struct aa_audit_cache *cache,
* @cache: the cache to insert into
* @node: the audit node to insert into the cache
*
* Returns: matching node in cache OR @node if @node was inserted.
* Returns: refcounted matching node in cache OR @node if @node was inserted.
*
* Increments refcount on node if successfully inserted. Assumes caller
* already has valid ref count.
* Increments refcount on existing node if returned
*/
struct aa_audit_node *aa_audit_cache_insert(struct aa_audit_cache *cache,
struct aa_audit_node *node)
@@ -507,6 +521,8 @@ struct aa_audit_node *aa_audit_cache_insert(struct aa_audit_cache *cache,
tmp = node;
cache->size++;
}
aa_get_audit_node(tmp);
/* else raced another insert */
spin_unlock(&cache->lock);
@@ -531,7 +547,7 @@ void aa_audit_cache_destroy(struct aa_audit_cache *cache)
list_for_each_entry_safe(node, tmp, &cache->head, list) {
list_del_init(&node->list);
aa_audit_node_free(node);
aa_put_audit_node(node);
}
cache->size = 0;
}
+19 -18
View File
@@ -106,6 +106,7 @@ static int check_cache(struct aa_profile *profile,
AA_DEBUG(DEBUG_UPCALL,
"cache hit denied, request: 0x%x by cached deny 0x%x\n",
ad->request, hit->data.denied);
aa_put_audit_node(hit);
return ad->error;
} else if (ad->request & ~hit->data.request) {
/* asking for more perms than is cached */
@@ -116,9 +117,12 @@ static int check_cache(struct aa_profile *profile,
} else {
AA_DEBUG(DEBUG_UPCALL, "cache hit");
ad->error = 0;
aa_put_audit_node(hit);
/* do audit */
return 0;
}
aa_put_audit_node(hit);
hit = NULL;
} else {
AA_DEBUG(DEBUG_UPCALL, "cache miss");
}
@@ -151,34 +155,31 @@ static int check_cache(struct aa_profile *profile,
ad->error = node->data.error;
if (cache_response) {
if (hit) {
hit:
/* TODO: shouldn't add until after auditing it, or at
* least having a refcount. Fix once removing entry is
* allowed
*/
AA_DEBUG(DEBUG_UPCALL, "inserting cache entry requ 0x%x denied 0x%x",
node->data.request, node->data.denied);
hit = aa_audit_cache_insert(&profile->learning_cache,
node);
AA_DEBUG(DEBUG_UPCALL, "cache insert %s: name %s node %s\n",
hit != node ? "lost race" : "",
hit->data.name, node->data.name);
if (hit != node) {
AA_DEBUG(DEBUG_UPCALL, "updating existing cache entry");
aa_audit_cache_update_ent(&profile->learning_cache,
hit, &node->data);
aa_put_audit_node(hit);
} else {
/* TODO: shouldn't add until after auditing it, or at
* least having a refcount. Fix once removing entry is
* allowed
*/
AA_DEBUG(DEBUG_UPCALL, "inserting cache entry requ 0x%x denied 0x%x",
node->data.request, node->data.denied);
hit = aa_audit_cache_insert(&profile->learning_cache,
node);
AA_DEBUG(DEBUG_UPCALL, "cache insert %s: name %s node %s\n",
hit != node ? "lost race" : "",
hit->data.name, node->data.name);
if (hit != node)
goto hit;
AA_DEBUG(DEBUG_UPCALL, "inserted into cache");
/* do not free node, it is now owned by the cache */
node = NULL;
}
/* now to audit */
} /* cache_response */
return_to_audit:
aa_audit_node_free(node);
aa_put_audit_node(node);
return 0;
}
+18 -1
View File
@@ -174,6 +174,7 @@ struct apparmor_audit_data {
};
struct aa_audit_node {
struct kref count;
struct apparmor_audit_data data;
struct list_head list;
struct aa_knotif knotif;
@@ -254,10 +255,26 @@ int aa_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, void *vrule,
int lsmid);
void aa_audit_node_free(struct aa_audit_node *node);
void aa_audit_node_free_kref(struct kref *kref);
struct aa_audit_node *aa_dup_audit_data(struct apparmor_audit_data *orig,
gfp_t gfp);
long aa_audit_data_cmp(struct apparmor_audit_data *lhs,
struct apparmor_audit_data *rhs);
static inline struct aa_audit_node *aa_get_audit_node(struct aa_audit_node *node)
{
if (node)
kref_get(&(node->count));
return node;
}
static inline void aa_put_audit_node(struct aa_audit_node *node)
{
if (node)
kref_put(&node->count, aa_audit_node_free_kref);
}
#endif /* __AA_AUDIT_H */
-1
View File
@@ -91,5 +91,4 @@ static inline void aa_put_listener(struct aa_listener *listener)
kref_put(&listener->count, aa_listener_kref);
}
#endif /* __AA_NOTIFY_H */