summaryrefslogtreecommitdiffstats
path: root/lib/assoc_array.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2013-12-02 12:24:18 +0100
committerDavid Howells <dhowells@redhat.com>2013-12-02 12:24:18 +0100
commitd54e58b7f01552b0eb7d445f4b58de4499ad5ea6 (patch)
treea9fa542f64099599b74dbe6f77107d6cb79d3324 /lib/assoc_array.c
parentKEYS: Pre-clear struct key on allocation (diff)
downloadlinux-d54e58b7f01552b0eb7d445f4b58de4499ad5ea6.tar.xz
linux-d54e58b7f01552b0eb7d445f4b58de4499ad5ea6.zip
KEYS: Fix the keyring hash function
The keyring hash function (used by the associative array) is supposed to clear the bottommost nibble of the index key (where the hash value resides) for keyrings and make sure it is non-zero for non-keyrings. This is done to make keyrings cluster together on one branch of the tree separately to other keys. Unfortunately, the wrong mask is used, so only the bottom two bits are examined and cleared and not the whole bottom nibble. This means that keys and keyrings can still be successfully searched for under most circumstances as the hash is consistent in its miscalculation, but if a keyring's associative array bottom node gets filled up then approx 75% of the keyrings will not be put into the 0 branch. The consequence of this is that a key in a keyring linked to by another keyring, ie. keyring A -> keyring B -> key may not be found if the search starts at keyring A and then descends into keyring B because search_nested_keyrings() only searches up the 0 branch (as it "knows" all keyrings must be there and not elsewhere in the tree). The fix is to use the right mask. This can be tested with: r=`keyctl newring sandbox @s` for ((i=0; i<=16; i++)); do keyctl newring ring$i $r; done for ((i=0; i<=16; i++)); do keyctl add user a$i a %:ring$i; done for ((i=0; i<=16; i++)); do keyctl search $r user a$i; done This creates a sandbox keyring, then creates 17 keyrings therein (labelled ring0..ring16). This causes the root node of the sandbox's associative array to overflow and for the tree to have extra nodes inserted. Each keyring then is given a user key (labelled aN for ringN) for us to search for. We then search for the user keys we added, starting from the sandbox. If working correctly, it should return the same ordered list of key IDs as for...keyctl add... did. Without this patch, it reports ENOKEY "Required key not available" for some of the keys. Just which keys get this depends as the kernel pointer to the key type forms part of the hash function. Reported-by: Nalin Dahyabhai <nalin@redhat.com> Signed-off-by: David Howells <dhowells@redhat.com> Tested-by: Stephen Gallagher <sgallagh@redhat.com>
Diffstat (limited to 'lib/assoc_array.c')
0 files changed, 0 insertions, 0 deletions