Mercurial > illumos > illumos-gate
changeset 13724:7740792727e0
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>
author | Robert Mustacchi <rm@joyent.com> |
---|---|
date | Wed, 13 Jun 2012 22:54:43 +0000 |
parents | 3297c26a553a |
children | 9a3ca91fb74e |
files | usr/src/uts/i86pc/ml/syscall_asm_amd64.s |
diffstat | 1 files changed, 28 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/i86pc/ml/syscall_asm_amd64.s Thu Mar 08 08:06:39 2012 +0000 +++ b/usr/src/uts/i86pc/ml/syscall_asm_amd64.s Wed Jun 13 22:54:43 2012 +0000 @@ -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 @@ 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)