// Copies with unix open, read, and write functions, but only // with a single char buffer // Very slow. void readwrite1char(unsigned long long size, int argc, char **argv) { Timer t; double wTime, eTime, sTime; t.start(); unsigned long long rin, rout; // Opens input file for reading int fr = open(argv[1], O_RDONLY); if (fr == -1) { perror("open 2"); exit(1); } // Opens output file for writing, sets user permissions as 0644 int fw = open(argv[2], O_CREAT | O_WRONLY , 0644); if (fw == -1) { perror("open 2"); exit(1); } char buffer[1]; while ((rin = read(fr, &buffer, 1)) > 0) { rout = write(fw, &buffer, (ssize_t) rin); if (rout != rin) { perror("write"); exit(1); } } if(rin == -1){ perror("read"); } t.elapsedTime(wTime, eTime, sTime); if (argc > 3) { std::cout << "Copying with 1 char buffer read() write(): " << std::endl; outputtime(wTime, eTime, sTime); } if (-1 == close(fw)) { perror("close fw"); exit(1); } if (-1 == close(fr)) { perror("close fr"); exit(1); } }
// Copying with get() and put() streams void getput(unsigned long long size, int argc, char **argv) { Timer t; double wTime, eTime, sTime; t.start(); std::ifstream inf(argv[1]); std::ofstream outf(argv[2]); for (unsigned long long i = 0; i < size; ++i) { outf.put(inf.get()); } t.elapsedTime(wTime, eTime, sTime); if (argc > 3) { std::cout << "Copying with get() and put(): " << std::endl; outputtime(wTime, eTime, sTime); } inf.close(); outf.close(); }
int main(int argc, char **argv) { sigset_t oldmask, newmask; pid_t pid; int status; int exitcode; char *valid_users; char *ptr; char *path; char cwd[MAXPATHLEN+3]; int opt; struct rlimit lim; progname = argv[0]; /* Clear environment to prevent all kinds of security holes, save PATH */ path = getenv("PATH"); environ[0] = NULL; /* FIXME: Clean path before setting it again? */ if ( path!=NULL ) setenv("PATH",path,1); /* Parse command-line options */ use_root = use_time = use_user = use_output = no_coredump = 0; memsize = filesize = nproc = RLIM_INFINITY; be_verbose = be_quiet = 0; show_help = show_version = 0; opterr = 0; while ( (opt = getopt_long(argc,argv,"+r:t:u:m:f:p:co:vq",long_opts,(int *) 0))!=-1 ) { switch ( opt ) { case 0: /* long-only option */ break; case 'r': /* rootdir option */ use_root = 1; rootdir = (char *) malloc(strlen(optarg)+2); strcpy(rootdir,optarg); break; case 't': /* time option */ use_time = 1; runtime = strtol(optarg,&ptr,10); if ( *ptr!=0 || runtime<=0 ) { error(0,"invalid time specified: `%s'",optarg); } break; case 'u': /* user option */ use_user = 1; runuid = strtol(optarg,&ptr,10); if ( *ptr!=0 ) runuid = userid(optarg); if ( runuid<0 ) error(0,"invalid username or ID specified: `%s'",optarg); break; case 'm': /* memsize option */ memsize = (rlim_t) strtol(optarg,&ptr,10); if ( *ptr!=0 || memsize<=0 ) { error(0,"invalid memory limit specified: `%s'",optarg); } /* Convert limit from kB to bytes and check for overflow */ if ( memsize!=(memsize*1024)/1024 ) { memsize = RLIM_INFINITY; } else { memsize *= 1024; } break; case 'f': /* filesize option */ filesize = (rlim_t) strtol(optarg,&ptr,10); if ( *ptr!=0 || filesize<=0 ) { error(0,"invalid filesize limit specified: `%s'",optarg); } /* Convert limit from kB to bytes and check for overflow */ if ( filesize!=(filesize*1024)/1024 ) { filesize = RLIM_INFINITY; } else { filesize *= 1024; } break; case 'p': /* nproc option */ nproc = (rlim_t) strtol(optarg,&ptr,10); if ( *ptr!=0 || nproc<=0 ) { error(0,"invalid process limit specified: `%s'",optarg); } break; case 'c': /* no-core option */ no_coredump = 1; break; case 'o': /* output option */ use_output = 1; outputfilename = (char *) malloc(strlen(optarg)+2); strcpy(outputfilename,optarg); break; case 'v': /* verbose option */ be_verbose = 1; break; case 'q': /* quiet option */ be_quiet = 1; break; case ':': /* getopt error */ case '?': error(0,"unknown option or missing argument `%c'",optopt); break; default: error(0,"getopt returned character code `%c' ??",(char)opt); } } if ( show_help ) usage(); if ( show_version ) version(); if ( argc<=optind ) error(0,"no command specified"); /* Command to be executed */ cmdname = argv[optind]; cmdargs = argv+optind; /* Check that new uid is in list of valid uid's. This must be done before chroot for /etc/passwd lookup. */ if ( use_user ) { valid_users = strdup(VALID_USERS); for(ptr=strtok(valid_users,","); ptr!=NULL; ptr=strtok(NULL,",")) { if ( runuid==userid(ptr) ) break; } if ( ptr==NULL || runuid<=0 ) error(0,"illegal user specified: %d",runuid); } /* Set resource limits: must be root to raise hard limits. Note that limits can thus be raised from the systems defaults! */ /* First define shorthand macro function */ #define setlim(type) \ if ( setrlimit(RLIMIT_ ## type, &lim)!=0 ) { \ if ( errno==EPERM ) { \ warning("no permission to set resource RLIMIT_" #type); \ } else { \ error(errno,"setting resource RLIMIT_" #type); \ } \ } if ( memsize!=RLIM_INFINITY ) { verbose("setting memory limits to %d bytes",(int)memsize); } lim.rlim_cur = lim.rlim_max = memsize; setlim(AS); setlim(DATA); setlim(STACK); setlim(MEMLOCK); if ( filesize!=RLIM_INFINITY ) { verbose("setting filesize limit to %d bytes",(int)filesize); } lim.rlim_cur = lim.rlim_max = filesize; setlim(FSIZE); if ( nproc!=RLIM_INFINITY ) { verbose("setting process limit to %d",(int)nproc); } lim.rlim_cur = lim.rlim_max = nproc; setlim(NPROC); #undef setlim if ( no_coredump ) { verbose("disabling core dumps"); lim.rlim_cur = lim.rlim_max = 0; if ( setrlimit(RLIMIT_CORE,&lim)!=0 ) error(errno,"disabling core dumps"); } /* Set root-directory and change directory to there. */ if ( use_root ) { /* Small security issue: when running setuid-root, people can find out which directories exist from error message. */ if ( chdir(rootdir) ) error(errno,"cannot chdir to `%s'",rootdir); /* Get absolute pathname of rootdir, by reading it. */ if ( getcwd(cwd,MAXPATHLEN)==NULL ) error(errno,"cannot get directory"); if ( cwd[strlen(cwd)-1]!='/' ) strcat(cwd,"/"); /* Canonicalize CHROOT_PREFIX: the use of NULL below is a GNU extension, recommended for security */ if ( (path = realpath(CHROOT_PREFIX,NULL))==NULL ) { error(errno,"cannot canonicalize path '%s'",CHROOT_PREFIX); } /* Check that we are within prescribed path. */ if ( strncmp(cwd,path,strlen(path))!=0 ) { error(0,"invalid root: must be within `%s'",path); } free(path); if ( chroot(".") ) error(errno,"cannot change root to `%s'",cwd); verbose("using root-directory `%s'",cwd); } /* Set user-id (must be root for this). */ if ( use_user ) { if ( setuid(runuid) ) error(errno,"cannot set user ID to `%d'",runuid); verbose("using user ID `%d'",runuid); } else { /* Reset effective uid to real uid, to increase security when program is run setuid */ if ( setuid(getuid()) ) error(errno,"cannot set real user ID"); verbose("using real uid `%d' as effective uid",getuid()); } if ( geteuid()==0 || getuid()==0 ) error(0,"root privileges not dropped"); /* Open output file for writing running time to */ if ( use_output ) { outputfile = fopen(outputfilename,"w"); if ( outputfile==NULL ) error(errno,"cannot open `%s'",outputfilename); verbose("using file `%s' to write runtime to",outputfilename); } switch ( child_pid = fork() ) { case -1: /* error */ error(errno,"cannot fork"); case 0: /* run controlled command */ /* Run the command in a separate process group so that the command and all its children can be killed off with one signal. */ setsid(); execvp(cmdname,cmdargs); error(errno,"cannot start `%s'",cmdname); default: /* become watchdog */ if ( gettimeofday(&starttime,NULL) ) error(errno,"getting time"); /* unmask all signals */ memset(&newmask, 0, sizeof(newmask)); if ( sigprocmask(SIG_SETMASK, &newmask, &oldmask)!=0 ) { error(errno,"unmasking signals"); } signal(SIGTERM,terminate); if ( use_time ) { signal(SIGALRM,terminate); alarm(runtime); verbose("using timelimit of %d seconds",runtime); } /* Wait for the child command to finish */ while ( (pid = wait(&status))!=-1 && pid!=child_pid ); if ( pid!=child_pid ) error(errno,"waiting on child"); outputtime(); /* Test whether command has finished abnormally */ if ( ! WIFEXITED(status) ) { if ( WIFSIGNALED(status) ) { warning("command terminated with signal %d",WTERMSIG(status)); return 128+WTERMSIG(status); } if ( WIFSTOPPED(status) ) { warning("command stopped with signal %d",WSTOPSIG(status)); return 128+WSTOPSIG(status); } error(0,"command exit status unknown: %d",status); } /* Return the exitstatus of the command */ exitcode = WEXITSTATUS(status); if ( exitcode!=0 ) verbose("command exited with exitcode %d",exitcode); return exitcode; } /* This should never be reached */ error(0,"unexpected end of program"); }