]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Make ossl_ht_delete use read-once semantics
authorNeil Horman <nhorman@openssl.org>
Mon, 22 Jul 2024 21:28:02 +0000 (17:28 -0400)
committerNeil Horman <nhorman@openssl.org>
Wed, 31 Jul 2024 12:05:53 +0000 (08:05 -0400)
To ensure that the value of h->md doesn't get recomputed during a delete
operation use ossl_rcu_deref on it

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com>
(Merged from https://github.com/openssl/openssl/pull/24969)

crypto/hashtable/hashtable.c

index 61d11940a9dcba4c10c23838baabeae136069192..b24b64571493145bcec2c254f81830a93f3628c6 100644 (file)
@@ -485,7 +485,6 @@ static int grow_hashtable(HT *h, size_t oldsize)
     /*
      * Now we replace the old mutable data with the new
      */
-    oldmd = ossl_rcu_deref(&h->md);
     ossl_rcu_assign_ptr(&h->md, &newmd);
     ossl_rcu_call(h->lock, free_old_neigh_table, oldmd);
     h->wpd.need_sync = 1;
@@ -658,6 +657,7 @@ static void free_old_entry(void *arg)
 
 int ossl_ht_delete(HT *h, HT_KEY *key)
 {
+    struct ht_mutable_data_st *md = ossl_rcu_deref(&h->md);
     uint64_t hash;
     uint64_t neigh_idx;
     size_t j;
@@ -667,15 +667,15 @@ int ossl_ht_delete(HT *h, HT_KEY *key)
 
     hash = h->config.ht_hash_fn(key->keybuf, key->keysize);
 
-    neigh_idx = hash & h->md->neighborhood_mask;
-    PREFETCH_NEIGHBORHOOD(h->md->neighborhoods[neigh_idx]);
+    neigh_idx = hash & md->neighborhood_mask;
+    PREFETCH_NEIGHBORHOOD(md->neighborhoods[neigh_idx]);
     for (j = 0; j < NEIGHBORHOOD_LEN; j++) {
-        if (compare_hash(hash, h->md->neighborhoods[neigh_idx].entries[j].hash)) {
+        if (compare_hash(hash, md->neighborhoods[neigh_idx].entries[j].hash)) {
             h->wpd.value_count--;
-            CRYPTO_atomic_store(&h->md->neighborhoods[neigh_idx].entries[j].hash,
+            CRYPTO_atomic_store(&md->neighborhoods[neigh_idx].entries[j].hash,
                                 0, h->atomic_lock);
-            v = (struct ht_internal_value_st *)h->md->neighborhoods[neigh_idx].entries[j].value;
-            ossl_rcu_assign_ptr(&h->md->neighborhoods[neigh_idx].entries[j].value,
+            v = (struct ht_internal_value_st *)md->neighborhoods[neigh_idx].entries[j].value;
+            ossl_rcu_assign_ptr(&md->neighborhoods[neigh_idx].entries[j].value,
                                 &nv);
             rc = 1;
             break;