Commit a270b3e0 authored by John Johansen's avatar John Johansen Committed by Thadeu Lima de Souza Cascardo

UBUNTU: SAUCE: apparmor: fix label leak when new label is unused

When a new label is created, it is created with a proxy in a circular
ref count that is broken by replacement. However if the label is not
used it will never be replaced and the circular ref count will never
be broken resulting in a leak.

BugLink: http://bugs.launchpad.net/bugs/1660834Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
Acked-by: default avatarStefan Bader <stefan.bader@canonical.com>
Acked-by: default avatarTim Gardner <tim.gardner@canonical.com>
Acked-by: default avatarBrad Figg <brad.figg@canonical.com>
Signed-off-by: default avatarThadeu Lima de Souza Cascardo <cascardo@canonical.com>
parent 5b7add16
......@@ -308,6 +308,8 @@ int aa_vec_unique(struct aa_profile **vec, int n, int flags)
static void label_destroy(struct aa_label *label)
{
struct aa_label *tmp;
AA_BUG(!label);
if (label_is_stale(label))
......@@ -329,6 +331,11 @@ static void label_destroy(struct aa_label *label)
rcu_assign_pointer(label->proxy->label, NULL);
aa_free_sid(label->sid);
tmp = rcu_dereference_protected(label->proxy->label, true);
if (tmp == label)
rcu_assign_pointer(label->proxy->label, NULL);
aa_put_proxy(label->proxy);
label->proxy = (struct aa_proxy *) PROXY_POISON + 1;
}
......@@ -380,6 +387,15 @@ void aa_label_kref(struct kref *kref)
call_rcu(&label->rcu, label_free_rcu);
}
static void label_free_or_put_new(struct aa_label *label, struct aa_label *new)
{
if (label != new)
/* need to free directly to break circular ref with proxy */
aa_label_free(new);
else
aa_put_label(new);
}
bool aa_label_init(struct aa_label *label, int size)
{
AA_BUG(!label);
......@@ -842,7 +858,7 @@ static struct aa_label *vec_create_and_insert_label(struct aa_profile **vec,
write_lock_irqsave(&ls->lock, flags);
label = __label_insert(ls, new, false);
write_unlock_irqrestore(&ls->lock, flags);
aa_put_label(new);
label_free_or_put_new(label, new);
return label;
}
......@@ -1241,7 +1257,7 @@ struct aa_label *aa_label_merge(struct aa_label *a, struct aa_label *b,
goto out;
label = label_merge_insert(new, a, b);
aa_put_label(new);
label_free_or_put_new(label, new);
out:
aa_put_label(a);
aa_put_label(b);
......@@ -2042,8 +2058,7 @@ static struct aa_label *__label_update(struct aa_label *label)
/* ensure label is removed, and redirected correctly */
__label_remove(label, tmp);
write_unlock_irqrestore(&ls->lock, flags);
aa_put_label(new);
label_free_or_put_new(tmp, new);
return tmp;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment