1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
| #![no_std]
#![no_main]
#![feature(custom_test_frameworks)]
#![test_runner(rustbelt::test_runner)]
#![reexport_test_harness_main = "test_main"]
extern crate alloc;
use bootloader::{BootInfo, entry_point};
use core::panic::PanicInfo;
use core::sync::atomic::{AtomicBool, Ordering};
use rustbelt::process::{self, ExitStatus, SpawnArgs};
use rustbelt::stack::{self, KernelStack, STACK_SIZE};
use rustbelt::{fs, memory, thread};
entry_point!(main);
fn main(boot_info: &'static BootInfo) -> ! {
rustbelt::init();
rustbelt::init_memory(boot_info);
rustbelt::init_smp();
fs::init();
rustbelt::init_storage();
test_main();
rustbelt::hlt_loop();
}
#[test_case]
fn guard_page_sits_right_below_each_kernel_stack() {
let s = KernelStack::new().expect("no stack");
assert_eq!(s.top() - s.bottom(), STACK_SIZE);
assert_eq!(s.guard_page(), s.bottom() - 4096);
assert!(stack::is_guard_page(s.guard_page()));
assert!(stack::is_guard_page(s.bottom() - 1));
assert!(!stack::is_guard_page(s.bottom()));
assert!(!stack::is_guard_page(s.top() - 8));
}
#[test_case]
fn user_stack_guard_zone_bounds() {
let stack_bottom = process::USER_STACK_TOP - process::USER_STACK_SIZE;
assert!(process::in_user_stack_guard(stack_bottom - 1));
assert!(process::in_user_stack_guard(process::USER_STACK_ZONE_START));
assert!(!process::in_user_stack_guard(stack_bottom));
assert!(!process::in_user_stack_guard(process::USER_STACK_ZONE_START - 1));
}
static REACHED_END: AtomicBool = AtomicBool::new(false);
#[allow(unconditional_recursion)]
fn recurse(depth: u64) -> u64 {
let buf = core::hint::black_box([depth as u8; 256]);
recurse(depth + 1) + buf[0] as u64
}
fn overflowing_thread() {
recurse(0);
REACHED_END.store(true, Ordering::Relaxed);
}
#[test_case]
fn kernel_stack_overflow_kills_only_that_thread() {
let frames = memory::frames_in_use();
let stacks = stack::live_stacks();
let caught = thread::stack_overflows();
for _ in 0..3 {
let id = thread::spawn("recurser", overflowing_thread);
thread::join(id);
}
assert!(!REACHED_END.load(Ordering::Relaxed));
assert_eq!(thread::stack_overflows(), caught + 3);
assert_eq!(stack::live_stacks(), stacks);
assert_eq!(memory::frames_in_use(), frames);
}
#[test_case]
fn user_stack_overflow_kills_the_process() {
let run = || {
let spawn = SpawnArgs::kernel("overflow");
let p = process::spawn_path("/mnt/disk0/bin/overflow", spawn).expect("spawn failed");
process::wait(&p)
};
assert_eq!(run(), ExitStatus::Killed(rustbelt::signal::SIGSEGV, "stack overflow")); let frames = memory::frames_in_use();
assert_eq!(run(), ExitStatus::Killed(rustbelt::signal::SIGSEGV, "stack overflow"));
assert_eq!(memory::frames_in_use(), frames);
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
rustbelt::test_panic_handler(info)
}
|