View of xos/tests/segfault.c


XOS | Parent Directory | View | Download

/* Copyright (C) 2008  Emmanuel Varoquaux
 
   This file is part of XOS.
 
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
 
extern char end;
 
const char blabla[] = "blabla"; /* section .rodata */
 
static void f()
{
  char buf[100000];
 
  *buf = 1;
}
 
static int do_exception(int n)
{
  void *_brk, *new_brk;
 
  /* Chacune des sequences doit provoquer une exception. La variable n execute
     une sequence particuliere. */
  switch (n) {
 
  case 1: /* ecriture dans une zone memoire en lecture seule */
    printf("crashing...\n"); /* pour controler que le segfault se produit bien la ou on l'attend */
    asm volatile ("movb $0, blabla");
    break;
 
  case 2: /* autre ecriture dans une zone memoire en lecture seule */
    printf("crashing...\n");
    asm volatile ("movb $0, _start");
    break;
 
  case 3: /* ecriture dans une zone memoire inaccessible */
    printf("crashing...\n");
    asm volatile ("movb $0, 0");
    break;
 
  case 4: /* test sbrk 1 */
    _brk = sbrk(0);
    new_brk = brk;
    if ((unsigned long)new_brk & 0xfff) {
      new_brk = (void *)((unsigned long)new_brk & 0xfffff000);
      new_brk += 4096;
    }
    sbrk(new_brk - _brk);
    _brk = sbrk(0);
    *(char *)(_brk - 1) = '\0'; /* pas de segfault */
    printf("crashing...\n");
    *(char *)_brk = '\0'; /* segfault */
    break;
 
  case 5: /* test sbrk 2 */
    sbrk(4096);
    _brk = sbrk(0);
    if ((unsigned long)_brk & 0xfff) {
      _brk = (void *)((unsigned long)_brk & 0xfffff000);
      _brk += 4096;
    }
    *(char *)(_brk - 1) = '\0'; /* pas de segfault */
    printf("crashing...\n");
    *(char *)_brk = '\0'; /* segfault */
    break;
 
  case 6: /* ecriture dans une zone memoire en lecture seule par un appel systeme */
    printf("crashing...\n");
    if (read(0, (void *)(unsigned long)blabla, 1) < 0) {
      printf("segmentation fault  segfault\n");
      _exit(1);
    }
    break;
 
  case 7: /* autre ecriture dans une zone memoire en lecture seule par un appel systeme */
    printf("crashing...\n");
    read(0, (void **)f, 1);
    break;
 
  default:
    return 0;
  }
  printf("An exception should have occured !\n");
  return 1;
}
 
int main()
{
  int n;
  int pid;
 
  for (n = 1; n <= 6; n++) {
    printf("Test: %d\n", n);
    if (!(pid = fork())) {
      do_exception(n);
      _exit(1);
    }
    waitpid(pid, NULL, 0);
    printf("\n");
  }
 
  /* accroissement de la taille de la pile - ne devrait pas produire d'erreur justement */
  f();
  printf("ok !\n");
  return 0;
}