2 * iopl.c - Test case for a Linux on Xen 64-bit bug
3 * Copyright (c) 2015 Andrew Lutomirski
16 #include <sys/types.h>
24 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
28 memset(&sa, 0, sizeof(sa));
29 sa.sa_sigaction = handler;
30 sa.sa_flags = SA_SIGINFO | flags;
31 sigemptyset(&sa.sa_mask);
32 if (sigaction(sig, &sa, 0))
37 static jmp_buf jmpbuf;
39 static void sigsegv(int sig, siginfo_t *si, void *ctx_void)
41 siglongjmp(jmpbuf, 1);
49 if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
50 err(1, "sched_setaffinity to CPU 0");
52 /* Probe for iopl support. Note that iopl(0) works even as nonroot. */
54 printf("[OK]\tiopl(3) failed (%d) -- try running as root\n",
59 /* Restore our original state prior to starting the test. */
68 printf("\tchild: set IOPL to 3\n");
72 printf("[RUN]\tchild: write to 0x80\n");
73 asm volatile ("outb %%al, $0x80" : : "a" (0));
78 if (waitpid(child, &status, 0) != child ||
80 printf("[FAIL]\tChild died\n");
82 } else if (WEXITSTATUS(status) != 0) {
83 printf("[FAIL]\tChild failed\n");
86 printf("[OK]\tChild succeeded\n");
90 printf("[RUN]\tparent: write to 0x80 (should fail)\n");
92 sethandler(SIGSEGV, sigsegv, 0);
93 if (sigsetjmp(jmpbuf, 1) != 0) {
94 printf("[OK]\twrite was denied\n");
96 asm volatile ("outb %%al, $0x80" : : "a" (0));
97 printf("[FAIL]\twrite was allowed\n");
101 /* Test the capability checks. */
102 printf("\tiopl(3)\n");
106 printf("\tDrop privileges\n");
107 if (setresuid(1, 1, 1) != 0) {
108 printf("[WARN]\tDropping privileges failed\n");
112 printf("[RUN]\tiopl(3) unprivileged but with IOPL==3\n");
114 printf("[FAIL]\tiopl(3) should work if iopl is already 3 even if unprivileged\n");
118 printf("[RUN]\tiopl(0) unprivileged\n");
120 printf("[FAIL]\tiopl(0) should work if iopl is already 3 even if unprivileged\n");
124 printf("[RUN]\tiopl(3) unprivileged\n");
126 printf("[FAIL]\tiopl(3) should fail if when unprivileged if iopl==0\n");
129 printf("[OK]\tFailed as expected\n");
133 return nerrs ? 1 : 0;