1 // SPDX-License-Identifier: GPL-2.0
3 * iopl.c - Test case for a Linux on Xen 64-bit bug
4 * Copyright (c) 2015 Andrew Lutomirski
17 #include <sys/types.h>
25 static void sethandler(int sig
, void (*handler
)(int, siginfo_t
*, void *),
29 memset(&sa
, 0, sizeof(sa
));
30 sa
.sa_sigaction
= handler
;
31 sa
.sa_flags
= SA_SIGINFO
| flags
;
32 sigemptyset(&sa
.sa_mask
);
33 if (sigaction(sig
, &sa
, 0))
38 static jmp_buf jmpbuf
;
40 static void sigsegv(int sig
, siginfo_t
*si
, void *ctx_void
)
42 siglongjmp(jmpbuf
, 1);
50 if (sched_setaffinity(0, sizeof(cpuset
), &cpuset
) != 0)
51 err(1, "sched_setaffinity to CPU 0");
53 /* Probe for iopl support. Note that iopl(0) works even as nonroot. */
55 printf("[OK]\tiopl(3) failed (%d) -- try running as root\n",
60 /* Restore our original state prior to starting the test. */
69 printf("\tchild: set IOPL to 3\n");
73 printf("[RUN]\tchild: write to 0x80\n");
74 asm volatile ("outb %%al, $0x80" : : "a" (0));
79 if (waitpid(child
, &status
, 0) != child
||
81 printf("[FAIL]\tChild died\n");
83 } else if (WEXITSTATUS(status
) != 0) {
84 printf("[FAIL]\tChild failed\n");
87 printf("[OK]\tChild succeeded\n");
91 printf("[RUN]\tparent: write to 0x80 (should fail)\n");
93 sethandler(SIGSEGV
, sigsegv
, 0);
94 if (sigsetjmp(jmpbuf
, 1) != 0) {
95 printf("[OK]\twrite was denied\n");
97 asm volatile ("outb %%al, $0x80" : : "a" (0));
98 printf("[FAIL]\twrite was allowed\n");
102 /* Test the capability checks. */
103 printf("\tiopl(3)\n");
107 printf("\tDrop privileges\n");
108 if (setresuid(1, 1, 1) != 0) {
109 printf("[WARN]\tDropping privileges failed\n");
113 printf("[RUN]\tiopl(3) unprivileged but with IOPL==3\n");
115 printf("[FAIL]\tiopl(3) should work if iopl is already 3 even if unprivileged\n");
119 printf("[RUN]\tiopl(0) unprivileged\n");
121 printf("[FAIL]\tiopl(0) should work if iopl is already 3 even if unprivileged\n");
125 printf("[RUN]\tiopl(3) unprivileged\n");
127 printf("[FAIL]\tiopl(3) should fail if when unprivileged if iopl==0\n");
130 printf("[OK]\tFailed as expected\n");
134 return nerrs
? 1 : 0;