Permalink
Browse files

2873 sysretq doesn't properly handle non-canonical addresses

Reviewed by: Bryan Cantrill <bryan@joyent.com>
Reviewed by: Keith Wesolowski <keith.wesolowski@joyent.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Dan McDonald <danmcd@nexenta.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
  • Loading branch information...
rmustacc committed Jun 13, 2012
1 parent 3ddcfad commit 6ba2dbf5e79c7fc6e1221844ddaa2c88a42a3fc1
Showing with 28 additions and 0 deletions.
  1. +28 −0 usr/src/uts/i86pc/ml/syscall_asm_amd64.s
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/

#include <sys/asm_linkage.h>
@@ -565,6 +566,33 @@ _syscall_invoke:
CLI(%r14)
CHECK_POSTSYS_NE(%r15, %r14, %ebx)
jne _syscall_post

/*
* We need to protect ourselves against non-canonical return values
* because Intel doesn't check for them on sysret (AMD does). Canonical
* addresses on current amd64 processors only use 48-bits for VAs; an
* address is canonical if all upper bits (47-63) are identical. If we
* find a non-canonical %rip, we opt to go through the full
* _syscall_post path which takes us into an iretq which is not
* susceptible to the same problems sysret is.
*
* We're checking for a canonical address by first doing an arithmetic
* shift. This will fill in the remaining bits with the value of bit 63.
* If the address were canonical, the register would now have either all
* zeroes or all ones in it. Therefore we add one (inducing overflow)
* and compare against 1. A canonical address will either be zero or one
* at this point, hence the use of ja.
*
* At this point, r12 and r13 have the return value so we can't use
* those registers.
*/
movq REGOFF_RIP(%rsp), %rcx
sarq $47, %rcx
incq %rcx
cmpq $1, %rcx
ja _syscall_post


SIMPLE_SYSCALL_POSTSYS(%r15, %r14, %bx)

movq %r12, REGOFF_RAX(%rsp)

0 comments on commit 6ba2dbf

Please sign in to comment.