• David Howells's avatar
    KEYS: Fix searching of nested keyrings · 9c5e45df
    David Howells authored
    If a keyring contains more than 16 keyrings (the capacity of a single node in
    the associative array) then those keyrings are split over multiple nodes
    arranged as a tree.
    
    If search_nested_keyrings() is called to search the keyring then it will
    attempt to manually walk over just the 0 branch of the associative array tree
    where all the keyring links are stored.  This works provided the key is found
    before the algorithm steps from one node containing keyrings to a child node
    or if there are sufficiently few keyring links that the keyrings are all in
    one node.
    
    However, if the algorithm does need to step from a node to a child node, it
    doesn't change the node pointer unless a shortcut also gets transited.  This
    means that the algorithm will keep scanning the same node over and over again
    without terminating and without returning.
    
    To fix this, move the internal-pointer-to-node translation from inside the
    shortcut transit handler so that it applies it to node arrival as well.
    
    This can be tested by:
    
    	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
    	for ((i=17; i<=20; i++)); do keyctl search $r user a$i; done
    
    The searches should all complete successfully (or with an error for 17-20),
    but instead one or more of them will hang.
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    Tested-by: default avatarStephen Gallagher <sgallagh@redhat.com>
    9c5e45df
keyring.c 35.8 KB