Ejemplo n.º 1
0
void
scale(struct xy *p, struct val *v)
{
	float edge;

	getlim(p,v);
	setlim(p);
	edge = top-bot;
	p->xa = p->xsize*edge/((*p->xf)(p->xub) - (*p->xf)(p->xlb));
	p->xbot = bot + edge*p->xoff;
	p->xtop = p->xbot + (top-bot)*p->xsize;
	p->xb = p->xbot - (*p->xf)(p->xlb)*p->xa + .5;
}
Ejemplo n.º 2
0
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");
}