]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
cipso,calipso: resolve a number of problems with the DOI refcounts
authorPaul Moore <paul@paul-moore.com>
Thu, 4 Mar 2021 21:29:51 +0000 (16:29 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Mar 2021 15:34:29 +0000 (16:34 +0100)
commit ad5d07f4a9cd671233ae20983848874731102c08 upstream.

The current CIPSO and CALIPSO refcounting scheme for the DOI
definitions is a bit flawed in that we:

1. Don't correctly match gets/puts in netlbl_cipsov4_list().
2. Decrement the refcount on each attempt to remove the DOI from the
   DOI list, only removing it from the list once the refcount drops
   to zero.

This patch fixes these problems by adding the missing "puts" to
netlbl_cipsov4_list() and introduces a more conventional, i.e.
not-buggy, refcounting mechanism to the DOI definitions.  Upon the
addition of a DOI to the DOI list, it is initialized with a refcount
of one, removing a DOI from the list removes it from the list and
drops the refcount by one; "gets" and "puts" behave as expected with
respect to refcounts, increasing and decreasing the DOI's refcount by
one.

Fixes: b1edeb102397 ("netlabel: Replace protocol/NetLabel linking with refrerence counts")
Fixes: d7cce01504a0 ("netlabel: Add support for removing a CALIPSO DOI.")
Reported-by: syzbot+9ec037722d2603a9f52e@syzkaller.appspotmail.com
Signed-off-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/ipv4/cipso_ipv4.c
net/ipv6/calipso.c
net/netlabel/netlabel_cipso_v4.c

index 5535b722f66d67fb43e44124343e80283f613621..6a1b52b34e205a44f928560d90a21bf5def16a41 100644 (file)
@@ -533,16 +533,10 @@ int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info)
                ret_val = -ENOENT;
                goto doi_remove_return;
        }
-       if (!refcount_dec_and_test(&doi_def->refcount)) {
-               spin_unlock(&cipso_v4_doi_list_lock);
-               ret_val = -EBUSY;
-               goto doi_remove_return;
-       }
        list_del_rcu(&doi_def->list);
        spin_unlock(&cipso_v4_doi_list_lock);
 
-       cipso_v4_cache_invalidate();
-       call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu);
+       cipso_v4_doi_putdef(doi_def);
        ret_val = 0;
 
 doi_remove_return:
@@ -599,9 +593,6 @@ void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def)
 
        if (!refcount_dec_and_test(&doi_def->refcount))
                return;
-       spin_lock(&cipso_v4_doi_list_lock);
-       list_del_rcu(&doi_def->list);
-       spin_unlock(&cipso_v4_doi_list_lock);
 
        cipso_v4_cache_invalidate();
        call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu);
index 70611784c071f9a7070efce6fd1e3e9a2e2a1cf9..afc76062e1a11ed8367555448130a5b80ec437c2 100644 (file)
@@ -97,6 +97,9 @@ struct calipso_map_cache_entry {
 
 static struct calipso_map_cache_bkt *calipso_cache;
 
+static void calipso_cache_invalidate(void);
+static void calipso_doi_putdef(struct calipso_doi *doi_def);
+
 /* Label Mapping Cache Functions
  */
 
@@ -458,15 +461,10 @@ static int calipso_doi_remove(u32 doi, struct netlbl_audit *audit_info)
                ret_val = -ENOENT;
                goto doi_remove_return;
        }
-       if (!refcount_dec_and_test(&doi_def->refcount)) {
-               spin_unlock(&calipso_doi_list_lock);
-               ret_val = -EBUSY;
-               goto doi_remove_return;
-       }
        list_del_rcu(&doi_def->list);
        spin_unlock(&calipso_doi_list_lock);
 
-       call_rcu(&doi_def->rcu, calipso_doi_free_rcu);
+       calipso_doi_putdef(doi_def);
        ret_val = 0;
 
 doi_remove_return:
@@ -522,10 +520,8 @@ static void calipso_doi_putdef(struct calipso_doi *doi_def)
 
        if (!refcount_dec_and_test(&doi_def->refcount))
                return;
-       spin_lock(&calipso_doi_list_lock);
-       list_del_rcu(&doi_def->list);
-       spin_unlock(&calipso_doi_list_lock);
 
+       calipso_cache_invalidate();
        call_rcu(&doi_def->rcu, calipso_doi_free_rcu);
 }
 
index 9aacf2da3d98feaf94319f7315b255323f4416f2..3e3494c8d42f8dc51afa310c0163329170c57eea 100644 (file)
@@ -581,6 +581,7 @@ list_start:
 
                break;
        }
+       cipso_v4_doi_putdef(doi_def);
        rcu_read_unlock();
 
        genlmsg_end(ans_skb, data);
@@ -589,12 +590,14 @@ list_start:
 list_retry:
        /* XXX - this limit is a guesstimate */
        if (nlsze_mult < 4) {
+               cipso_v4_doi_putdef(doi_def);
                rcu_read_unlock();
                kfree_skb(ans_skb);
                nlsze_mult *= 2;
                goto list_start;
        }
 list_failure_lock:
+       cipso_v4_doi_putdef(doi_def);
        rcu_read_unlock();
 list_failure:
        kfree_skb(ans_skb);