|
7 | 7 | * This is the beating heart of kbox: every file open, read, write, stat, and |
8 | 8 | * directory operation the tracee makes gets routed through here. |
9 | 9 | * |
| 10 | + * Single-threaded dispatch contract |
| 11 | + * ---------------------------------- |
| 12 | + * All notification processing runs on a single thread (supervisor loop in |
| 13 | + * seccomp mode, SIGSYS handler in trap/rewrite mode). The following state is |
| 14 | + * protected only by this single-threaded invariant: |
| 15 | + * |
| 16 | + * dispatch_scratch[] Static I/O buffer (this file). |
| 17 | + * kbox_fd_table entries FD table (fd-table.c). |
| 18 | + * Path scratch buffers Translation/literal caches (path.c). |
| 19 | + * shadow_sockets[] SLIRP socket array (net-slirp.c). |
| 20 | + * saved_guest_segv/bus Fault handler saved actions (procmem.c). |
| 21 | + * fault_armed Thread-local; single-threaded guest means |
| 22 | + * only one thread ever arms it. |
| 23 | + * |
| 24 | + * If parallel dispatch or multi-threaded guest support is introduced, |
| 25 | + * every item above needs locking or per-thread allocation. |
10 | 26 | */ |
11 | 27 |
|
12 | 28 | #include <errno.h> |
@@ -126,6 +142,9 @@ static struct kbox_dispatch emulate_trap_rt_sigprocmask( |
126 | 142 | unsigned char set_mask[sizeof(sigset_t)]; |
127 | 143 | size_t mask_len; |
128 | 144 |
|
| 145 | + memset(current, 0, sizeof(current)); |
| 146 | + memset(next, 0, sizeof(next)); |
| 147 | + |
129 | 148 | if (sigset_size == 0 || sigset_size > sizeof(current)) |
130 | 149 | return kbox_dispatch_errno(EINVAL); |
131 | 150 | mask_len = sigset_size; |
@@ -153,8 +172,15 @@ static struct kbox_dispatch emulate_trap_rt_sigprocmask( |
153 | 172 | } |
154 | 173 |
|
155 | 174 | if (old_ptr != 0) { |
| 175 | + /* Strip SIGSYS from the reported mask -- the guest must not |
| 176 | + * observe kbox's reserved signal in its signal state. |
| 177 | + */ |
| 178 | + unsigned char visible[sizeof(sigset_t)]; |
| 179 | + |
| 180 | + memcpy(visible, current, sizeof(visible)); |
| 181 | + kbox_syscall_trap_sigset_strip_reserved(visible, sizeof(visible)); |
156 | 182 | int rc = guest_mem_write(ctx, kbox_syscall_request_pid(req), old_ptr, |
157 | | - current, mask_len); |
| 183 | + visible, mask_len); |
158 | 184 | if (rc < 0) |
159 | 185 | return kbox_dispatch_errno(-rc); |
160 | 186 | } |
@@ -213,15 +239,18 @@ static struct kbox_dispatch emulate_trap_rt_sigpending( |
213 | 239 | unsigned char pending[sizeof(sigset_t)]; |
214 | 240 | int rc; |
215 | 241 |
|
216 | | - (void) ctx; |
217 | | - |
218 | 242 | if (set_ptr == 0) |
219 | 243 | return kbox_dispatch_errno(EFAULT); |
220 | 244 | if (sigset_size == 0 || sigset_size > sizeof(pending)) |
221 | 245 | return kbox_dispatch_errno(EINVAL); |
222 | 246 | if (kbox_syscall_trap_get_pending(pending, sizeof(pending)) < 0) |
223 | 247 | return kbox_dispatch_errno(EIO); |
224 | 248 |
|
| 249 | + /* Strip SIGSYS from pending set -- the guest must not observe |
| 250 | + * kbox's reserved signal as pending. |
| 251 | + */ |
| 252 | + kbox_syscall_trap_sigset_strip_reserved(pending, sizeof(pending)); |
| 253 | + |
225 | 254 | rc = guest_mem_write(ctx, kbox_syscall_request_pid(req), set_ptr, pending, |
226 | 255 | sigset_size); |
227 | 256 | if (rc < 0) |
@@ -4405,7 +4434,17 @@ struct kbox_dispatch kbox_dispatch_request( |
4405 | 4434 | return kbox_dispatch_value(0); |
4406 | 4435 | } |
4407 | 4436 |
|
4408 | | - /* Signals. */ |
| 4437 | + /* Signals. |
| 4438 | + * |
| 4439 | + * rt_sigaction: only SIGSYS is denied (reserved for trap mode). |
| 4440 | + * All other signals -- including SIGURG (Go async preemption), |
| 4441 | + * SIGUSR1/2, SIGALRM, etc. -- pass through to the host kernel |
| 4442 | + * via CONTINUE. SIGSEGV/SIGBUS changes bump the fault handler |
| 4443 | + * generation counter so procmem.c reinstalls its handler. |
| 4444 | + * |
| 4445 | + * rt_sigprocmask: in trap/rewrite mode, emulated to keep the |
| 4446 | + * supervisor's SIGSYS unblocked. In seccomp mode, CONTINUE. |
| 4447 | + */ |
4409 | 4448 |
|
4410 | 4449 | if (nr == h->rt_sigaction) { |
4411 | 4450 | if (request_uses_trap_signals(req) && |
|
0 commit comments