body.c 2.33 KB
Newer Older
Oliver Pinter's avatar
Oliver Pinter committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* body.c - This part is shared by the test programs (except for the randomization
 *          tests)
 *
 * Copyright (c)2003,2004 by Peter Busser <peter@adamantix.org>
 * This file has been released under the GNU Public Licence version 2 or later
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>
#include <unistd.h>
Loic's avatar
Loic committed
19
#include <string.h>
Oliver Pinter's avatar
Oliver Pinter committed
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "body.h"


static void *test_thread(void *p)
{
	pause();
	return NULL;
}

int main( int argc, char *argv[] )
{
	int status;
	char *mode;
Loic's avatar
Loic committed
33
34
35

	/*
	 * This defaults to 1 as a safety mechanism. It is better to fail in
Oliver Pinter's avatar
Oliver Pinter committed
36
37
38
39
40
	 * blackhat mode, because kiddie mode can produce overly optimistic
	 * results.
	 */
	int paxtest_mode = 1;

Loic's avatar
Loic committed
41
#ifndef __clang__
Oliver Pinter's avatar
Oliver Pinter committed
42
43
	/* Dummy nested function */
	void dummy(void) {}
Loic's avatar
Loic committed
44
#endif
Oliver Pinter's avatar
Oliver Pinter committed
45
46
47
48
49
50
51
52

	mode = getenv( "PAXTEST_MODE" );
	if( mode == NULL ) {
		paxtest_mode = 1;
	} else {
		if( strcmp(mode,"0") == 0 ) {
			paxtest_mode = 0;
		} else if( strcmp(mode,"1") == 0 ) {
Loic's avatar
Loic committed
53
54
55
56
#ifdef __clang__
			printf("INFO: The blackhat mode not supported due to missing nested function support in clang.\n");
			paxtest_mode = 0;
#else
Oliver Pinter's avatar
Oliver Pinter committed
57
			paxtest_mode = 1;
Loic's avatar
Loic committed
58
#endif
Oliver Pinter's avatar
Oliver Pinter committed
59
60
61
62
63
64
65
		}
	}

	printf( "%s: ", testname );
	fflush( stdout );

	if( fork() == 0 ) {
Loic's avatar
Loic committed
66
67
68
#ifdef __clang__
		doit();
#else
Oliver Pinter's avatar
Oliver Pinter committed
69
70
71
72
73
74
75
76
77
78
79
		/* Perform a dirty (but not unrealistic) trick to circumvent
		 * the kernel protection.
		 */
		if( paxtest_mode == 1 ) {
			pthread_t thread;
			pthread_create(&thread, NULL, test_thread, dummy);
			doit();
			pthread_kill(thread, SIGTERM);
		} else {
			doit();
		}
Loic's avatar
Loic committed
80
#endif
Oliver Pinter's avatar
Oliver Pinter committed
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
	} else {
		wait( &status );
		if( WIFEXITED(status) == 0 ) {
			printf( "Killed\n" );
			exit( 0 );
		}
	}

	exit( 0 );
}

void itworked( void )
{
	printf( "Vulnerable\n" );
	exit( 1 );
}

void itfailed( void )
{
	printf( "Ok\n" );
	exit( 2 );
}


int do_mprotect( const void *addr, size_t len, int prot )
{
	void *ptr;
	int retval;
	unsigned long pagesize = sysconf(_SC_PAGESIZE);
	unsigned long offset = (unsigned long) addr & (pagesize - 1);

	/* Align to a multiple of PAGESIZE, assumed to be a power of two */
	ptr = (void *)((unsigned long) addr - offset);
	len += offset;

	retval = mprotect( ptr, len, prot );
	if( retval != 0 && (errno == EINVAL)) {
		perror( "could not mprotect():" );
		exit( 1 );
	}

	return retval;
}