On Thu, Jan 18, 2018 at 4:01 PM, Dan Williams dan.j.williams@intel.com wrote:
Changes since v3 [1]
Drop 'ifence_array_ptr' and associated compile-time + run-time switching and just use the masking approach all the time.
Convert 'get_user' to use pointer sanitization via masking rather than lfence. '__get_user' and associated paths still rely on lfence. (Linus)
"Basically, the rule is trivial: find all 'stac' users, and use address masking if those users already integrate the limit check, and lfence they don't."
At syscall entry sanitize the syscall number under speculation to remove a user controlled pointer de-reference in kernel space. (Linus)
Fix a raw lfence in the kvm code (added for v4.15-rc8) to use 'array_ptr'.
Propose 'array_idx' as a way to sanitize user input that is later used as an array index, but where the validation is happening in a different code block than the array reference. (Christian).
Fix grammar in speculation.txt (Kees)
Quoting Mark's original RFC:
"Recently, Google Project Zero discovered several classes of attack against speculative execution. One of these, known as variant-1, allows explicit bounds checks to be bypassed under speculation, providing an arbitrary read gadget. Further details can be found on the GPZ blog [2] and the Documentation patch in this series."
A precondition of using this attack on the kernel is to get a user controlled pointer de-referenced (under speculation) in privileged code. The primary source of user controlled pointers in the kernel is the arguments passed to 'get_user' and '__get_user'. An example of other user controlled pointers are user-controlled array / pointer offsets.
Better tooling is needed to find more arrays / pointers with user controlled indices / offsets that can be converted to use 'array_ptr' or 'array_idx'. A few are included in this set, and these are not expected to be complete. That said, the 'get_user' protections raise the bar on finding a vulnerable gadget in the kernel.
These patches are also available via the 'nospec-v4' git branch here:
git://git.kernel.org/pub/scm/linux/kernel/git/djbw/linux nospec-v4
I've pushed out a nospec-v4.1 with the below minor cleanup, a fixup of the changelog for "kvm, x86: fix spectre-v1 mitigation", and added Paolo's ack.
git://git.kernel.org/pub/scm/linux/kernel/git/djbw/linux nospec-v4.1
diff --git a/include/linux/nospec.h b/include/linux/nospec.h index 8af35be1869e..b8a9222e34d1 100644 --- a/include/linux/nospec.h +++ b/include/linux/nospec.h @@ -37,7 +37,7 @@ static inline unsigned long array_ptr_mask(unsigned long idx, unsigned long sz) unsigned long _i = (idx); \ unsigned long _mask = array_ptr_mask(_i, (sz)); \ \ - __u._ptr = _arr + (_i & _mask); \ + __u._ptr = _arr + _i; \ __u._bit &= _mask; \ __u._ptr; \ })