metag/uaccess: Fix access_ok()
commit 8a8b56638bcac4e64cccc88bf95a0f9f4b19a2fb upstream.
The __user_bad() macro used by access_ok() has a few corner cases
noticed by Al Viro where it doesn't behave correctly:
- The kernel range check has off by 1 errors which permit access to the
first and last byte of the kernel mapped range.
- The kernel range check ends at LINCORE_BASE rather than
META_MEMORY_LIMIT, which is ineffective when the kernel is in global
space (an extremely uncommon configuration).
There are a couple of other shortcomings here too:
- Access to the whole of the other address space is permitted (i.e. the
global half of the address space when the kernel is in local space).
This isn't ideal as it could theoretically still contain privileged
mappings set up by the bootloader.
- The size argument is unused, permitting user copies which start on
valid pages at the end of the user address range and cross the
boundary into the kernel address space (e.g. addr = 0x3ffffff0, size
> 0x10).
It isn't very convenient to add size checks when disallowing certain
regions, and it seems far safer to be sure and explicit about what
userland is able to access, so invert the logic to allow certain regions
instead, and fix the off by 1 errors and missing size checks. This also
allows the get_fs() == KERNEL_DS check to be more easily optimised into
the user address range case.
We now have 3 such allowed regions:
- The user address range (incorporating the get_fs() == KERNEL_DS
check).
- NULL (some kernel code expects this to work, and we'll always catch
the fault anyway).
- The core code memory region.
Fixes: 373cd784d0fc ("metag: Memory handling")
Reported-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: linux-metag@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 file changed