1
#include <arch/signal.h>
2
3
#include "internal.h"
4
5
static bool ctx_stack_valid(const sched_thread_t *thread, size_t need_bytes) {
6
if (!thread || !thread->context || !thread->stack || !thread->stack_size) {
7
return false;
8
}9
10
uintptr_t stack_base = (uintptr_t)thread->stack;
11
uintptr_t stack_end = stack_base + thread->stack_size;
12
uintptr_t ctx = thread->context;
13
14
if (ctx < stack_base || ctx >= stack_end) {
15
return false;
16
}17
18
size_t available = (size_t)(stack_end - ctx);
19
return need_bytes <= available;
20
}21
22
bool ctx_candidate_valid(const sched_thread_t *thread, const arch_int_state_t *state) {
23
if (!thread || !state || !thread->stack || !thread->stack_size) {
24
return false;
25
}26
27
uintptr_t ctx = (uintptr_t)state;
28
uintptr_t stack_base = (uintptr_t)thread->stack;
29
uintptr_t stack_end = stack_base + thread->stack_size;
30
31
if (stack_end < stack_base || ctx < stack_base || ctx >= stack_end) {
32
return false;
33
}34
35
size_t sregs_off = offsetof(arch_int_state_t, s_regs);
36
size_t kernel_frame_need = sregs_off + (3U * sizeof(arch_word_t));
37
38
if ((size_t)(stack_end - ctx) < kernel_frame_need) {
39
return false;
40
}41
42
if (!arch_signal_is_user(state)) {
43
return true;
44
}45
46
size_t user_frame_need = sregs_off + sizeof(state->s_regs);
47
48
if ((size_t)(stack_end - ctx) < user_frame_need) {
49
return false;
50
}51
52
return true;
53
}54
55
bool ctx_valid(const sched_thread_t *thread) {
56
if (!thread || !thread->context) {
57
return false;
58
}59
60
const arch_int_state_t *state = (const arch_int_state_t *)thread->context;
61
size_t sregs_off = offsetof(arch_int_state_t, s_regs);
62
size_t kernel_frame_need = sregs_off + (3U * sizeof(arch_word_t));
63
64
if (!ctx_stack_valid(thread, kernel_frame_need)) {
65
return false;
66
}67
68
bool user_frame = arch_signal_is_user(state);
69
arch_word_t ip = arch_state_ip(state);
70
71
if (!ip) {
72
return false;
73
}74
75
if (!user_frame && arch_kernel_vaddr_base() && ip < arch_kernel_vaddr_base()) {
76
return false;
77
}78
79
if (user_frame) {
80
if (!thread->user_thread) {
81
return false;
82
}83
84
size_t user_frame_need = sregs_off + sizeof(state->s_regs);
85
if (!ctx_stack_valid(thread, user_frame_need)) {
86
return false;
87
}88
89
arch_word_t sp = arch_state_sp(state);
90
91
if (!sp) {
92
return false;
93
}94
95
if (!arch_state_flags_sane(state)) {
96
return false;
97
}98
99
arch_word_t user_top = arch_user_stack_top();
100
if (user_top && (ip >= user_top || sp > user_top)) {
101
return false;
102
}103
104
if (thread->user_stack_base && thread->user_stack_size) {
105
arch_word_t user_base = (arch_word_t)thread->user_stack_base;
106
arch_word_t user_end = user_base + (arch_word_t)thread->user_stack_size;
107
108
if (user_end < user_base || sp < user_base || sp > user_end) {
109
return false;
110
}111
}112
}113
114
return true;
115
}