• Linus Torvalds's avatar
    maccess: make get_kernel_nofault() check for minimal type compatibility · 0c389d89
    Linus Torvalds authored
    Now that we've renamed probe_kernel_address() to get_kernel_nofault()
    and made it look and behave more in line with get_user(), some of the
    subtle type behavior differences end up being more obvious and possibly
    dangerous.
    
    When you do
    
            get_user(val, user_ptr);
    
    the type of the access comes from the "user_ptr" part, and the above
    basically acts as
    
            val = *user_ptr;
    
    by design (except, of course, for the fact that the actual dereference
    is done with a user access).
    
    Note how in the above case, the type of the end result comes from the
    pointer argument, and then the value is cast to the type of 'val' as
    part of the assignment.
    
    So the type of the pointer is ultimately the more important type both
    for the access itself.
    
    But 'get_kernel_nofault()' may now _look_ similar, but it behaves very
    differently.  When you do
    
            get_kernel_nofault(val, kernel_ptr);
    
    it behaves like
    
            val = *(typeof(val) *)kernel_ptr;
    
    except, of course, for the fact that the actual dereference is done with
    exception handling so that a faulting access is suppressed and returned
    as the error code.
    
    But note how different the casting behavior of the two superficially
    similar accesses are: one does the actual access in the size of the type
    the pointer points to, while the other does the access in the size of
    the target, and ignores the pointer type entirely.
    
    Actually changing get_kernel_nofault() to act like get_user() is almost
    certainly the right thing to do eventually, but in the meantime this
    patch adds logit to at least verify that the pointer type is compatible
    with the type of the result.
    
    In many cases, this involves just casting the pointer to 'void *' to
    make it obvious that the type of the pointer is not the important part.
    It's not how 'get_user()' acts, but at least the behavioral difference
    is now obvious and explicit.
    
    Cc: Christoph Hellwig <hch@lst.de>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    0c389d89
traps.c 20 KB