git: 5bc997b6f5b1 - main - amd64: do not allow to set IOPL to 3 when FRED is used
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 27 Oct 2026 12:01:18 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=5bc997b6f5b1265ff28d11405eb980bf471c3db4
commit 5bc997b6f5b1265ff28d11405eb980bf471c3db4
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-10-27 09:10:09 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-10-27 11:58:48 +0000
amd64: do not allow to set IOPL to 3 when FRED is used
SDM requires that IOPL is zero when returning to usermode with ERETU.
Do not set rflags.iopl for FreeBSD io(4) open.
This might be changed to disallow io(4) open for FRED at all with a
knob, if there is a real need.
Return ENOSYS from linux iopl(2), apparently Linux kernel can be
configured without iopl(2) support, so linux programs should be prepared
for this error.
Return EINVAL from vt(4)/syscons(4) ioctl(KDENABIO).
Fixes: 6e93f5e4d693 ("amd64: FRED support")
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
---
sys/amd64/amd64/io.c | 16 ++++++++++++----
sys/amd64/linux/linux_machdep.c | 3 +++
sys/amd64/linux32/linux32_machdep.c | 3 +++
sys/dev/syscons/syscons.c | 3 +++
sys/dev/vt/vt_core.c | 3 +++
5 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/sys/amd64/amd64/io.c b/sys/amd64/amd64/io.c
index 6c36d5fb20e1..ba34675c0cc5 100644
--- a/sys/amd64/amd64/io.c
+++ b/sys/amd64/amd64/io.c
@@ -31,21 +31,29 @@
#include <machine/frame.h>
#include <machine/iodev.h>
+#include <machine/md_var.h>
#include <machine/psl.h>
int
iodev_open(struct thread *td)
{
-
- td->td_frame->tf_rflags |= PSL_IOPL;
+ /*
+ * SDM rev. 93 vol.3 8.4.2.1 Loading and Checking the Return State:
+ * Checking IOPL ensures that, when FRED transitions are
+ * enabled, IOPL is always 0 when CPL = 3.
+ *
+ * As result, io(4) cannot enable the IOPL for usermode on FRED.
+ */
+ if (!fred)
+ td->td_frame->tf_rflags |= PSL_IOPL;
return (0);
}
int
iodev_close(struct thread *td)
{
-
- td->td_frame->tf_rflags &= ~PSL_IOPL;
+ if (!fred)
+ td->td_frame->tf_rflags &= ~PSL_IOPL;
return (0);
}
diff --git a/sys/amd64/linux/linux_machdep.c b/sys/amd64/linux/linux_machdep.c
index dc7f55f6f198..e22a3ed22c31 100644
--- a/sys/amd64/linux/linux_machdep.c
+++ b/sys/amd64/linux/linux_machdep.c
@@ -88,6 +88,9 @@ linux_iopl(struct thread *td, struct linux_iopl_args *args)
return (error);
if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
return (error);
+ /* See comment in sys/amd64/amd64/io.c. */
+ if (fred && args->level != 0)
+ return (ENOSYS);
td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) |
(args->level * (PSL_IOPL / 3));
diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c
index a9517b42a4d9..a62965308c33 100644
--- a/sys/amd64/linux32/linux32_machdep.c
+++ b/sys/amd64/linux32/linux32_machdep.c
@@ -332,6 +332,9 @@ linux_iopl(struct thread *td, struct linux_iopl_args *args)
return (error);
if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
return (error);
+ /* See comment in sys/amd64/amd64/io.c. */
+ if (fred && args->level != 0)
+ return (ENOSYS);
td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) |
(args->level * (PSL_IOPL / 3));
diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c
index 9167da23efd8..06e3c498ddd6 100644
--- a/sys/dev/syscons/syscons.c
+++ b/sys/dev/syscons/syscons.c
@@ -72,6 +72,7 @@
#if defined(__i386__) || defined(__amd64__)
#include <machine/psl.h>
#include <machine/frame.h>
+#include <machine/md_var.h>
#endif
#if defined(__amd64__) || defined(__i386__)
@@ -1338,6 +1339,8 @@ sctty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
#ifdef __i386__
td->td_frame->tf_eflags |= PSL_IOPL;
#elif defined(__amd64__)
+ if (fred)
+ return (EINVAL);
td->td_frame->tf_rflags |= PSL_IOPL;
#endif
return 0;
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c
index 0ea2ec58f4cc..909ee3b8689d 100644
--- a/sys/dev/vt/vt_core.c
+++ b/sys/dev/vt/vt_core.c
@@ -61,6 +61,7 @@
#if defined(__i386__) || defined(__amd64__)
#include <machine/psl.h>
#include <machine/frame.h>
+#include <machine/md_var.h>
#endif
static int vtterm_cngrab_noswitch(struct vt_device *, struct vt_window *);
@@ -2971,6 +2972,8 @@ skip_thunk:
#if defined(__i386__)
td->td_frame->tf_eflags |= PSL_IOPL;
#elif defined(__amd64__)
+ if (fred)
+ return (EINVAL);
td->td_frame->tf_rflags |= PSL_IOPL;
#endif
return (0);