This is a note to let you know that I've just added the patch titled cipso,calipso: resolve a number of problems with the DOI refcounts to the 4.9-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: cipso-calipso-resolve-a-number-of-problems-with-the-doi-refcounts.patch and it can be found in the queue-4.9 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From foo@baz Mon Jan 24 07:28:36 PM CET 2022 From: Ben Hutchings <ben@xxxxxxxxxxxxxxx> Date: Mon, 24 Jan 2022 17:32:21 +0100 Subject: cipso,calipso: resolve a number of problems with the DOI refcounts To: stable@xxxxxxxxxxxxxxx Cc: Paul Moore <paul@xxxxxxxxxxxxxx> Message-ID: <Ye7UlciYUYBcfI31@xxxxxxxxxxxxxxx> Content-Disposition: inline From: Paul Moore <paul@xxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxxxxxxxxxxxx Signed-off-by: Paul Moore <paul@xxxxxxxxxxxxxx> Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx> [bwh: Backported to 4.9: adjust context] Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- net/ipv4/cipso_ipv4.c | 11 +---------- net/ipv6/calipso.c | 14 +++++--------- net/netlabel/netlabel_cipso_v4.c | 3 +++ 3 files changed, 9 insertions(+), 19 deletions(-) --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -534,16 +534,10 @@ int cipso_v4_doi_remove(u32 doi, struct ret_val = -ENOENT; goto doi_remove_return; } - if (!atomic_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: @@ -600,9 +594,6 @@ void cipso_v4_doi_putdef(struct cipso_v4 if (!atomic_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); --- a/net/ipv6/calipso.c +++ b/net/ipv6/calipso.c @@ -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, s ret_val = -ENOENT; goto doi_remove_return; } - if (!atomic_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 ca if (!atomic_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); } --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -587,6 +587,7 @@ list_start: break; } + cipso_v4_doi_putdef(doi_def); rcu_read_unlock(); genlmsg_end(ans_skb, data); @@ -595,12 +596,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); Patches currently in stable-queue which might be from ben@xxxxxxxxxxxxxxx are queue-4.9/lib-timerqueue-rely-on-rbtree-semantics-for-next-timer.patch queue-4.9/gup-document-and-work-around-cow-can-break-either-way-issue.patch queue-4.9/fuse-fix-live-lock-in-fuse_iget.patch queue-4.9/kvm-do-not-assume-pte-is-writable-after-follow_pfn.patch queue-4.9/drm-ttm-nouveau-don-t-call-tt-destroy-callback-on-alloc-failure.patch queue-4.9/gianfar-simplify-fcs-handling-and-fix-memory-leak.patch queue-4.9/mm-add-follow_pte_pmd.patch queue-4.9/revert-gup-document-and-work-around-cow-can-break-either-way-issue.patch queue-4.9/gianfar-fix-jumbo-packets-napi-rx-overrun-crash.patch queue-4.9/cipso-calipso-resolve-a-number-of-problems-with-the-doi-refcounts.patch queue-4.9/rbtree-cache-leftmost-node-internally.patch queue-4.9/kvm-use-kvm_pfn_t-for-local-pfn-variable-in-hva_to_pfn_remapped.patch queue-4.9/kvm-do-not-allow-mapping-valid-but-non-reference-counted-pages.patch queue-4.9/fuse-fix-bad-inode.patch