diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2026-04-25 09:49:08 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2026-04-27 03:23:19 +0000 |
| commit | bd8edba0792b71be3f8ed5dea9c22287e95c986a (patch) | |
| tree | dd0c4e40bf4da138adadccce7f03142f89688e6c | |
| parent | 912f9dfca451e359dda7cdf45539b7c19764f54d (diff) | |
amd64 ia32_syscall(): only allow for ILP32 processes
64bit processes can issue INT $0x80 instruction, and get the syscall
dispatched through ia32_syscall(). This works because syscall argument
fetch and result return are selected from the process sysent.
But, ia32_syscall() does not verify some conditions and does not perform
some actions which are considered unnecessary because the caller is
supposed to only access lower 4G. The INT syscall path breaks this
assumption.
We never supported such hack, so disable it. Send the offending thread
SIGBUS as if #GP was issued by hardware due to IDT vector 0x80 having
not numerically high enough DPL value.
Reviewed by: markj
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D56630
| -rw-r--r-- | sys/amd64/ia32/ia32_syscall.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c index 85e3d8f8e920..edafb753faa0 100644 --- a/sys/amd64/ia32/ia32_syscall.c +++ b/sys/amd64/ia32/ia32_syscall.c @@ -218,6 +218,15 @@ ia32_syscall(struct trapframe *frame) orig_tf_rflags = frame->tf_rflags; td = curthread; td->td_frame = frame; + if (__predict_false(SV_PROC_FLAG(td->td_proc, SV_ILP32) == 0)) { + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_code = BUS_OBJERR; + ksi.ksi_addr = (void *)frame->tf_rip; + trapsignal(td, &ksi); + userret(td, td->td_frame); + return; + } syscallenter(td); |
