aboutsummaryrefslogtreecommitdiffstats
path: root/lib/assoc_array.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-02-14 11:20:15 -0500
committerJames Morris <james.morris@microsoft.com>2019-02-15 17:12:08 -0500
commitbb2ba2d75a2d673e76ddaf13a9bd30d6a8b1bb08 (patch)
tree9f3a8e081a191743d29454281be65d32792ec974 /lib/assoc_array.c
parenta08bf91ce28ed3ae7b6fef35d843fef8dc8c2cd9 (diff)
assoc_array: Fix shortcut creation
Fix the creation of shortcuts for which the length of the index key value is an exact multiple of the machine word size. The problem is that the code that blanks off the unused bits of the shortcut value malfunctions if the number of bits in the last word equals machine word size. This is due to the "<<" operator being given a shift of zero in this case, and so the mask that should be all zeros is all ones instead. This causes the subsequent masking operation to clear everything rather than clearing nothing. Ordinarily, the presence of the hash at the beginning of the tree index key makes the issue very hard to test for, but in this case, it was encountered due to a development mistake that caused the hash output to be either 0 (keyring) or 1 (non-keyring) only. This made it susceptible to the keyctl/unlink/valid test in the keyutils package. The fix is simply to skip the blanking if the shift would be 0. For example, an index key that is 64 bits long would produce a 0 shift and thus a 'blank' of all 1s. This would then be inverted and AND'd onto the index_key, incorrectly clearing the entire last word. Fixes: 3cb989501c26 ("Add a generic associative array implementation.") Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <james.morris@microsoft.com>
Diffstat (limited to 'lib/assoc_array.c')
-rw-r--r--lib/assoc_array.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/lib/assoc_array.c b/lib/assoc_array.c
index c6659cb37033..59875eb278ea 100644
--- a/lib/assoc_array.c
+++ b/lib/assoc_array.c
@@ -768,9 +768,11 @@ all_leaves_cluster_together:
768 new_s0->index_key[i] = 768 new_s0->index_key[i] =
769 ops->get_key_chunk(index_key, i * ASSOC_ARRAY_KEY_CHUNK_SIZE); 769 ops->get_key_chunk(index_key, i * ASSOC_ARRAY_KEY_CHUNK_SIZE);
770 770
771 blank = ULONG_MAX << (level & ASSOC_ARRAY_KEY_CHUNK_MASK); 771 if (level & ASSOC_ARRAY_KEY_CHUNK_MASK) {
772 pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, level, blank); 772 blank = ULONG_MAX << (level & ASSOC_ARRAY_KEY_CHUNK_MASK);
773 new_s0->index_key[keylen - 1] &= ~blank; 773 pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, level, blank);
774 new_s0->index_key[keylen - 1] &= ~blank;
775 }
774 776
775 /* This now reduces to a node splitting exercise for which we'll need 777 /* This now reduces to a node splitting exercise for which we'll need
776 * to regenerate the disparity table. 778 * to regenerate the disparity table.