mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Fix some todos
This commit is contained in:
parent
9d372f48dd
commit
9cc4f33c76
13 changed files with 261 additions and 139 deletions
17
ape/ape-m1.c
17
ape/ape-m1.c
|
@ -22,6 +22,7 @@
|
||||||
#include <libkern/OSCacheControl.h>
|
#include <libkern/OSCacheControl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <semaphore.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -30,7 +31,6 @@
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <semaphore.h>
|
|
||||||
|
|
||||||
#define pagesz 16384
|
#define pagesz 16384
|
||||||
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
|
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
|
||||||
|
@ -89,6 +89,8 @@ struct Syslib {
|
||||||
long (*sem_post)(int *);
|
long (*sem_post)(int *);
|
||||||
long (*sem_wait)(int *);
|
long (*sem_wait)(int *);
|
||||||
long (*sem_trywait)(int *);
|
long (*sem_trywait)(int *);
|
||||||
|
long (*getrlimit)(int, struct rlimit *);
|
||||||
|
long (*setrlimit)(int, const struct rlimit *);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ELFCLASS32 1
|
#define ELFCLASS32 1
|
||||||
|
@ -814,7 +816,8 @@ static long sys_getentropy(void *buf, size_t buflen) {
|
||||||
return sysret(getentropy(buf, buflen));
|
return sysret(getentropy(buf, buflen));
|
||||||
}
|
}
|
||||||
|
|
||||||
static long sys_sem_open(const char *name, int oflags, mode_t mode, unsigned value) {
|
static long sys_sem_open(const char *name, int oflags, mode_t mode,
|
||||||
|
unsigned value) {
|
||||||
return sysret((long)sem_open(name, oflags, mode, value));
|
return sysret((long)sem_open(name, oflags, mode, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,6 +841,14 @@ static long sys_sem_trywait(sem_t *sem) {
|
||||||
return sysret(sem_trywait(sem));
|
return sysret(sem_trywait(sem));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long sys_getrlimit(int which, struct rlimit *rlim) {
|
||||||
|
return sysret(getrlimit(which, rlim));
|
||||||
|
}
|
||||||
|
|
||||||
|
static long sys_setrlimit(int which, const struct rlimit *rlim) {
|
||||||
|
return sysret(setrlimit(which, rlim));
|
||||||
|
}
|
||||||
|
|
||||||
static long sys_write(int fd, const void *data, size_t size) {
|
static long sys_write(int fd, const void *data, size_t size) {
|
||||||
return sysret(write(fd, data, size));
|
return sysret(write(fd, data, size));
|
||||||
}
|
}
|
||||||
|
@ -930,6 +941,8 @@ int main(int argc, char **argv, char **envp) {
|
||||||
M->lib.sem_post = sys_sem_post;
|
M->lib.sem_post = sys_sem_post;
|
||||||
M->lib.sem_wait = sys_sem_wait;
|
M->lib.sem_wait = sys_sem_wait;
|
||||||
M->lib.sem_trywait = sys_sem_trywait;
|
M->lib.sem_trywait = sys_sem_trywait;
|
||||||
|
M->lib.getrlimit = sys_getrlimit;
|
||||||
|
M->lib.setrlimit = sys_setrlimit;
|
||||||
|
|
||||||
/* getenv("_") is close enough to at_execfn */
|
/* getenv("_") is close enough to at_execfn */
|
||||||
execfn = argc > 0 ? argv[0] : 0;
|
execfn = argc > 0 ? argv[0] : 0;
|
||||||
|
|
Binary file not shown.
|
@ -100,7 +100,7 @@ static int cosmo_clock_nanosleep(int clock, int flags,
|
||||||
if (timespec_cmp(remain, quantum) > 0) {
|
if (timespec_cmp(remain, quantum) > 0) {
|
||||||
waitfor = timespec_sub(remain, quantum);
|
waitfor = timespec_sub(remain, quantum);
|
||||||
if (sys_clock_nanosleep(sleep_clock, 0, &waitfor, rem) == -1) {
|
if (sys_clock_nanosleep(sleep_clock, 0, &waitfor, rem) == -1) {
|
||||||
if (rem && errno == EINTR) {
|
if (!flags && rem && errno == EINTR) {
|
||||||
*rem = timespec_add(*rem, quantum);
|
*rem = timespec_add(*rem, quantum);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
|
||||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
||||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
|
||||||
│ │
|
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
|
||||||
│ above copyright notice and this permission notice appear in all copies. │
|
|
||||||
│ │
|
|
||||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
||||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
||||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
||||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
||||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
||||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
||||||
#include "libc/macros.internal.h"
|
|
||||||
.privileged
|
|
||||||
|
|
||||||
diagnose_syscall:
|
|
||||||
push %rbp
|
|
||||||
mov %rsp,%rbp
|
|
||||||
push %rbx
|
|
||||||
push %r12
|
|
||||||
push %r13
|
|
||||||
push %r14
|
|
||||||
push %r15
|
|
||||||
|
|
||||||
mov $0x7fffffff,%eax
|
|
||||||
add $4,%eax # set sf/of/pf
|
|
||||||
|
|
||||||
mov %rdi,%rax # nr
|
|
||||||
mov %rsi,%rdi # arg 1
|
|
||||||
mov %rdx,%rsi # arg 2
|
|
||||||
mov %rcx,%rdx # arg 3
|
|
||||||
mov %r8,%r10 # arg 4
|
|
||||||
mov %r9,%r8 # arg 5
|
|
||||||
mov 16(%rbp),%r9 # arg 6
|
|
||||||
push 24(%rbp) # arg 7
|
|
||||||
push %rax # fake ret addr
|
|
||||||
mov 32(%rbp),%r12 # ucontext before
|
|
||||||
mov 40(%rbp),%r13 # ucontext after
|
|
||||||
xor %ecx,%ecx
|
|
||||||
xor %r11d,%r11d
|
|
||||||
mov $0x5555555555555555,%r11
|
|
||||||
mov $0x5555555555555555,%r14
|
|
||||||
mov $0x5555555555555555,%r15
|
|
||||||
mov $0x5555555555555555,%rbx
|
|
||||||
|
|
||||||
// save machine state before system call
|
|
||||||
pushf
|
|
||||||
pop 176(%r12)
|
|
||||||
mov %r8,40(%r12)
|
|
||||||
mov %r9,48(%r12)
|
|
||||||
mov %r10,56(%r12)
|
|
||||||
mov %r11,64(%r12)
|
|
||||||
mov %r12,72(%r12)
|
|
||||||
mov %r13,80(%r12)
|
|
||||||
mov %r14,88(%r12)
|
|
||||||
mov %r15,96(%r12)
|
|
||||||
mov %rdi,104(%r12)
|
|
||||||
mov %rsi,112(%r12)
|
|
||||||
mov %rbp,120(%r12)
|
|
||||||
mov %rbx,128(%r12)
|
|
||||||
mov %rdx,136(%r12)
|
|
||||||
mov %rax,144(%r12)
|
|
||||||
mov %rcx,152(%r12)
|
|
||||||
push %rbx
|
|
||||||
lea 320(%r12),%rbx
|
|
||||||
mov %rbx,224(%r12) # set fpregs ptr
|
|
||||||
pop %rbx
|
|
||||||
|
|
||||||
syscall
|
|
||||||
|
|
||||||
// save machine state after system call
|
|
||||||
pushf
|
|
||||||
pop 176(%r13)
|
|
||||||
mov %r8,40(%r13)
|
|
||||||
mov %r9,48(%r13)
|
|
||||||
mov %r10,56(%r13)
|
|
||||||
mov %r11,64(%r13)
|
|
||||||
mov %r12,72(%r13)
|
|
||||||
mov %r13,80(%r13)
|
|
||||||
mov %r14,88(%r13)
|
|
||||||
mov %r15,96(%r13)
|
|
||||||
mov %rdi,104(%r13)
|
|
||||||
mov %rsi,112(%r13)
|
|
||||||
mov %rbp,120(%r13)
|
|
||||||
mov %rbx,128(%r13)
|
|
||||||
mov %rdx,136(%r13)
|
|
||||||
mov %rax,144(%r13)
|
|
||||||
mov %rcx,152(%r13)
|
|
||||||
push %rbx
|
|
||||||
lea 320(%r13),%rbx
|
|
||||||
mov %rbx,224(%r13) # set fpregs ptr
|
|
||||||
pop %rbx
|
|
||||||
|
|
||||||
pop %r13
|
|
||||||
pop %r13
|
|
||||||
|
|
||||||
pop %r15
|
|
||||||
pop %r14
|
|
||||||
pop %r13
|
|
||||||
pop %r12
|
|
||||||
pop %rbx
|
|
||||||
pop %rbp
|
|
||||||
ret
|
|
||||||
.endfn diagnose_syscall,globl
|
|
|
@ -18,11 +18,13 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/struct/rlimit.internal.h"
|
#include "libc/calls/struct/rlimit.internal.h"
|
||||||
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/intrin/describeflags.internal.h"
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/runtime/stack.h"
|
#include "libc/runtime/stack.h"
|
||||||
|
#include "libc/runtime/syslib.internal.h"
|
||||||
#include "libc/sysv/consts/rlimit.h"
|
#include "libc/sysv/consts/rlimit.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
|
@ -40,6 +42,8 @@ int getrlimit(int resource, struct rlimit *rlim) {
|
||||||
rc = einval();
|
rc = einval();
|
||||||
} else if (!rlim || (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim)))) {
|
} else if (!rlim || (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim)))) {
|
||||||
rc = efault();
|
rc = efault();
|
||||||
|
} else if (IsXnuSilicon()) {
|
||||||
|
rc = _sysret(__syslib->__getrlimit(resource, rlim));
|
||||||
} else if (!IsWindows()) {
|
} else if (!IsWindows()) {
|
||||||
rc = sys_getrlimit(resource, rlim);
|
rc = sys_getrlimit(resource, rlim);
|
||||||
} else if (resource == RLIMIT_STACK) {
|
} else if (resource == RLIMIT_STACK) {
|
||||||
|
|
|
@ -342,23 +342,26 @@ static textwindows int ProcessMouseEvent(const struct NtInputRecord *r,
|
||||||
bs &= kNtFromLeft1stButtonPressed | kNtRightmostButtonPressed;
|
bs &= kNtFromLeft1stButtonPressed | kNtRightmostButtonPressed;
|
||||||
if (ev & kNtMouseWheeled) {
|
if (ev & kNtMouseWheeled) {
|
||||||
// scroll wheel (unnatural mode)
|
// scroll wheel (unnatural mode)
|
||||||
if (!(r->Event.MouseEvent.dwControlKeyState &
|
bool isup = ((int)r->Event.MouseEvent.dwButtonState >> 16) > 0;
|
||||||
(kNtShiftPressed | kNtLeftCtrlPressed | kNtRightCtrlPressed |
|
if (__ttyconf.magic & kTtyXtMouse) {
|
||||||
kNtLeftAltPressed | kNtRightAltPressed))) {
|
if (r->Event.MouseEvent.dwControlKeyState &
|
||||||
bool isup = ((int)r->Event.MouseEvent.dwButtonState >> 16) > 0;
|
(kNtLeftCtrlPressed | kNtRightCtrlPressed)) {
|
||||||
if (__ttyconf.magic & kTtyXtMouse) {
|
|
||||||
e = isup ? 80 : 81;
|
e = isup ? 80 : 81;
|
||||||
goto OutputXtermMouseEvent;
|
|
||||||
} else {
|
} else {
|
||||||
// we disable mouse highlighting when the tty is put in raw mode
|
e = isup ? 64 : 65;
|
||||||
// to mouse wheel events with widely understood vt100 arrow keys
|
}
|
||||||
*p++ = 033;
|
goto OutputXtermMouseEvent;
|
||||||
*p++ = !__keystroke.ohno_decckm ? '[' : 'O';
|
} else if (!(r->Event.MouseEvent.dwControlKeyState &
|
||||||
if (isup) {
|
(kNtShiftPressed | kNtLeftCtrlPressed | kNtRightCtrlPressed |
|
||||||
*p++ = 'A';
|
kNtLeftAltPressed | kNtRightAltPressed))) {
|
||||||
} else {
|
// we disable mouse highlighting when the tty is put in raw mode
|
||||||
*p++ = 'B';
|
// to mouse wheel events with widely understood vt100 arrow keys
|
||||||
}
|
*p++ = 033;
|
||||||
|
*p++ = !__keystroke.ohno_decckm ? '[' : 'O';
|
||||||
|
if (isup) {
|
||||||
|
*p++ = 'A';
|
||||||
|
} else {
|
||||||
|
*p++ = 'B';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ((bs || currentbs) && (__ttyconf.magic & kTtyXtMouse)) {
|
} else if ((bs || currentbs) && (__ttyconf.magic & kTtyXtMouse)) {
|
||||||
|
|
|
@ -19,11 +19,13 @@
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/struct/rlimit.internal.h"
|
#include "libc/calls/struct/rlimit.internal.h"
|
||||||
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/intrin/describeflags.internal.h"
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
|
#include "libc/runtime/syslib.internal.h"
|
||||||
#include "libc/sysv/consts/rlimit.h"
|
#include "libc/sysv/consts/rlimit.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
|
@ -79,6 +81,8 @@ int setrlimit(int resource, const struct rlimit *rlim) {
|
||||||
rc = einval();
|
rc = einval();
|
||||||
} else if (!rlim || (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim)))) {
|
} else if (!rlim || (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim)))) {
|
||||||
rc = efault();
|
rc = efault();
|
||||||
|
} else if (IsXnuSilicon()) {
|
||||||
|
rc = _sysret(__syslib->__setrlimit(resource, rlim));
|
||||||
} else if (!IsWindows()) {
|
} else if (!IsWindows()) {
|
||||||
rc = sys_setrlimit(resource, rlim);
|
rc = sys_setrlimit(resource, rlim);
|
||||||
if (IsXnu() && !rc && resource == RLIMIT_AS) {
|
if (IsXnu() && !rc && resource == RLIMIT_AS) {
|
||||||
|
|
|
@ -68,6 +68,8 @@ struct Syslib {
|
||||||
long (*__sem_post)(int *);
|
long (*__sem_post)(int *);
|
||||||
long (*__sem_wait)(int *);
|
long (*__sem_wait)(int *);
|
||||||
long (*__sem_trywait)(int *);
|
long (*__sem_trywait)(int *);
|
||||||
|
long (*__getrlimit)(int, void *);
|
||||||
|
long (*__setrlimit)(int, const void *);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct Syslib *__syslib;
|
extern struct Syslib *__syslib;
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
|
|
||||||
#define TLS_ALIGNMENT 64
|
#define TLS_ALIGNMENT 64
|
||||||
|
|
||||||
#define TIB_FLAG_VFORKED 1
|
#define TIB_FLAG_VFORKED 1
|
||||||
#define TIB_FLAG_WINCRASHING 2
|
|
||||||
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
|
@ -32,10 +32,6 @@
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
|
|
||||||
void SetUpOnce(void) {
|
|
||||||
if (!IsWindows()) _Exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnAlrm(int sig) {
|
void OnAlrm(int sig) {
|
||||||
// do nothing
|
// do nothing
|
||||||
STRACE("OnAlrm()");
|
STRACE("OnAlrm()");
|
||||||
|
|
108
test/libc/calls/stackoverflow1_test.c
Normal file
108
test/libc/calls/stackoverflow1_test.c
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/struct/rlimit.h"
|
||||||
|
#include "libc/calls/struct/sigaction.h"
|
||||||
|
#include "libc/calls/struct/sigaltstack.h"
|
||||||
|
#include "libc/calls/struct/siginfo.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "libc/limits.h"
|
||||||
|
#include "libc/mem/gc.internal.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/runtime/sysconf.h"
|
||||||
|
#include "libc/sysv/consts/rlimit.h"
|
||||||
|
#include "libc/sysv/consts/sa.h"
|
||||||
|
#include "libc/sysv/consts/sig.h"
|
||||||
|
#include "libc/sysv/consts/ss.h"
|
||||||
|
#include "libc/testlib/testlib.h"
|
||||||
|
#include "libc/thread/thread.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* stack overflow recovery technique #1
|
||||||
|
* overflow the gigantic main process stack
|
||||||
|
* simple but it can upset kernels / libraries
|
||||||
|
*/
|
||||||
|
|
||||||
|
jmp_buf recover;
|
||||||
|
volatile bool smashed_stack;
|
||||||
|
|
||||||
|
void CrashHandler(int sig, siginfo_t *si, void *ctx) {
|
||||||
|
struct sigaltstack ss;
|
||||||
|
ASSERT_SYS(0, 0, sigaltstack(0, &ss));
|
||||||
|
ASSERT_EQ(SS_ONSTACK, ss.ss_flags);
|
||||||
|
kprintf("kprintf avoids overflowing %G %p\n", si->si_signo, si->si_addr);
|
||||||
|
smashed_stack = true;
|
||||||
|
ASSERT_TRUE(__is_stack_overflow(si, ctx));
|
||||||
|
longjmp(recover, 123);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetUp(void) {
|
||||||
|
|
||||||
|
// tune down the main process's stack size to a reasonable amount
|
||||||
|
// some operating systems, e.g. freebsd, will do things like have
|
||||||
|
// 500mb RLIMIT_STACK by default, even on machines with 400mb RAM
|
||||||
|
struct rlimit rl = {2 * 1024 * 1024, 2 * 1024 * 1024};
|
||||||
|
if (!IsWindows() && !IsXnu()) {
|
||||||
|
ASSERT_SYS(0, 0, setrlimit(RLIMIT_STACK, &rl));
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up the signal handler and alternative stack
|
||||||
|
struct sigaction sa;
|
||||||
|
struct sigaltstack ss;
|
||||||
|
ss.ss_flags = 0;
|
||||||
|
ss.ss_size = sysconf(_SC_MINSIGSTKSZ) + 8192;
|
||||||
|
ss.ss_sp = _mapanon(ss.ss_size);
|
||||||
|
ASSERT_SYS(0, 0, sigaltstack(&ss, 0));
|
||||||
|
sa.sa_flags = SA_SIGINFO | SA_ONSTACK; // <-- important
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_sigaction = CrashHandler;
|
||||||
|
sigaction(SIGBUS, &sa, 0);
|
||||||
|
sigaction(SIGSEGV, &sa, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StackOverflow(int f(), int n) {
|
||||||
|
if (n < INT_MAX) {
|
||||||
|
return f(f, n + 1) - 1;
|
||||||
|
} else {
|
||||||
|
return INT_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int (*pStackOverflow)(int (*)(), int) = StackOverflow;
|
||||||
|
|
||||||
|
TEST(stackoverflow, standardStack_altStack_process_longjmp) {
|
||||||
|
if (IsTiny()) return; // TODO(jart): why?
|
||||||
|
|
||||||
|
int jumpcode;
|
||||||
|
if (!(jumpcode = setjmp(recover))) {
|
||||||
|
exit(pStackOverflow(pStackOverflow, 0));
|
||||||
|
}
|
||||||
|
ASSERT_EQ(123, jumpcode);
|
||||||
|
ASSERT_TRUE(smashed_stack);
|
||||||
|
|
||||||
|
// here's where longjmp() gets us into trouble
|
||||||
|
struct sigaltstack ss;
|
||||||
|
ASSERT_SYS(0, 0, sigaltstack(0, &ss));
|
||||||
|
if (IsXnu() || IsNetbsd()) {
|
||||||
|
ASSERT_EQ(SS_ONSTACK, ss.ss_flags); // wut
|
||||||
|
} else {
|
||||||
|
ASSERT_EQ(0, ss.ss_flags);
|
||||||
|
}
|
||||||
|
}
|
105
test/libc/calls/stackoverflow2_test.c
Normal file
105
test/libc/calls/stackoverflow2_test.c
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/struct/sigaction.h"
|
||||||
|
#include "libc/calls/struct/sigaltstack.h"
|
||||||
|
#include "libc/calls/struct/siginfo.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "libc/limits.h"
|
||||||
|
#include "libc/mem/gc.internal.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/runtime/sysconf.h"
|
||||||
|
#include "libc/sysv/consts/sa.h"
|
||||||
|
#include "libc/sysv/consts/sig.h"
|
||||||
|
#include "libc/sysv/consts/ss.h"
|
||||||
|
#include "libc/testlib/testlib.h"
|
||||||
|
#include "libc/thread/thread.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* stack overflow recovery technique #2
|
||||||
|
* longjmp out of signal back into thread
|
||||||
|
* simple but it can upset kernels / libraries
|
||||||
|
*/
|
||||||
|
|
||||||
|
jmp_buf recover;
|
||||||
|
volatile bool smashed_stack;
|
||||||
|
|
||||||
|
void CrashHandler(int sig, siginfo_t *si, void *ctx) {
|
||||||
|
struct sigaltstack ss;
|
||||||
|
ASSERT_SYS(0, 0, sigaltstack(0, &ss));
|
||||||
|
ASSERT_EQ(SS_ONSTACK, ss.ss_flags);
|
||||||
|
kprintf("kprintf avoids overflowing %G %p\n", si->si_signo, si->si_addr);
|
||||||
|
smashed_stack = true;
|
||||||
|
ASSERT_TRUE(__is_stack_overflow(si, ctx));
|
||||||
|
longjmp(recover, 123);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StackOverflow(int f(), int n) {
|
||||||
|
if (n < INT_MAX) {
|
||||||
|
return f(f, n + 1) - 1;
|
||||||
|
} else {
|
||||||
|
return INT_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int (*pStackOverflow)(int (*)(), int) = StackOverflow;
|
||||||
|
|
||||||
|
void *MyPosixThread(void *arg) {
|
||||||
|
int jumpcode;
|
||||||
|
struct sigaction sa, o1, o2;
|
||||||
|
struct sigaltstack ss;
|
||||||
|
ss.ss_flags = 0;
|
||||||
|
ss.ss_size = sysconf(_SC_MINSIGSTKSZ) + 4096;
|
||||||
|
ss.ss_sp = gc(malloc(ss.ss_size));
|
||||||
|
ASSERT_SYS(0, 0, sigaltstack(&ss, 0));
|
||||||
|
sa.sa_flags = SA_SIGINFO | SA_ONSTACK; // <-- important
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_sigaction = CrashHandler;
|
||||||
|
sigaction(SIGBUS, &sa, &o1);
|
||||||
|
sigaction(SIGSEGV, &sa, &o2);
|
||||||
|
if (!(jumpcode = setjmp(recover))) {
|
||||||
|
exit(pStackOverflow(pStackOverflow, 0));
|
||||||
|
}
|
||||||
|
ASSERT_EQ(123, jumpcode);
|
||||||
|
sigaction(SIGSEGV, &o2, 0);
|
||||||
|
sigaction(SIGBUS, &o1, 0);
|
||||||
|
// here's where longjmp() gets us into trouble
|
||||||
|
ASSERT_SYS(0, 0, sigaltstack(0, &ss));
|
||||||
|
if (IsXnu() || IsNetbsd()) {
|
||||||
|
ASSERT_EQ(SS_ONSTACK, ss.ss_flags); // wut
|
||||||
|
} else {
|
||||||
|
ASSERT_EQ(0, ss.ss_flags);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(stackoverflow, standardStack_altStack_thread_longjmp) {
|
||||||
|
pthread_t th;
|
||||||
|
struct sigaltstack ss;
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
smashed_stack = false;
|
||||||
|
pthread_create(&th, 0, MyPosixThread, 0);
|
||||||
|
pthread_join(th, 0);
|
||||||
|
ASSERT_TRUE(smashed_stack);
|
||||||
|
// this should be SS_DISABLE but ShowCrashReports() creates an alt stack
|
||||||
|
ASSERT_SYS(0, 0, sigaltstack(0, &ss));
|
||||||
|
ASSERT_EQ(0, ss.ss_flags);
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,10 +31,9 @@
|
||||||
#include "libc/x/x.h"
|
#include "libc/x/x.h"
|
||||||
#include "third_party/libcxx/math.h"
|
#include "third_party/libcxx/math.h"
|
||||||
|
|
||||||
#if 0 // TODO(jart): fix me
|
|
||||||
|
|
||||||
bool gotsome;
|
bool gotsome;
|
||||||
ucontext_t uc, goback;
|
ucontext_t uc, goback;
|
||||||
|
extern long __klog_handle;
|
||||||
|
|
||||||
void SetUpOnce(void) {
|
void SetUpOnce(void) {
|
||||||
testlib_enable_tmp_setup_teardown();
|
testlib_enable_tmp_setup_teardown();
|
||||||
|
@ -90,18 +89,17 @@ TEST(makecontext, backtrace) {
|
||||||
SPAWN(fork);
|
SPAWN(fork);
|
||||||
ASSERT_SYS(0, 0, close(2));
|
ASSERT_SYS(0, 0, close(2));
|
||||||
ASSERT_SYS(0, 2, creat("log", 0644));
|
ASSERT_SYS(0, 2, creat("log", 0644));
|
||||||
|
__klog_handle = 2;
|
||||||
getcontext(&uc);
|
getcontext(&uc);
|
||||||
uc.uc_link = 0;
|
uc.uc_link = 0;
|
||||||
uc.uc_stack.ss_sp = NewCosmoStack();
|
uc.uc_stack.ss_sp = NewCosmoStack();
|
||||||
uc.uc_stack.ss_size = GetStackSize();
|
uc.uc_stack.ss_size = GetStackSize();
|
||||||
makecontext(&uc, itsatrap, 2, 123, 456);
|
makecontext(&uc, itsatrap, 2, 123, 456);
|
||||||
setcontext(&uc);
|
setcontext(&uc);
|
||||||
EXITS(128 + SIGSEGV);
|
TERMS(SIGSEGV);
|
||||||
if (!GetSymbolTable()) return;
|
if (!GetSymbolTable()) return;
|
||||||
char *log = gc(xslurp("log", 0));
|
char *log = gc(xslurp("log", 0));
|
||||||
EXPECT_NE(0, strstr(log, "itsatrap"));
|
EXPECT_NE(0, strstr(log, "itsatrap"));
|
||||||
EXPECT_NE(0, strstr(log, "runcontext"));
|
EXPECT_NE(0, strstr(log, "runcontext"));
|
||||||
EXPECT_NE(0, strstr(log, "makecontext_backtrace"));
|
EXPECT_NE(0, strstr(log, "makecontext_backtrace"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
Loading…
Reference in a new issue