|
20 | 20 | */ |
21 | 21 | /* |
22 | 22 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
| 23 | + * Copyright (c) 2012, Joyent, Inc. All rights reserved. |
23 | 24 | */ |
24 | 25 |
|
25 | 26 | #include <sys/asm_linkage.h> |
@@ -565,6 +566,33 @@ _syscall_invoke: |
565 | 566 | CLI(%r14) |
566 | 567 | CHECK_POSTSYS_NE(%r15, %r14, %ebx) |
567 | 568 | jne _syscall_post |
| 569 | + |
| 570 | + /* |
| 571 | + * We need to protect ourselves against non-canonical return values |
| 572 | + * because Intel doesn't check for them on sysret (AMD does). Canonical |
| 573 | + * addresses on current amd64 processors only use 48-bits for VAs; an |
| 574 | + * address is canonical if all upper bits (47-63) are identical. If we |
| 575 | + * find a non-canonical %rip, we opt to go through the full |
| 576 | + * _syscall_post path which takes us into an iretq which is not |
| 577 | + * susceptible to the same problems sysret is. |
| 578 | + * |
| 579 | + * We're checking for a canonical address by first doing an arithmetic |
| 580 | + * shift. This will fill in the remaining bits with the value of bit 63. |
| 581 | + * If the address were canonical, the register would now have either all |
| 582 | + * zeroes or all ones in it. Therefore we add one (inducing overflow) |
| 583 | + * and compare against 1. A canonical address will either be zero or one |
| 584 | + * at this point, hence the use of ja. |
| 585 | + * |
| 586 | + * At this point, r12 and r13 have the return value so we can't use |
| 587 | + * those registers. |
| 588 | + */ |
| 589 | + movq REGOFF_RIP(%rsp), %rcx |
| 590 | + sarq $47, %rcx |
| 591 | + incq %rcx |
| 592 | + cmpq $1, %rcx |
| 593 | + ja _syscall_post |
| 594 | + |
| 595 | + |
568 | 596 | SIMPLE_SYSCALL_POSTSYS(%r15, %r14, %bx) |
569 | 597 |
|
570 | 598 | movq %r12, REGOFF_RAX(%rsp) |
|
0 commit comments