1#!/bin/sh 2 3# 4# Copyright (c) 2009 Peter Holm <pho@FreeBSD.org> 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29# Test the amd64 implementation of: 30# 1. Per-process private ldt and corresponding i386 arch syscalls. 31# 2. Per-process private io permission bitmap and corresponding 32# i386 arch syscalls. 33# 3. Sigcontext 34 35# The tests must be compiled on i386 and run on amd64 36 37# All tests by kib@ 38 39[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 40 41. ../default.cfg 42 43cd /tmp 44if [ "`uname -p`" = "i386" ]; then 45 cat > ldt.c <<EOF 46/* \$Id: ldt.c,v 1.8 2008/11/01 21:14:59 kostik Exp kostik \$ */ 47 48#include <sys/param.h> 49#include <sys/types.h> 50#include <sys/wait.h> 51#include <machine/segments.h> 52#include <machine/sysarch.h> 53#include <errno.h> 54#include <inttypes.h> 55#include <signal.h> 56#include <stdio.h> 57#include <string.h> 58#include <unistd.h> 59 60char stack[64 * 1024]; 61 62char a[1]; 63 64int 65s2ds(int sel) 66{ 67 68 return (LSEL(sel, SEL_UPL)); 69} 70 71unsigned char 72readbyte(int sel, int offset) 73{ 74 unsigned char res; 75 76 __asm__ volatile( 77 "\tpushl %%es\n" 78 "\tmovl %1,%%es\n" 79 "\tmovb %%es:(%2),%0\n" 80 "\tpopl %%es\n" 81 : "=r"(res) : "r"(s2ds(sel)), "r"(offset)); 82 83 return (res); 84} 85 86void 87writebyte(int sel, int offset, unsigned char val) 88{ 89 90 __asm__ volatile( 91 "\tpushl %%es\n" 92 "\tmovl %0,%%es\n" 93 "\tmovb %2,%%es:(%1)\n" 94 "\tpopl %%es\n" 95 : : "r"(s2ds(sel)), "r"(offset), "r"(val) : "memory"); 96} 97 98int 99alloc_sel(char *base, size_t len, int type, int p) 100{ 101 int sel; 102 union descriptor descs[1], descsk[1]; 103 uintptr_t pb; 104 105 memset(descs, 0, sizeof(descs)); 106 if (len > PAGE_SIZE) { 107 len = roundup(len, PAGE_SIZE); 108 len /= PAGE_SIZE; 109 descs[0].sd.sd_lolimit = len & 0xffff; 110 descs[0].sd.sd_hilimit = (len >> 16) & 0xf; 111 descs[0].sd.sd_gran = 1; 112 } else { 113 descs[0].sd.sd_lolimit = len; 114 descs[0].sd.sd_hilimit = 0; 115 descs[0].sd.sd_gran = 0; 116 } 117 pb = (uintptr_t)base; 118 descs[0].sd.sd_lobase = pb & 0xffffff; 119 descs[0].sd.sd_hibase = (pb >> 24) & 0xff; 120 descs[0].sd.sd_type = type; 121 descs[0].sd.sd_dpl = SEL_UPL; 122 descs[0].sd.sd_p = p; 123 descs[0].sd.sd_def32 = 1; 124 125 if ((sel = i386_set_ldt(LDT_AUTO_ALLOC, descs, 1)) == -1) 126 fprintf(stderr, "i386_set_ldt: %s\n", strerror(errno)); 127 else if (i386_get_ldt(sel, descsk, 1) == -1) { 128 fprintf(stderr, "i386_get_ldt: %s\n", strerror(errno)); 129 sel = -1; 130 } else if (memcmp(descs, descsk, sizeof(descs)) != 0) { 131 fprintf(stderr, "descs != descsk\n"); 132 sel = -1; 133 } else 134 fprintf(stderr, "selector %d\n", sel); 135 136 return (sel); 137} 138 139int 140test1(int tnum, int sel) 141{ 142 unsigned char ar; 143 144 writebyte(sel, 0, '1'); 145 ar = readbyte(sel, 0); 146 if (ar == '1') 147 fprintf(stderr, "test %d.1 ok\n", tnum); 148 else 149 fprintf(stderr, "test%d.1 failed, ar %x\n", tnum, ar); 150 writebyte(sel, 0, '2'); 151 ar = readbyte(sel, 0); 152 if (ar == '2') 153 fprintf(stderr, "test %d.2 ok\n", tnum); 154 else 155 fprintf(stderr, "test%d.2 failed, ar %x\n", tnum, ar); 156 return (sel); 157} 158 159int 160test2_func(void *arg) 161{ 162 int *sel; 163 164 sel = arg; 165 test1(2, *sel); 166 rfork(0); 167 test1(3, *sel); 168 return (0); 169} 170 171void 172test2(int sel) 173{ 174 pid_t r; 175 int status; 176 177 r = rfork_thread(RFPROC | RFMEM, stack + sizeof(stack), 178 test2_func, &sel); 179 if (r == -1) { 180 fprintf(stderr, "rfork(RFPROC): %s\n", strerror(errno)); 181 return; 182 } else { 183 waitpid(r, &status, 0); 184 if (WIFSIGNALED(status)) { 185 fprintf(stderr, "test2: child terminated by %s\n", 186 strsignal(WTERMSIG(status))); 187 } 188 } 189} 190 191int 192main(int argc, char *argv[]) 193{ 194 int sel; 195 196 sel = alloc_sel(a, 1, SDT_MEMRWA, 1); 197 if (sel == -1) 198 return (1); 199 200 test1(1, sel); 201 test2(sel); 202 return (0); 203} 204EOF 205 cc -o ldt_static_i386 -Wall -static ldt.c 206 rm ldt.c 207 208 cat > ioperm.c <<EOF 209/* \$Id: ioperm.c,v 1.3 2008/11/02 15:43:33 kostik Exp \$ */ 210 211#include <machine/sysarch.h> 212#include <errno.h> 213#include <signal.h> 214#include <stdio.h> 215#include <stdlib.h> 216#include <string.h> 217 218static const unsigned int port_num = 0x130; 219 220unsigned char 221inb(unsigned int port) 222{ 223 unsigned char data; 224 225 __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port)); 226 return (data); 227} 228 229void 230sigbus_handler(int signo) 231{ 232 233 fprintf(stderr, "Got SIGBUS\n"); 234 exit(0); 235} 236 237int 238main(int argc, char *argv[]) 239{ 240 struct sigaction sa; 241 unsigned int length1; 242 int enable1; 243 244 if (i386_get_ioperm(port_num, &length1, &enable1) == -1) { 245 fprintf(stderr, "get 1: %s\n", strerror(errno)); 246 return (1); 247 } 248 if (length1 != 0 && enable1 != 0) { 249 fprintf(stderr, "enable1: enabled\n"); 250 return (1); 251 } 252 if (i386_set_ioperm(port_num, 1, 1) == -1) { 253 fprintf(stderr, "set 1: %s\n", strerror(errno)); 254 return (1); 255 } 256 inb(port_num); 257 if (i386_set_ioperm(port_num, 1, 0) == -1) { 258 fprintf(stderr, "set 2: %s\n", strerror(errno)); 259 return (1); 260 } 261 if (i386_get_ioperm(port_num, &length1, &enable1) == -1) { 262 fprintf(stderr, "get 1: %s\n", strerror(errno)); 263 return (1); 264 } 265 if (enable1 != 0) { 266 fprintf(stderr, "enable2: enabled\n"); 267 return (1); 268 } 269 fprintf(stderr, "And now we should get SIGBUS\n"); 270 memset(&sa, 0, sizeof(sa)); 271 sa.sa_handler = sigbus_handler; 272 if (sigaction(SIGBUS, &sa, NULL) == -1) { 273 fprintf(stderr, "sigaction(SIGBUS): %s\n", strerror(errno)); 274 return (1); 275 } 276 inb(port_num); 277 278 return (0); 279} 280EOF 281 cc -o ioperm_static_i386 -Wall -static ioperm.c 282 rm ioperm.c 283 284 cat > fault.c <<EOF 285/* \$Id: fault.c,v 1.5 2008/10/28 17:39:16 kostik Exp \$ */ 286 287#include <sys/cdefs.h> 288#include <sys/types.h> 289#include <sys/ucontext.h> 290#include <errno.h> 291#include <signal.h> 292#include <stdio.h> 293#include <string.h> 294#include <unistd.h> 295 296extern char *fault_instr; 297int run; 298 299void 300sigsegv_sigaction(int signo, siginfo_t *si, void *c) 301{ 302 ucontext_t *uc; 303 mcontext_t *mc; 304 305 uc = c; 306 mc = &uc->uc_mcontext; 307 printf("SIGSEGV run %d err %x ds %x ss %x es %x fs %x gs %x\n", 308 run, mc->mc_err, mc->mc_ds, mc->mc_ss, mc->mc_es, mc->mc_fs, 309 mc->mc_gs); 310 switch (run) { 311 case 0: 312 mc->mc_ds = 0x1111; 313 break; 314 case 1: 315 mc->mc_es = 0x1111; 316 break; 317 case 2: 318 mc->mc_fs = 0x1111; 319 break; 320 case 3: 321 mc->mc_gs = 0x1111; 322 break; 323 case 4: 324 mc->mc_ss = 0x1111; 325 break; 326 case 5: 327 _exit(11); 328 } 329 run++; 330} 331 332void 333fault(void) 334{ 335 336 __asm__ volatile(".globl\tfault_instr;fault_instr:\ttestl\t\$0,0\n"); 337} 338 339int 340main(int argc, char *argv[]) 341{ 342 struct sigaction sa; 343 344 memset(&sa, 0, sizeof(sa)); 345 sa.sa_sigaction = sigsegv_sigaction; 346 sa.sa_flags = SA_SIGINFO; 347 if (sigaction(SIGSEGV, &sa, NULL) == -1) { 348 fprintf(stderr, "sigaction: %s\n", strerror(errno)); 349 return (1); 350 } 351 if (sigaction(SIGBUS, &sa, NULL) == -1) { 352 fprintf(stderr, "sigaction: %s\n", strerror(errno)); 353 return (1); 354 } 355 356 fault(); 357 358 return (0); 359} 360EOF 361 cc -o fault_static_i386 -Wall -static fault.c 362 rm fault.c 363fi 364 365if [ "`uname -p`" = "amd64" ]; then 366 [ -x ldt_static_i386 ] && ./ldt_static_i386 367 [ -x ioperm_static_i386 ] && ./ioperm_static_i386 368 [ -x fault_static_i386 ] && { ./fault_static_i386; rm fault_static_i386.core; } 369fi 370exit 0 371