lkml.org 
[lkml]   [2019]   [Mar]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.19 10/48] assoc_array: Fix shortcut creation
    Date
    From: David Howells <dhowells@redhat.com>

    [ Upstream commit bb2ba2d75a2d673e76ddaf13a9bd30d6a8b1bb08 ]

    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>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    lib/assoc_array.c | 8 +++++---
    1 file 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 @@ static bool assoc_array_insert_into_terminal_node(struct assoc_array_edit *edit,
    new_s0->index_key[i] =
    ops->get_key_chunk(index_key, i * ASSOC_ARRAY_KEY_CHUNK_SIZE);

    - blank = ULONG_MAX << (level & ASSOC_ARRAY_KEY_CHUNK_MASK);
    - pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, level, blank);
    - new_s0->index_key[keylen - 1] &= ~blank;
    + if (level & ASSOC_ARRAY_KEY_CHUNK_MASK) {
    + blank = ULONG_MAX << (level & ASSOC_ARRAY_KEY_CHUNK_MASK);
    + pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, level, blank);
    + new_s0->index_key[keylen - 1] &= ~blank;
    + }

    /* This now reduces to a node splitting exercise for which we'll need
    * to regenerate the disparity table.
    --
    2.19.1
    \
     
     \ /
      Last update: 2019-03-13 20:14    [W:4.860 / U:0.880 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site