Skip to content

Commit 50b343d

Browse files
committed
libchkstk: Add frame low address overflow checks
If an especially large frame is requested, the low frame address might overflow and land above the stack pointer, disabling the stack probe. In practice it would only happen from alloca calls and VLAs using untrusted sizes, but it would be nice to handle it anyway. This change introduces an overflow check, nulling the low address and forcing the probe loop to run until it overflows the stack. In 64-bit (all) and 32-bit ___chkstk_ms, it costs a two-byte instruction on the unhappy path, and on the fast path conversion of an unconditional jump to a predictable conditional jump. On 32-bit __chkstk it costs two, two-byte instructions, one on the fast path and one on the unhappy path. Not too bad. The stack low address "mov" did not need to move. I did it to keep the stack frame operations together. Thanks to Stefan Kanthak for pointing out this defect.
1 parent 6708972 commit 50b343d

File tree

1 file changed

+10
-6
lines changed

1 file changed

+10
-6
lines changed

src/libchkstk.S

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ __chkstk:
2929
# endif
3030
push %rax
3131
push %rcx
32+
mov %gs:(0x10), %rcx // rcx = stack low address
3233
neg %rax // rax = frame low address
3334
add %rsp, %rax // "
34-
mov %gs:(0x10), %rcx // rcx = stack low address
35-
jmp 1f
35+
jb 1f // frame low address overflow?
36+
xor %eax, %eax // overflowed: frame low address = null
3637
0: sub $0x1000, %rcx // extend stack into guard page
3738
test %eax, (%rcx) // commit page (two instruction bytes)
3839
1: cmp %rax, %rcx
@@ -49,10 +50,11 @@ __chkstk:
4950
___chkstk_ms:
5051
push %eax
5152
push %ecx
53+
mov %fs:(0x08), %ecx // ecx = stack low address
5254
neg %eax // eax = frame low address
5355
add %esp, %eax // "
54-
mov %fs:(0x08), %ecx // ecx = stack low address
55-
jmp 1f
56+
jb 1f // frame low address overflow?
57+
xor %eax, %eax // overflowed: frame low address = null
5658
0: sub $0x1000, %ecx // extend stack into guard page
5759
test %eax, (%ecx) // commit page (two instruction bytes)
5860
1: cmp %eax, %ecx
@@ -66,10 +68,12 @@ ___chkstk_ms:
6668
.globl __chkstk
6769
__chkstk:
6870
push %ecx // preserve ecx
71+
mov %fs:(0x08), %ecx // ecx = stack low address
6972
neg %eax // eax = frame low address
7073
lea 8(%esp,%eax), %eax // "
71-
mov %fs:(0x08), %ecx // ecx = stack low address
72-
jmp 1f
74+
cmp %esp, %eax // frame low address overflow?
75+
jb 1f // "
76+
xor %eax, %eax // overflowed: frame low address = null
7377
0: sub $0x1000, %ecx // extend stack into guard page
7478
test %eax, (%ecx) // commit page (two instruction bytes)
7579
1: cmp %eax, %ecx

0 commit comments

Comments
 (0)