|
![]() |
/*****************************************************************************
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