Commit e23c92ae authored by John Johansen's avatar John Johansen Committed by Tim Gardner

Revert "UBUNTU: SAUCE: apparmor: Fix: refcount race between locating in labelset and get"

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

This reverts commit 3ceb6a970f5eec7580ec740ed493b07c142984f2.
Signed-off-by: default avatarTim Gardner <tim.gardner@canonical.com>
parent 03c5aa50
...@@ -391,8 +391,7 @@ static struct aa_label *__aa_label_insert(struct aa_labelset *ls, ...@@ -391,8 +391,7 @@ static struct aa_label *__aa_label_insert(struct aa_labelset *ls,
static struct aa_label *__aa_label_remove_and_insert(struct aa_labelset *ls, static struct aa_label *__aa_label_remove_and_insert(struct aa_labelset *ls,
struct aa_label *remove, struct aa_label *remove,
struct aa_label *insert, struct aa_label *insert)
bool replace)
{ {
AA_BUG(!ls); AA_BUG(!ls);
AA_BUG(!remove); AA_BUG(!remove);
...@@ -402,7 +401,7 @@ static struct aa_label *__aa_label_remove_and_insert(struct aa_labelset *ls, ...@@ -402,7 +401,7 @@ static struct aa_label *__aa_label_remove_and_insert(struct aa_labelset *ls,
AA_BUG(insert->flags & FLAG_IN_TREE); AA_BUG(insert->flags & FLAG_IN_TREE);
__aa_label_remove(ls, remove); __aa_label_remove(ls, remove);
return __aa_label_insert(ls, insert, replace); return __aa_label_insert(ls, insert, false);
} }
struct aa_label *aa_label_remove_and_insert(struct aa_labelset *ls, struct aa_label *aa_label_remove_and_insert(struct aa_labelset *ls,
...@@ -413,7 +412,7 @@ struct aa_label *aa_label_remove_and_insert(struct aa_labelset *ls, ...@@ -413,7 +412,7 @@ struct aa_label *aa_label_remove_and_insert(struct aa_labelset *ls,
struct aa_label *l; struct aa_label *l;
write_lock_irqsave(&ls->lock, flags); write_lock_irqsave(&ls->lock, flags);
l = __aa_label_remove_and_insert(ls, remove, insert, false); l = aa_get_label(__aa_label_remove_and_insert(ls, remove, insert));
write_unlock_irqrestore(&ls->lock, flags); write_unlock_irqrestore(&ls->lock, flags);
return l; return l;
...@@ -436,10 +435,12 @@ bool aa_label_replace(struct aa_labelset *ls, struct aa_label *old, ...@@ -436,10 +435,12 @@ bool aa_label_replace(struct aa_labelset *ls, struct aa_label *old,
bool res; bool res;
write_lock_irqsave(&ls->lock, flags); write_lock_irqsave(&ls->lock, flags);
l = __aa_label_remove_and_insert(ls, old, new, true); if (!(old->flags & FLAG_IN_TREE))
l = __aa_label_insert(ls, new, false);
else
l = __aa_label_remove_and_insert(ls, old, new);
res = (l == new); res = (l == new);
write_unlock_irqrestore(&ls->lock, flags); write_unlock_irqrestore(&ls->lock, flags);
aa_put_label(l);
return res; return res;
} }
...@@ -548,8 +549,7 @@ static int label_cmp(struct aa_label *a, struct aa_label *b) ...@@ -548,8 +549,7 @@ static int label_cmp(struct aa_label *a, struct aa_label *b)
* Requires: @ls lock held * Requires: @ls lock held
* caller to hold a valid ref on l * caller to hold a valid ref on l
* *
* Returns: ref counted @label if matching label is in tree * Returns: unref counted @label if matching label is in tree
* ref counted label that is equiv to @l in tree
* else NULL if @vec equiv is not in tree * else NULL if @vec equiv is not in tree
*/ */
static struct aa_label *__aa_label_vec_find(struct aa_labelset *ls, static struct aa_label *__aa_label_vec_find(struct aa_labelset *ls,
...@@ -572,7 +572,7 @@ static struct aa_label *__aa_label_vec_find(struct aa_labelset *ls, ...@@ -572,7 +572,7 @@ static struct aa_label *__aa_label_vec_find(struct aa_labelset *ls,
else if (result < 0) else if (result < 0)
node = node->rb_right; node = node->rb_right;
else else
return aa_get_label_not0(this); return this;
} }
return NULL; return NULL;
...@@ -586,8 +586,8 @@ static struct aa_label *__aa_label_vec_find(struct aa_labelset *ls, ...@@ -586,8 +586,8 @@ static struct aa_label *__aa_label_vec_find(struct aa_labelset *ls,
* Requires: @ls lock held * Requires: @ls lock held
* caller to hold a valid ref on l * caller to hold a valid ref on l
* *
* Returns: ref counted @l if @l is in tree OR * Returns: unref counted @l if @l is in tree
* ref counted label that is equiv to @l in tree * unref counted label that is equiv to @l in tree
* else NULL if @l or equiv is not in tree * else NULL if @l or equiv is not in tree
*/ */
static struct aa_label *__aa_label_find(struct aa_labelset *ls, static struct aa_label *__aa_label_find(struct aa_labelset *ls,
...@@ -620,7 +620,7 @@ struct aa_label *aa_label_vec_find(struct aa_labelset *ls, ...@@ -620,7 +620,7 @@ struct aa_label *aa_label_vec_find(struct aa_labelset *ls,
AA_BUG(n <= 0); AA_BUG(n <= 0);
read_lock_irqsave(&ls->lock, flags); read_lock_irqsave(&ls->lock, flags);
label = __aa_label_vec_find(ls, vec, n); label = aa_get_label(__aa_label_vec_find(ls, vec, n));
labelstats_inc(sread); labelstats_inc(sread);
read_unlock_irqrestore(&ls->lock, flags); read_unlock_irqrestore(&ls->lock, flags);
...@@ -653,9 +653,8 @@ struct aa_label *aa_label_find(struct aa_labelset *ls, struct aa_label *l) ...@@ -653,9 +653,8 @@ struct aa_label *aa_label_find(struct aa_labelset *ls, struct aa_label *l)
* Requires: @ls->lock * Requires: @ls->lock
* caller to hold a valid ref on l * caller to hold a valid ref on l
* *
* Returns: @l if successful in inserting @l - with additional refcount * Returns: @l if successful in inserting @l
* else ref counted equivalent label that is already in the set, * else ref counted equivalent label that is already in the set.
the else condition only happens if @replace is false
*/ */
static struct aa_label *__aa_label_insert(struct aa_labelset *ls, static struct aa_label *__aa_label_insert(struct aa_labelset *ls,
struct aa_label *l, bool replace) struct aa_label *l, bool replace)
...@@ -676,11 +675,10 @@ static struct aa_label *__aa_label_insert(struct aa_labelset *ls, ...@@ -676,11 +675,10 @@ static struct aa_label *__aa_label_insert(struct aa_labelset *ls,
parent = *new; parent = *new;
if (result == 0) { if (result == 0) {
labelsetstats_inc(ls, existing); labelsetstats_inc(ls, existing);
if (!replace && aa_get_label_not0(this)) if (!replace)
return this; return this;
/* *this is either queued for destruction or being replaced */ __aa_label_replace(ls, this, l);
AA_BUG(!__aa_label_replace(ls, this, l)); return l;
return aa_get_label(l);
} else if (result < 0) } else if (result < 0)
new = &((*new)->rb_left); new = &((*new)->rb_left);
else /* (result > 0) */ else /* (result > 0) */
...@@ -694,7 +692,7 @@ static struct aa_label *__aa_label_insert(struct aa_labelset *ls, ...@@ -694,7 +692,7 @@ static struct aa_label *__aa_label_insert(struct aa_labelset *ls,
labelsetstats_inc(ls, insert); labelsetstats_inc(ls, insert);
labelsetstats_inc(ls, intree); labelsetstats_inc(ls, intree);
return aa_get_label(l); return l;
} }
/** /**
...@@ -718,7 +716,7 @@ struct aa_label *aa_label_insert(struct aa_labelset *ls, struct aa_label *l) ...@@ -718,7 +716,7 @@ struct aa_label *aa_label_insert(struct aa_labelset *ls, struct aa_label *l)
/* check if label exists before taking lock */ /* check if label exists before taking lock */
if (!label_invalid(l)) { if (!label_invalid(l)) {
read_lock_irqsave(&ls->lock, flags); read_lock_irqsave(&ls->lock, flags);
label = __aa_label_find(ls, l); label = aa_get_label(__aa_label_find(ls, l));
read_unlock_irqrestore(&ls->lock, flags); read_unlock_irqrestore(&ls->lock, flags);
labelstats_inc(fread); labelstats_inc(fread);
if (label) if (label)
...@@ -726,7 +724,7 @@ struct aa_label *aa_label_insert(struct aa_labelset *ls, struct aa_label *l) ...@@ -726,7 +724,7 @@ struct aa_label *aa_label_insert(struct aa_labelset *ls, struct aa_label *l)
} }
write_lock_irqsave(&ls->lock, flags); write_lock_irqsave(&ls->lock, flags);
label = __aa_label_insert(ls, l, false); label = aa_get_label(__aa_label_insert(ls, l, false));
write_unlock_irqrestore(&ls->lock, flags); write_unlock_irqrestore(&ls->lock, flags);
return label; return label;
...@@ -957,7 +955,9 @@ static struct aa_label *__label_merge_insert(struct aa_labelset *ls, ...@@ -957,7 +955,9 @@ static struct aa_label *__label_merge_insert(struct aa_labelset *ls,
} }
if (label_profiles_unconfined(l)) if (label_profiles_unconfined(l))
l->flags |= FLAG_UNCONFINED; l->flags |= FLAG_UNCONFINED;
return __aa_label_insert(ls, l, true); __aa_label_insert(ls, l, true);
return aa_get_label(l);
} }
/** /**
...@@ -985,7 +985,7 @@ static struct aa_labelset *labelset_of_merge(struct aa_label *a, struct aa_label ...@@ -985,7 +985,7 @@ static struct aa_labelset *labelset_of_merge(struct aa_label *a, struct aa_label
* *
* Requires: read_lock held * Requires: read_lock held
* *
* Returns: ref counted label that is equiv to merge of @a and @b * Returns: unref counted label that is equiv to merge of @a and @b
* else NULL if merge of @a and @b is not in set * else NULL if merge of @a and @b is not in set
*/ */
static struct aa_label *__aa_label_find_merge(struct aa_labelset *ls, static struct aa_label *__aa_label_find_merge(struct aa_labelset *ls,
...@@ -1012,7 +1012,7 @@ static struct aa_label *__aa_label_find_merge(struct aa_labelset *ls, ...@@ -1012,7 +1012,7 @@ static struct aa_label *__aa_label_find_merge(struct aa_labelset *ls,
else if (result > 0) else if (result > 0)
node = node->rb_right; node = node->rb_right;
else else
return aa_get_label_not0(this); return this;
} }
return NULL; return NULL;
...@@ -1044,7 +1044,7 @@ struct aa_label *aa_label_find_merge(struct aa_label *a, struct aa_label *b) ...@@ -1044,7 +1044,7 @@ struct aa_label *aa_label_find_merge(struct aa_label *a, struct aa_label *b)
a = ar = aa_get_newest_label(a); a = ar = aa_get_newest_label(a);
if (label_invalid(b)) if (label_invalid(b))
b = br = aa_get_newest_label(b); b = br = aa_get_newest_label(b);
label = __aa_label_find_merge(ls, a, b); label = aa_get_label(__aa_label_find_merge(ls, a, b));
read_unlock_irqrestore(&ls->lock, flags); read_unlock_irqrestore(&ls->lock, flags);
aa_put_label(ar); aa_put_label(ar);
aa_put_label(br); aa_put_label(br);
...@@ -1145,14 +1145,13 @@ struct aa_label *aa_label_vec_merge(struct aa_profile **vec, int len, ...@@ -1145,14 +1145,13 @@ struct aa_label *aa_label_vec_merge(struct aa_profile **vec, int len,
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
new->ent[i] = aa_get_profile(vec[i]); new->ent[i] = aa_get_profile(vec[i]);
label = __aa_label_insert(ls, new, false); label = __aa_label_insert(ls, new, false);
if (label != new) {
aa_get_label(label);
/* not fully constructed don't put */
aa_label_free(new);
}
} }
write_unlock_irqrestore(&ls->lock, flags); write_unlock_irqrestore(&ls->lock, flags);
if (label != new)
/* not fully constructed don't put */
aa_label_free(new);
else
/* extra ref */
aa_put_label(new);
return label; return label;
} }
...@@ -1702,18 +1701,6 @@ void aa_labelset_init(struct aa_labelset *ls) ...@@ -1702,18 +1701,6 @@ void aa_labelset_init(struct aa_labelset *ls)
labelstats_init(&ls); labelstats_init(&ls);
} }
static bool vec_invalid(struct aa_profile **vec, int n)
{
int i;
for (i = 0; i < n; i++) {
if (PROFILE_INVALID(vec[i]))
return true;
}
return false;
}
static struct aa_label *labelset_next_invalid(struct aa_labelset *ls) static struct aa_label *labelset_next_invalid(struct aa_labelset *ls)
{ {
struct aa_label *label; struct aa_label *label;
...@@ -1729,14 +1716,18 @@ static struct aa_label *labelset_next_invalid(struct aa_labelset *ls) ...@@ -1729,14 +1716,18 @@ static struct aa_label *labelset_next_invalid(struct aa_labelset *ls)
struct label_it i; struct label_it i;
label = rb_entry(node, struct aa_label, node); label = rb_entry(node, struct aa_label, node);
if ((label_invalid(label) || vec_invalid(label->ent, label->size)) && if (label_invalid(label))
aa_get_label_not0(label))
goto out; goto out;
label_for_each(i, label, p) {
if (PROFILE_INVALID(p))
goto out;
}
} }
label = NULL; label = NULL;
out: out:
aa_get_label(label);
read_unlock_irqrestore(&ls->lock, flags); read_unlock_irqrestore(&ls->lock, flags);
return label; return label;
...@@ -1810,12 +1801,11 @@ static struct aa_label *__label_update(struct aa_label *label) ...@@ -1810,12 +1801,11 @@ static struct aa_label *__label_update(struct aa_label *label)
goto insert; goto insert;
} }
insert: insert:
tmp = __aa_label_remove_and_insert(labels_set(label), label, l, true); tmp = __aa_label_remove_and_insert(labels_set(label), label, l);
if (tmp != l) { if (tmp != l) {
aa_get_label(tmp);
aa_label_free(l); aa_label_free(l);
l = tmp; }
} else
aa_put_label(l); /* extr ref */
write_unlock_irqrestore(&ls->lock, flags); write_unlock_irqrestore(&ls->lock, flags);
......
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