Skip to content
  • Mitko Haralanov's avatar
    IB/hfi1: Fix buffer cache races which may cause corruption · e88c9271
    Mitko Haralanov authored
    
    
    There are two possible causes for node/memory corruption both
    of which are related to the cache eviction algorithm. One way
    to cause corruption is due to the asynchronous nature of the
    MMU invalidation and the locking used when invalidating node.
    
    The MMU invalidation routine would temporarily release the
    RB tree lock to avoid a deadlock. However, this would allow
    the eviction function to take the lock resulting in the removal
    of cache nodes.
    
    If the node being removed by the eviction code is the same as
    the node being invalidated, the result is use after free.
    
    The same is true in the other direction due to the temporary
    release of the eviction list lock in the eviction loop.
    
    Another corner case exists when dealing with the SDMA buffer
    cache that could cause memory corruption of kernel memory.
    The most common way, in which this corruption exhibits itself
    is a linked list node corruption. In that case, the kernel will
    complain that a node with poisoned pointers is being removed.
    The fact that the pointers are already poisoned means that the
    node has already been removed from the list.
    
    To root cause of this corruption was a mishandling of the
    eviction list maintained by the driver. In order for this
    to happen four conditions need to be satisfied:
    
       1. A node describing a user buffer already exists in the
          interval RB tree,
       2. The beginning of the current user buffer matches that
          node but is bigger. This will cause the node to be
          extended.
       3. The amount of cached buffers is close or at the limit
          of the buffer cache size.
       4. The node has dropped close to the end of the eviction
          list. This will cause the node to be considered for
          eviction.
    
    If all of the above conditions have been satisfied, it is
    possible for the eviction algorithm to evict the current node,
    which will free the node without the driver knowing.
    
    To solve both issues described above:
       - the locking around the MMU invalidation loop and cache
         eviction loop has been improved so locks are not released in
         the loop body,
       - a new RB function is introduced which will "atomically" find
         and remove the matching node from the RB tree, preventing the
         MMU invalidation loop from touching it, and
       - the node being extended by the pin_vector_pages() function is
         removed from the eviction list prior to calling the eviction
         function.
    
    Reviewed-by: default avatarDean Luick <dean.luick@intel.com>
    Signed-off-by: default avatarMitko Haralanov <mitko.haralanov@intel.com>
    Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
    e88c9271