Example #1
0
static void validate_lex_operand(Validator *val, MVMuint32 flags) {
    MVMuint16 lex_index, frame_index, i;
    MVMuint32 lex_count;
    MVMStaticFrame *frame = val->frame;

    /* Two steps forward, two steps back to keep the error reporting happy,
       and to make the endian conversion within ensure_bytes correct.
       (Both are using val->cur_op, and want it to have different values.) */
    ensure_bytes(val, 2);
    lex_index   = GET_UI16(val->cur_op, 0);
    val->cur_op += 2;
    ensure_bytes(val, 2);
    val->cur_op -= 2;
    frame_index = GET_UI16(val->cur_op, 2);

    for (i = frame_index; i; i--) {
        frame = frame->body.outer;
        if (!frame)
            fail(val, MSG(val, "lexical operand requires %" PRIu16
                          " more enclosing scopes"), i);
    }

    lex_count = frame->body.num_lexicals;
    if (lex_index >= lex_count)
        fail(val, MSG(val, "lexical operand index %" PRIu16
                      " out of range 0.. %" PRIu32), lex_index, lex_count - 1);

    val->cur_op += 4;
}
Example #2
0
static void validate_reg_operand(Validator *val, MVMuint32 flags) {
    MVMuint32 operand_type = flags & MVM_operand_type_mask;
    MVMuint32 reg_type;
    MVMuint16 reg;

    ensure_bytes(val, 2);

    reg = GET_REG(val->cur_op, 0);
    if (reg >= val->loc_count)
        fail(val, MSG(val, "register operand index %" PRIu16
                      " out of range 0..%" PRIu32), reg, val->loc_count - 1);

    reg_type = val->loc_types[reg] << 3;

    if (operand_type == MVM_operand_type_var) {
        if (!val->reg_type_var) {
            val->reg_type_var = reg_type;
            goto next_operand;
        }

        operand_type = val->reg_type_var;
    }

    if (reg_type != operand_type)
        fail(val, MSG(val, "operand type %i does not match register type %i"),
             operand_type, reg_type);

next_operand:
    val->cur_op += 2;
}
Example #3
0
MVM_STATIC_INLINE void read_op(Validator *val) {
    MVMuint16  opcode;
    const MVMOpInfo *info;
    MVMuint32  pos;

    ensure_bytes(val, 2);

    opcode = *(MVMuint16 *)val->cur_op;
    info   = get_info(val, opcode);
    pos    = val->cur_op - val->bc_start;

#if 0
    MVM_string_print(val->tc, val->cu->body.filename);
    printf(" %u %s %.2s\n", val->cur_instr, info->name, info->mark);
#endif

    val->labels[pos] |= MVM_BC_op_boundary;
    val->cur_info     = info;
    val->cur_mark     = info->mark;
    val->cur_op      += 2;
    val->cur_instr   += 1;
}
Example #4
0
static void validate_literal_operand(Validator *val, MVMuint32 flags) {
    MVMuint32 type = flags & MVM_operand_type_mask;
    MVMuint32 size;

    switch (type) {
    case MVM_operand_int8:
        size = 1;
        break;
    case MVM_operand_int16:
        size = 2;
        break;
    case MVM_operand_int32:
        size = 4;
        break;
    case MVM_operand_int64:
        size = 8;
        break;
    case MVM_operand_num32:
        size = 4;
        break;
    case MVM_operand_num64:
        size = 8;
        break;
    case MVM_operand_callsite:
        size = 2;
        break;
    case MVM_operand_coderef:
        size = 2;
        break;
    case MVM_operand_str:
        size = 4;
        break;
    case MVM_operand_ins:
        size = 4;
        break;

    case MVM_operand_obj:
    case MVM_operand_type_var:
        fail(val, MSG(val, "operand type %i can't be a literal"), type);

    default:
        fail(val, MSG(val, "unknown operand type %i"), type);
    }

    ensure_bytes(val, size);

    switch (type) {
    case MVM_operand_callsite: {
        MVMuint16 index = GET_UI16(val->cur_op, 0);
        MVMuint32 count = val->cu->body.orig_callsites;
        if (index >= count)
            fail(val, MSG(val, "callsite index %" PRIu16
                          " out of range 0..%" PRIu32), index, count - 1);
        break;
    }

    case MVM_operand_coderef: {
        MVMuint16 index = GET_UI16(val->cur_op, 0);
        MVMuint32 count = val->cu->body.orig_frames;
        if (index >= count)
            fail(val, MSG(val, "coderef index %" PRIu16
                          " out of range 0..%" PRIu32), index, count - 1);
        break;
    }

    case MVM_operand_str: {
        MVMuint32 index = GET_UI32(val->cur_op, 0);
        MVMuint32 count = val->cu->body.orig_strings;
        if (index >= count)
            fail(val, MSG(val, "string index %" PRIu32
                          " out of range 0..%" PRIu32), index, count - 1);
        break;
    }

    case MVM_operand_ins: {
        MVMuint32 offset = GET_UI32(val->cur_op, 0);
        if (offset >= val->bc_size)
            fail(val, MSG(val, "branch instruction offset %" PRIu32
                          " out of range 0..%" PRIu32), offset, val->bc_size - 1);
        val->labels[offset] |= MVM_BC_branch_target;
    }
    }

    val->cur_op += size;
}
Example #5
0
static int handle_global_update(enum global_type type, size_t size, unsigned char *value)
{
	struct global_config *config;
	bool timer_needs_update = false;
	enum session_timer_type timer_type;
	int error;

	config = kmalloc(sizeof(*config), GFP_KERNEL);
	if (!config)
		return -ENOMEM;
	config->mtu_plateaus = NULL;

	error = config_clone(config);
	if (error)
		goto fail;

	switch (type) {
#ifdef STATEFUL
	case MAX_PKTS:
		if (!ensure_bytes(size, 8))
			goto einval;
		config->max_stored_pkts = *((__u64 *) value);
		break;
	case SRC_ICMP6ERRS_BETTER:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->src_icmp6errs_better = *((__u8 *) value);
		break;
	case BIB_LOGGING:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->bib_logging = *((__u8 *) value);
		break;
	case SESSION_LOGGING:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->session_logging = *((__u8 *) value);
		break;

	case UDP_TIMEOUT:
		if (!ensure_bytes(size, 8))
			goto einval;
		if (!assign_timeout(value, UDP_MIN, &config->ttl.udp))
			goto einval;
		timer_needs_update = true;
		timer_type = SESSIONTIMER_UDP;
		break;
	case ICMP_TIMEOUT:
		if (!ensure_bytes(size, 8))
			goto einval;
		if (!assign_timeout(value, 0, &config->ttl.icmp))
			goto einval;
		timer_needs_update = true;
		timer_type = SESSIONTIMER_ICMP;
		break;
	case TCP_EST_TIMEOUT:
		if (!ensure_bytes(size, 8))
			goto einval;
		if (!assign_timeout(value, TCP_EST, &config->ttl.tcp_est))
			goto einval;
		timer_needs_update = true;
		timer_type = SESSIONTIMER_EST;
		break;
	case TCP_TRANS_TIMEOUT:
		if (!ensure_bytes(size, 8))
			goto einval;
		if (!assign_timeout(value, TCP_TRANS, &config->ttl.tcp_trans))
			goto einval;
		timer_needs_update = true;
		timer_type = SESSIONTIMER_TRANS;
		break;
	case FRAGMENT_TIMEOUT:
		if (!ensure_bytes(size, 8))
			goto einval;
		if (!assign_timeout(value, FRAGMENT_MIN, &config->ttl.frag))
			goto einval;
		break;
	case DROP_BY_ADDR:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->drop_by_addr = *((__u8 *) value);
		break;
	case DROP_ICMP6_INFO:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->drop_icmp6_info = *((__u8 *) value);
		break;
	case DROP_EXTERNAL_TCP:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->drop_external_tcp = *((__u8 *) value);
		break;
#else
	case COMPUTE_UDP_CSUM_ZERO:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->compute_udp_csum_zero = *((__u8 *) value);
		break;
	case RANDOMIZE_RFC6791:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->randomize_error_addresses = *((__u8 *) value);
		break;
#endif
	case RESET_TCLASS:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->reset_traffic_class = *((__u8 *) value);
		break;
	case RESET_TOS:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->reset_tos = *((__u8 *) value);
		break;
	case NEW_TOS:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->new_tos = *((__u8 *) value);
		break;
	case DF_ALWAYS_ON:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->atomic_frags.df_always_on = *((__u8 *) value);
		break;
	case BUILD_IPV6_FH:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->atomic_frags.build_ipv6_fh = *((__u8 *) value);
		break;
	case BUILD_IPV4_ID:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->atomic_frags.build_ipv4_id = *((__u8 *) value);
		break;
	case LOWER_MTU_FAIL:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->atomic_frags.lower_mtu_fail = *((__u8 *) value);
		break;
	case MTU_PLATEAUS:
		if (is_error(update_plateaus(config, size, value)))
			goto einval;
		break;
	case DISABLE:
		config->is_disable = (__u8) true;
		break;
	case ENABLE:
		config->is_disable = (__u8) false;
		break;
	case ATOMIC_FRAGMENTS:
		if (!ensure_bytes(size, 1))
			goto einval;
		config->atomic_frags.df_always_on = *((__u8 *) value);
		config->atomic_frags.build_ipv6_fh = *((__u8 *) value);
		config->atomic_frags.build_ipv4_id = !(*((__u8 *) value));
		config->atomic_frags.lower_mtu_fail = !(*((__u8 *) value));
		break;
	default:
		log_err("Unknown config type: %u", type);
		goto einval;
	}

	error = config_set(config);
	if (error)
		goto fail;

	if (timer_needs_update)
		error = sessiondb_update_timer(timer_type);

	return error;

einval:
	error = -EINVAL;
	/* Fall through. */

fail:
	kfree(config->mtu_plateaus);
	kfree(config);
	return error;
}