예제 #1
0
static bool
qualify_syscall_name(const char *s, struct number_set *set)
{
	bool found = false;

	for (unsigned int p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
		for (kernel_long_t scno = 0;
		     (scno = scno_by_name(s, p, scno)) >= 0;
		     ++scno) {
			add_number_to_set_array(scno, set, p);
			found = true;
		}
	}

	return found;
}
static bool
parse_inject_token(const char *const token, struct inject_opts *const fopts,
		   struct inject_personality_data *const pdata,
		   const bool fault_tokens_only)
{
	const char *val;
	int intval;

	if ((val = STR_STRIP_PREFIX(token, "when=")) != token) {
		/*
		 *	== 1+1
		 * F	== F+0
		 * F+	== F+1
		 * F+S
		 */
		char *end;
		intval = string_to_uint_ex(val, &end, 0xffff, "+");
		if (intval < 1)
			return false;

		fopts->first = intval;

		if (*end) {
			val = end + 1;
			if (*val) {
				/* F+S */
				intval = string_to_uint_upto(val, 0xffff);
				if (intval < 1)
					return false;
				fopts->step = intval;
			} else {
				/* F+ == F+1 */
				fopts->step = 1;
			}
		} else {
			/* F == F+0 */
			fopts->step = 0;
		}
	} else if ((val = STR_STRIP_PREFIX(token, "syscall=")) != token) {
		if (fopts->data.flags & INJECT_F_SYSCALL)
			return false;

		for (unsigned int p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
			kernel_long_t scno = scno_by_name(val, p, 0);

			if (scno < 0)
				return false;

			/*
			 * We want to inject only pure system calls with no side
			 * effects.
			 */
			if (!(sysent_vec[p][scno].sys_flags & TRACE_PURE))
				return false;

			pdata[p].scno = scno;
		}

		fopts->data.flags |= INJECT_F_SYSCALL;
	} else if ((val = STR_STRIP_PREFIX(token, "error=")) != token) {
		if (fopts->data.flags & (INJECT_F_ERROR | INJECT_F_RETVAL))
			return false;
		intval = string_to_uint_upto(val, MAX_ERRNO_VALUE);
		if (intval < 0)
			intval = find_errno_by_name(val);
		if (intval < 1)
			return false;
		fopts->data.rval_idx = retval_new(intval);
		fopts->data.flags |= INJECT_F_ERROR;
	} else if (!fault_tokens_only
		   && (val = STR_STRIP_PREFIX(token, "retval=")) != token) {

		if (fopts->data.flags & (INJECT_F_ERROR | INJECT_F_RETVAL))
			return false;

		errno = 0;
		char *endp;
		unsigned long long ullval = strtoull(val, &endp, 0);
		if (endp == val || *endp || (kernel_ulong_t) ullval != ullval
		    || ((ullval == 0 || ullval == ULLONG_MAX) && errno))
			return false;

#if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
		bool inadvertent_fault_injection = false;
#endif

#if !HAVE_ARCH_DEDICATED_ERR_REG
		if ((kernel_long_t) ullval < 0
		    && (kernel_long_t) ullval >= -MAX_ERRNO_VALUE) {
# if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
			inadvertent_fault_injection = true;
# endif
			error_msg("Inadvertent injection of error %" PRI_kld
				  " is possible for retval=%llu",
				  -(kernel_long_t) ullval, ullval);
		}
# if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
		else if ((int) ullval < 0 && (int) ullval >= -MAX_ERRNO_VALUE) {
			inadvertent_fault_injection = true;
			error_msg("Inadvertent injection of error %d is"
				  " possible in compat personality for"
				  " retval=%llu",
				  -(int) ullval, ullval);
		}
# endif
#endif

#if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
		if (!inadvertent_fault_injection
		    && (unsigned int) ullval != ullval) {
			error_msg("Injected return value %llu will be"
				  " clipped to %u in compat personality",
				  ullval, (unsigned int) ullval);
		}
#endif

		fopts->data.rval_idx = retval_new(ullval);
		fopts->data.flags |= INJECT_F_RETVAL;
	} else if (!fault_tokens_only
		   && (val = STR_STRIP_PREFIX(token, "signal=")) != token) {
		if (fopts->data.flags & INJECT_F_SIGNAL)
			return false;
		intval = sigstr_to_uint(val);
		if (intval < 1 || intval > NSIG_BYTES * 8)
			return false;
		fopts->data.signo = intval;
		fopts->data.flags |= INJECT_F_SIGNAL;
	} else if (!fault_tokens_only
		&& (val = STR_STRIP_PREFIX(token, "delay_enter=")) != token) {
		if (!parse_delay_token(val, fopts, true))
			return false;
	} else if (!fault_tokens_only
		&& (val = STR_STRIP_PREFIX(token, "delay_exit=")) != token) {
		if (!parse_delay_token(val, fopts, false))
			return false;
	} else {
		return false;
	}

	return true;
}