示例#1
0
文件: vfork.c 项目: Mellanox/arc_ltp
int
main(int argc, char** argv)
{

#if HAVE_DECL_PTRACE_SETOPTIONS && HAVE_DECL_PTRACE_O_TRACEVFORKDONE
	int exit_status;

	_parse_opts(argc, argv);

	if (fp == NULL) {
		fp = stderr;
	}

	if (socketpair(AF_UNIX, SOCK_STREAM, 0, psync) == -1) {
		tst_resm(TBROK | TERRNO, "socketpair() failed");
	} else {

		child = fork();
		if (child == -1) {
			tst_resm(TBROK | TERRNO, "fork() failed");
		} else if (child == 0) {

			int rc = EXIT_FAILURE;

			tst_sig(FORK, DEF_HANDLER, child_cleanup);

			if (close(psync[1])) {
				tst_resm(TBROK, "close(psync[1]) failed)");
			} else {
				/* sleep until the parent wakes us up */
				await_mutex(psync[0]);
				rc = do_vfork(num_vforks);
			}
			_exit(rc);

		} else {

			tst_sig(FORK, kill_child, parent_cleanup);

			close(psync[0]);

			/* Set up ptrace */
			if (ptrace(PTRACE_ATTACH, child, NULL, NULL) == -1) {
				tst_resm(TBROK | TERRNO,
					 "ptrace(ATTACH) failed");
				tst_exit();
			}
			if (waitpid(child, NULL, 0) != child) {
				tst_resm(TBROK | TERRNO, "waitpid(%d) failed",
							 child);
				kill_child();
			} else {

				if (ptrace(PTRACE_SETOPTIONS, child, NULL,
					   PTRACE_O_TRACEVFORK) == -1) {
					tst_resm(TINFO | TERRNO,
						"ptrace(PTRACE_SETOPTIONS) "
						"failed.");
				}
				if (ptrace(PTRACE_CONT, child, NULL, NULL) == -1) {
					tst_resm(TINFO | TERRNO,
						"ptrace(PTRACE_CONT) failed.");
				}

				send_mutex(psync[1]);

				close(psync[1]);

				tst_resm(TINFO, "Child spawn's pid=%d", child);
				fprintf(fp, "%d\n", child);
				fflush(fp);

				exit_status = do_trace(child, ++num_vforks);

				tst_resm(exit_status == 0 ? TPASS : TFAIL,
					"do_trace %s",
					(exit_status == 0 ? "succeeded" : "failed"));

				parent_cleanup();

			}

		}

	}

#else
	tst_resm(TCONF, "System doesn't support have required ptrace "
		        "capabilities.");
#endif
	tst_resm(TINFO, "Exiting...");
	tst_exit();

}
示例#2
0
/* Parse arguments, etc then get my socket address/port information. Attempt to
 * adopt this process into a job in the following order:
 * 	1) If the user has only one job on the node, pick that one
 * 	2) Send RPC to source IP of socket. If there is a slurmd at the IP
 * 		address, ask it which job I belong to. On success, pick that one
 *	3) Pick a job semi-randomly (default) or skip the adoption (if
 *		configured)
 */
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags
				__attribute__((unused)), int argc, const char **argv)
{
	int retval = PAM_IGNORE, rc, slurmrc, bufsize, user_jobs;
	char *user_name;
	List steps = NULL;
	step_loc_t *stepd = NULL;
	struct passwd pwd, *pwd_result;
	char *buf = NULL;

	_init_opts();
	_parse_opts(pamh, argc, argv);
	_log_init(opts.log_level);

	switch (opts.action_generic_failure) {
	case CALLERID_ACTION_DENY:
		rc = PAM_PERM_DENIED;
		break;
	case CALLERID_ACTION_ALLOW:
		rc = PAM_SUCCESS;
		break;
	case CALLERID_ACTION_IGNORE:
		rc = PAM_IGNORE;
		break;
		/* Newer gcc versions warn if enum cases are missing */
	default:
		error("The code is broken!!!!");
	}

	retval = pam_get_item(pamh, PAM_USER, (void *) &user_name);
	if (user_name == NULL || retval != PAM_SUCCESS)  {
		pam_syslog(pamh, LOG_ERR, "No username in PAM_USER? Fail!");
		return PAM_SESSION_ERR;
	}

	/* Check for an unsafe config that might lock out root. This is a very
	 * basic check that shouldn't be 100% relied on */
	if (!opts.ignore_root &&
	    (opts.action_unknown == CALLERID_ACTION_DENY ||
	     opts.action_no_jobs != CALLERID_ACTION_ALLOW ||
	     opts.action_adopt_failure != CALLERID_ACTION_ALLOW ||
	     opts.action_generic_failure != CALLERID_ACTION_ALLOW
		    )) {
		/* Let's get verbose */
		info("===============================");
		info("Danger!!!");
		info("A crazy admin set ignore_root=0 and some unsafe actions");
		info("You might lock out root!");
		info("If this is desirable, modify the source code");
		info("Setting ignore_root=1 and continuing");
		opts.ignore_root = 1;
	}

	/* Ignoring root is probably best but the admin can allow it */
	if (!strcmp(user_name, "root")) {
		if (opts.ignore_root) {
			info("Ignoring root user");
			return PAM_IGNORE;
		} else {
			/* This administrator is crazy */
			info("Danger!!! This is a connection attempt by root and ignore_root=0 is set! Hope for the best!");
		}
	}

	/* Calculate buffer size for getpwnam_r */
	bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
	if (bufsize == -1)
		bufsize = 16384; /* take a large guess */

	buf = xmalloc(bufsize);
	retval = getpwnam_r(user_name, &pwd, buf, bufsize, &pwd_result);
	if (pwd_result == NULL) {
		if (retval == 0) {
			error("getpwnam_r could not locate %s", user_name);
		} else {
			errno = retval;
			error("getpwnam_r: %m");
		}

		xfree(buf);
		return PAM_SESSION_ERR;
	}

	if (_load_cgroup_config() != SLURM_SUCCESS)
		return rc;

	/* Check if there are any steps on the node from any user. A failure here
	 * likely means failures everywhere so exit on failure or if no local jobs
	 * exist. */
	steps = stepd_available(NULL, opts.node_name);
	if (!steps) {
		error("Error obtaining local step information.");
		goto cleanup;
	}

	/* Check to see if this user has only one job on the node. If so, choose
	 * that job and adopt this process into it (unless configured not to) */
	user_jobs = _user_job_count(steps, pwd.pw_uid, &stepd);
	if (user_jobs == 0) {
		if (opts.action_no_jobs == CALLERID_ACTION_DENY) {
			send_user_msg(pamh,
				      "Access denied by "
				      PAM_MODULE_NAME
				      ": you have no active jobs on this node");
			rc = PAM_PERM_DENIED;
		} else {
			debug("uid %u owns no jobs but action_no_jobs=ignore",
			      pwd.pw_uid);
			rc = PAM_IGNORE;
		}
		goto cleanup;
	} else if (user_jobs == 1) {
		if (opts.single_job_skip_rpc) {
			info("Connection by user %s: user has only one job %u",
			     user_name,
			     stepd->jobid);
			slurmrc = _adopt_process(getpid(), stepd);
			/* If adoption into the only job fails, it is time to
			 * exit. Return code is based on the
			 * action_adopt_failure setting */
			if (slurmrc == SLURM_SUCCESS ||
			    (opts.action_adopt_failure ==
			     CALLERID_ACTION_ALLOW))
				rc = PAM_SUCCESS;
			else
				rc = PAM_PERM_DENIED;
			goto cleanup;
		}
	} else {
		debug("uid %u has %d jobs", pwd.pw_uid, user_jobs);
	}

	/* Single job check turned up nothing (or we skipped it). Make RPC call
	 * to slurmd at source IP. If it can tell us the job, the function calls
	 * _adopt_process */
	rc = _try_rpc(&pwd);
	if (rc == PAM_SUCCESS)
		goto cleanup;

	/* The source of the connection either didn't reply or couldn't
	 * determine the job ID at the source. Proceed to action_unknown */
	rc = _action_unknown(pamh, &pwd, steps);

cleanup:
	FREE_NULL_LIST(steps);
	xfree(buf);
	xfree(slurm_cgroup_conf);
	xfree(opts.node_name);
	return rc;
}