@@ -35,32 +35,145 @@ static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
35
35
36
36
}
37
37
38
+ static void clearhandler (int sig )
39
+ {
40
+ struct sigaction sa ;
41
+ memset (& sa , 0 , sizeof (sa ));
42
+ sa .sa_handler = SIG_DFL ;
43
+ sigemptyset (& sa .sa_mask );
44
+ if (sigaction (sig , & sa , 0 ))
45
+ err (1 , "sigaction" );
46
+ }
47
+
38
48
static jmp_buf jmpbuf ;
39
49
40
50
static void sigsegv (int sig , siginfo_t * si , void * ctx_void )
41
51
{
42
52
siglongjmp (jmpbuf , 1 );
43
53
}
44
54
55
+ static bool try_outb (unsigned short port )
56
+ {
57
+ sethandler (SIGSEGV , sigsegv , SA_RESETHAND );
58
+ if (sigsetjmp (jmpbuf , 1 ) != 0 ) {
59
+ return false;
60
+ } else {
61
+ asm volatile ("outb %%al, %w[port]"
62
+ : : [port ] "Nd" (port ), "a" (0 ));
63
+ return true;
64
+ }
65
+ clearhandler (SIGSEGV );
66
+ }
67
+
68
+ static void expect_ok_outb (unsigned short port )
69
+ {
70
+ if (!try_outb (port )) {
71
+ printf ("[FAIL]\toutb to 0x%02hx failed\n" , port );
72
+ exit (1 );
73
+ }
74
+
75
+ printf ("[OK]\toutb to 0x%02hx worked\n" , port );
76
+ }
77
+
78
+ static void expect_gp_outb (unsigned short port )
79
+ {
80
+ if (try_outb (port )) {
81
+ printf ("[FAIL]\toutb to 0x%02hx worked\n" , port );
82
+ nerrs ++ ;
83
+ }
84
+
85
+ printf ("[OK]\toutb to 0x%02hx failed\n" , port );
86
+ }
87
+
88
+ static bool try_cli (void )
89
+ {
90
+ sethandler (SIGSEGV , sigsegv , SA_RESETHAND );
91
+ if (sigsetjmp (jmpbuf , 1 ) != 0 ) {
92
+ return false;
93
+ } else {
94
+ asm volatile ("cli" );
95
+ return true;
96
+ }
97
+ clearhandler (SIGSEGV );
98
+ }
99
+
100
+ static bool try_sti (void )
101
+ {
102
+ sethandler (SIGSEGV , sigsegv , SA_RESETHAND );
103
+ if (sigsetjmp (jmpbuf , 1 ) != 0 ) {
104
+ return false;
105
+ } else {
106
+ asm volatile ("sti" );
107
+ return true;
108
+ }
109
+ clearhandler (SIGSEGV );
110
+ }
111
+
112
+ static void expect_gp_sti (void )
113
+ {
114
+ if (try_sti ()) {
115
+ printf ("[FAIL]\tSTI worked\n" );
116
+ nerrs ++ ;
117
+ } else {
118
+ printf ("[OK]\tSTI faulted\n" );
119
+ }
120
+ }
121
+
122
+ static void expect_gp_cli (void )
123
+ {
124
+ if (try_cli ()) {
125
+ printf ("[FAIL]\tCLI worked\n" );
126
+ nerrs ++ ;
127
+ } else {
128
+ printf ("[OK]\tCLI faulted\n" );
129
+ }
130
+ }
131
+
45
132
int main (void )
46
133
{
47
134
cpu_set_t cpuset ;
135
+
48
136
CPU_ZERO (& cpuset );
49
137
CPU_SET (0 , & cpuset );
50
138
if (sched_setaffinity (0 , sizeof (cpuset ), & cpuset ) != 0 )
51
139
err (1 , "sched_setaffinity to CPU 0" );
52
140
53
141
/* Probe for iopl support. Note that iopl(0) works even as nonroot. */
54
- if (iopl (3 ) != 0 ) {
142
+ switch (iopl (3 )) {
143
+ case 0 :
144
+ break ;
145
+ case - ENOSYS :
146
+ printf ("[OK]\tiopl() nor supported\n" );
147
+ return 0 ;
148
+ default :
55
149
printf ("[OK]\tiopl(3) failed (%d) -- try running as root\n" ,
56
150
errno );
57
151
return 0 ;
58
152
}
59
153
60
- /* Restore our original state prior to starting the test. */
154
+ /* Make sure that CLI/STI are blocked even with IOPL level 3 */
155
+ expect_gp_cli ();
156
+ expect_gp_sti ();
157
+ expect_ok_outb (0x80 );
158
+
159
+ /* Establish an I/O bitmap to test the restore */
160
+ if (ioperm (0x80 , 1 , 1 ) != 0 )
161
+ err (1 , "ioperm(0x80, 1, 1) failed\n" );
162
+
163
+ /* Restore our original state prior to starting the fork test. */
61
164
if (iopl (0 ) != 0 )
62
165
err (1 , "iopl(0)" );
63
166
167
+ /*
168
+ * Verify that IOPL emulation is disabled and the I/O bitmap still
169
+ * works.
170
+ */
171
+ expect_ok_outb (0x80 );
172
+ expect_gp_outb (0xed );
173
+ /* Drop the I/O bitmap */
174
+ if (ioperm (0x80 , 1 , 0 ) != 0 )
175
+ err (1 , "ioperm(0x80, 1, 0) failed\n" );
176
+
64
177
pid_t child = fork ();
65
178
if (child == -1 )
66
179
err (1 , "fork" );
@@ -90,14 +203,9 @@ int main(void)
90
203
91
204
printf ("[RUN]\tparent: write to 0x80 (should fail)\n" );
92
205
93
- sethandler (SIGSEGV , sigsegv , 0 );
94
- if (sigsetjmp (jmpbuf , 1 ) != 0 ) {
95
- printf ("[OK]\twrite was denied\n" );
96
- } else {
97
- asm volatile ("outb %%al, $0x80" : : "a" (0 ));
98
- printf ("[FAIL]\twrite was allowed\n" );
99
- nerrs ++ ;
100
- }
206
+ expect_gp_outb (0x80 );
207
+ expect_gp_cli ();
208
+ expect_gp_sti ();
101
209
102
210
/* Test the capability checks. */
103
211
printf ("\tiopl(3)\n" );
@@ -133,4 +241,3 @@ int main(void)
133
241
done :
134
242
return nerrs ? 1 : 0 ;
135
243
}
136
-
0 commit comments