From: Mathieu Desnoyers Date: Tue, 6 Sep 2022 19:10:17 +0000 (-0400) Subject: Fix: bytecode interpreter: LOAD_FIELD: handle user fields X-Git-Tag: v2.13.6~12 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=8c36b1385480103f12373817016ff22d20301f5b;p=lttng-modules.git Fix: bytecode interpreter: LOAD_FIELD: handle user fields The instructions for recursive traversal through composed types are used by the capture bytecode, and by filter expressions which access fields nested within composed types. Instructions BYTECODE_OP_LOAD_FIELD_STRING and BYTECODE_OP_LOAD_FIELD_SEQUENCE were leaving the "user" attribute uninitialized. Initialize those to 0. The handling of userspace strings and integers is missing in LOAD_FIELD instructions. Therefore, ensure that the specialization leaves the generic LOAD_FIELD instruction in place for userspace input. Add a "user" attribute to: - struct bytecode_get_index_data elem field (produced by the specialization), - struct vstack_load used by the specialization, - struct load_ptr used by the interpreter. - struct lttng_interpreter_output used by the event notification capture. Use this "user" attribute in dynamic_load_field() for integer, string and string_sequence object types to ensure that the proper userspace-aware accesses are performed when loading those fields. Signed-off-by: Mathieu Desnoyers Change-Id: Ib8d4db5b7da5064e5897ab3802ab47e063607036 --- diff --git a/include/lttng/lttng-bytecode.h b/include/lttng/lttng-bytecode.h index cd0d8fbe..37c0e8a0 100644 --- a/include/lttng/lttng-bytecode.h +++ b/include/lttng/lttng-bytecode.h @@ -102,6 +102,7 @@ struct bytecode_get_index_data { size_t len; enum object_type type; bool rev_bo; /* reverse byte order */ + bool user; /* from userspace */ } elem; }; @@ -111,6 +112,7 @@ struct vstack_load { enum object_type object_type; const struct lttng_kernel_event_field *field; bool rev_bo; /* reverse byte order */ + bool user; /* from userspace */ }; struct vstack_entry { @@ -180,6 +182,7 @@ struct load_ptr { const void *ptr; size_t nr_elem; bool rev_bo; + bool user; /* from userspace */ /* Temporary place-holders for contexts. */ union { int64_t s64; @@ -199,7 +202,7 @@ struct estack_entry { const char __user *user_str; size_t seq_len; enum estack_string_literal_type literal_type; - int user; /* is string from userspace ? */ + bool user; /* is string from userspace ? */ } s; struct load_ptr ptr; } u; @@ -271,7 +274,9 @@ struct lttng_interpreter_output { struct { const char *str; + const char __user *user_str; size_t len; + bool user; /* is string from userspace ? */ } str; struct { const void *ptr; diff --git a/src/lttng-bytecode-interpreter.c b/src/lttng-bytecode-interpreter.c index 4b100ab8..4bb3a79a 100644 --- a/src/lttng-bytecode-interpreter.c +++ b/src/lttng-bytecode-interpreter.c @@ -16,6 +16,7 @@ #include #include #include +#include /* * get_char should be called with page fault handler disabled if it is expected @@ -284,6 +285,9 @@ static int context_get_index(struct lttng_kernel_probe_ctx *lttng_probe_ctx, switch (field->type->type) { case lttng_kernel_type_integer: + { + const struct lttng_kernel_type_integer *integer_type = lttng_kernel_get_type_integer(field->type); + ctx_field->get_value(ctx_field->priv, lttng_probe_ctx, &v); if (lttng_kernel_get_type_integer(field->type)->signedness) { ptr->object_type = OBJECT_TYPE_S64; @@ -294,8 +298,10 @@ static int context_get_index(struct lttng_kernel_probe_ctx *lttng_probe_ctx, ptr->u.u64 = v.u.s64; /* Cast. */ ptr->ptr = &ptr->u.u64; } - ptr->rev_bo = lttng_kernel_get_type_integer(field->type)->reverse_byte_order; + ptr->rev_bo = integer_type->reverse_byte_order; + ptr->user = integer_type->user; break; + } case lttng_kernel_type_enum: { const struct lttng_kernel_type_enum *enum_type = lttng_kernel_get_type_enum(field->type); @@ -312,11 +318,13 @@ static int context_get_index(struct lttng_kernel_probe_ctx *lttng_probe_ctx, ptr->ptr = &ptr->u.u64; } ptr->rev_bo = integer_type->reverse_byte_order; + ptr->user = integer_type->user; break; } case lttng_kernel_type_array: { const struct lttng_kernel_type_array *array_type = lttng_kernel_get_type_array(field->type); + const struct lttng_kernel_type_integer *integer_type; if (!lttng_kernel_type_is_bytewise_integer(array_type->elem_type)) { printk(KERN_WARNING "LTTng: bytecode: Array nesting only supports integer types.\n"); @@ -326,7 +334,9 @@ static int context_get_index(struct lttng_kernel_probe_ctx *lttng_probe_ctx, printk(KERN_WARNING "LTTng: bytecode: Only string arrays are supported for contexts.\n"); return -EINVAL; } + integer_type = lttng_kernel_get_type_integer(array_type->elem_type); ptr->object_type = OBJECT_TYPE_STRING; + ptr->user = integer_type->user; ctx_field->get_value(ctx_field->priv, lttng_probe_ctx, &v); ptr->ptr = v.u.str; break; @@ -334,6 +344,7 @@ static int context_get_index(struct lttng_kernel_probe_ctx *lttng_probe_ctx, case lttng_kernel_type_sequence: { const struct lttng_kernel_type_sequence *sequence_type = lttng_kernel_get_type_sequence(field->type); + const struct lttng_kernel_type_integer *integer_type; if (!lttng_kernel_type_is_bytewise_integer(sequence_type->elem_type)) { printk(KERN_WARNING "LTTng: bytecode: Sequence nesting only supports integer types.\n"); @@ -343,16 +354,23 @@ static int context_get_index(struct lttng_kernel_probe_ctx *lttng_probe_ctx, printk(KERN_WARNING "LTTng: bytecode: Only string sequences are supported for contexts.\n"); return -EINVAL; } + integer_type = lttng_kernel_get_type_integer(sequence_type->elem_type); ptr->object_type = OBJECT_TYPE_STRING; + ptr->user = integer_type->user; ctx_field->get_value(ctx_field->priv, lttng_probe_ctx, &v); ptr->ptr = v.u.str; break; } case lttng_kernel_type_string: + { + const struct lttng_kernel_type_string *string_type = lttng_kernel_get_type_string(field->type); + ptr->object_type = OBJECT_TYPE_STRING; + ptr->user = string_type->user; ctx_field->get_value(ctx_field->priv, lttng_probe_ctx, &v); ptr->ptr = v.u.str; break; + } case lttng_kernel_type_struct: printk(KERN_WARNING "LTTng: bytecode: Structure type cannot be loaded.\n"); return -EINVAL; @@ -388,6 +406,7 @@ static int dynamic_get_index(struct lttng_kernel_probe_ctx *lttng_probe_ctx, stack_top->u.ptr.ptr = ptr; stack_top->u.ptr.object_type = gid->elem.type; stack_top->u.ptr.rev_bo = gid->elem.rev_bo; + stack_top->u.ptr.user = gid->elem.user; BUG_ON(stack_top->u.ptr.field->type->type != lttng_kernel_type_array); stack_top->u.ptr.field = NULL; break; @@ -407,6 +426,7 @@ static int dynamic_get_index(struct lttng_kernel_probe_ctx *lttng_probe_ctx, stack_top->u.ptr.ptr = ptr; stack_top->u.ptr.object_type = gid->elem.type; stack_top->u.ptr.rev_bo = gid->elem.rev_bo; + stack_top->u.ptr.user = gid->elem.user; BUG_ON(stack_top->u.ptr.field->type->type != lttng_kernel_type_sequence); stack_top->u.ptr.field = NULL; break; @@ -443,6 +463,7 @@ static int dynamic_get_index(struct lttng_kernel_probe_ctx *lttng_probe_ctx, stack_top->u.ptr.type = LOAD_OBJECT; stack_top->u.ptr.field = gid->field; stack_top->u.ptr.rev_bo = gid->elem.rev_bo; + stack_top->u.ptr.user = gid->elem.user; break; } @@ -472,7 +493,12 @@ static int dynamic_load_field(struct estack_entry *stack_top) switch (stack_top->u.ptr.object_type) { case OBJECT_TYPE_S8: dbg_printk("op load field s8\n"); - stack_top->u.v = *(int8_t *) stack_top->u.ptr.ptr; + if (stack_top->u.ptr.user) { + if (lttng_copy_from_user_check_nofault(&stack_top->u.v, (int8_t __user *) stack_top->u.ptr.ptr, sizeof(int8_t))) + stack_top->u.v = 0; + } else { + stack_top->u.v = *(int8_t *) stack_top->u.ptr.ptr; + } stack_top->type = REG_S64; break; case OBJECT_TYPE_S16: @@ -480,7 +506,12 @@ static int dynamic_load_field(struct estack_entry *stack_top) int16_t tmp; dbg_printk("op load field s16\n"); - tmp = *(int16_t *) stack_top->u.ptr.ptr; + if (stack_top->u.ptr.user) { + if (lttng_copy_from_user_check_nofault(&tmp, (int16_t __user *) stack_top->u.ptr.ptr, sizeof(int16_t))) + tmp = 0; + } else { + tmp = *(int16_t *) stack_top->u.ptr.ptr; + } if (stack_top->u.ptr.rev_bo) __swab16s(&tmp); stack_top->u.v = tmp; @@ -492,7 +523,12 @@ static int dynamic_load_field(struct estack_entry *stack_top) int32_t tmp; dbg_printk("op load field s32\n"); - tmp = *(int32_t *) stack_top->u.ptr.ptr; + if (stack_top->u.ptr.user) { + if (lttng_copy_from_user_check_nofault(&tmp, (int32_t __user *) stack_top->u.ptr.ptr, sizeof(int32_t))) + tmp = 0; + } else { + tmp = *(int32_t *) stack_top->u.ptr.ptr; + } if (stack_top->u.ptr.rev_bo) __swab32s(&tmp); stack_top->u.v = tmp; @@ -504,7 +540,12 @@ static int dynamic_load_field(struct estack_entry *stack_top) int64_t tmp; dbg_printk("op load field s64\n"); - tmp = *(int64_t *) stack_top->u.ptr.ptr; + if (stack_top->u.ptr.user) { + if (lttng_copy_from_user_check_nofault(&tmp, (int64_t __user *) stack_top->u.ptr.ptr, sizeof(int64_t))) + tmp = 0; + } else { + tmp = *(int64_t *) stack_top->u.ptr.ptr; + } if (stack_top->u.ptr.rev_bo) __swab64s(&tmp); stack_top->u.v = tmp; @@ -516,6 +557,11 @@ static int dynamic_load_field(struct estack_entry *stack_top) int64_t tmp; dbg_printk("op load field signed enumeration\n"); + if (stack_top->u.ptr.user) { + dbg_printk("Bytecode warning: user enum unsupported.\n"); + ret = -EINVAL; + goto end; + } tmp = *(int64_t *) stack_top->u.ptr.ptr; if (stack_top->u.ptr.rev_bo) __swab64s(&tmp); @@ -525,7 +571,12 @@ static int dynamic_load_field(struct estack_entry *stack_top) } case OBJECT_TYPE_U8: dbg_printk("op load field u8\n"); - stack_top->u.v = *(uint8_t *) stack_top->u.ptr.ptr; + if (stack_top->u.ptr.user) { + if (lttng_copy_from_user_check_nofault(&stack_top->u.v, (uint8_t __user *) stack_top->u.ptr.ptr, sizeof(uint8_t))) + stack_top->u.v = 0; + } else { + stack_top->u.v = *(uint8_t *) stack_top->u.ptr.ptr; + } stack_top->type = REG_U64; break; case OBJECT_TYPE_U16: @@ -533,7 +584,12 @@ static int dynamic_load_field(struct estack_entry *stack_top) uint16_t tmp; dbg_printk("op load field u16\n"); - tmp = *(uint16_t *) stack_top->u.ptr.ptr; + if (stack_top->u.ptr.user) { + if (lttng_copy_from_user_check_nofault(&tmp, (uint16_t __user *) stack_top->u.ptr.ptr, sizeof(uint16_t))) + tmp = 0; + } else { + tmp = *(uint16_t *) stack_top->u.ptr.ptr; + } if (stack_top->u.ptr.rev_bo) __swab16s(&tmp); stack_top->u.v = tmp; @@ -545,7 +601,12 @@ static int dynamic_load_field(struct estack_entry *stack_top) uint32_t tmp; dbg_printk("op load field u32\n"); - tmp = *(uint32_t *) stack_top->u.ptr.ptr; + if (stack_top->u.ptr.user) { + if (lttng_copy_from_user_check_nofault(&tmp, (uint32_t __user *) stack_top->u.ptr.ptr, sizeof(uint32_t))) + tmp = 0; + } else { + tmp = *(uint32_t *) stack_top->u.ptr.ptr; + } if (stack_top->u.ptr.rev_bo) __swab32s(&tmp); stack_top->u.v = tmp; @@ -557,7 +618,12 @@ static int dynamic_load_field(struct estack_entry *stack_top) uint64_t tmp; dbg_printk("op load field u64\n"); - tmp = *(uint64_t *) stack_top->u.ptr.ptr; + if (stack_top->u.ptr.user) { + if (lttng_copy_from_user_check_nofault(&tmp, (uint64_t __user *) stack_top->u.ptr.ptr, sizeof(uint64_t))) + tmp = 0; + } else { + tmp = *(uint64_t *) stack_top->u.ptr.ptr; + } if (stack_top->u.ptr.rev_bo) __swab64s(&tmp); stack_top->u.v = tmp; @@ -569,6 +635,11 @@ static int dynamic_load_field(struct estack_entry *stack_top) uint64_t tmp; dbg_printk("op load field unsigned enumeration\n"); + if (stack_top->u.ptr.user) { + dbg_printk("Bytecode warning: user enum unsupported.\n"); + ret = -EINVAL; + goto end; + } tmp = *(uint64_t *) stack_top->u.ptr.ptr; if (stack_top->u.ptr.rev_bo) __swab64s(&tmp); @@ -578,19 +649,30 @@ static int dynamic_load_field(struct estack_entry *stack_top) } case OBJECT_TYPE_STRING: { - const char *str; + dbg_printk("op load field string: user=%d\n", stack_top->u.ptr.user); + if (stack_top->u.ptr.user) { + const char __user *user_str = (const char __user *) stack_top->u.ptr.ptr; - dbg_printk("op load field string\n"); - str = (const char *) stack_top->u.ptr.ptr; - stack_top->u.s.str = str; - if (unlikely(!stack_top->u.s.str)) { - dbg_printk("Bytecode warning: loading a NULL string.\n"); - ret = -EINVAL; - goto end; + stack_top->u.s.user_str = user_str; + if (unlikely(!stack_top->u.s.user_str)) { + dbg_printk("Bytecode warning: loading a NULL user string.\n"); + ret = -EINVAL; + goto end; + } + stack_top->u.s.user = 1; + } else { + const char *str = (const char *) stack_top->u.ptr.ptr; + + stack_top->u.s.str = str; + if (unlikely(!stack_top->u.s.str)) { + dbg_printk("Bytecode warning: loading a NULL string.\n"); + ret = -EINVAL; + goto end; + } + stack_top->u.s.user = 0; } stack_top->u.s.seq_len = LTTNG_SIZE_MAX; - stack_top->u.s.literal_type = - ESTACK_STRING_LITERAL_TYPE_NONE; + stack_top->u.s.literal_type = ESTACK_STRING_LITERAL_TYPE_NONE; stack_top->type = REG_STRING; break; } @@ -598,17 +680,27 @@ static int dynamic_load_field(struct estack_entry *stack_top) { const char *ptr; - dbg_printk("op load field string sequence\n"); + dbg_printk("op load field string sequence: user=%d\n", stack_top->u.ptr.user); ptr = stack_top->u.ptr.ptr; stack_top->u.s.seq_len = *(unsigned long *) ptr; - stack_top->u.s.str = *(const char **) (ptr + sizeof(unsigned long)); - if (unlikely(!stack_top->u.s.str)) { - dbg_printk("Bytecode warning: loading a NULL sequence.\n"); - ret = -EINVAL; - goto end; + if (stack_top->u.ptr.user) { + stack_top->u.s.user_str = *(const char __user **) (ptr + sizeof(unsigned long)); + if (unlikely(!stack_top->u.s.user_str)) { + dbg_printk("Bytecode warning: loading a NULL user sequence.\n"); + ret = -EINVAL; + goto end; + } + stack_top->u.s.user = 1; + } else { + stack_top->u.s.str = *(const char **) (ptr + sizeof(unsigned long)); + if (unlikely(!stack_top->u.s.str)) { + dbg_printk("Bytecode warning: loading a NULL sequence.\n"); + ret = -EINVAL; + goto end; + } + stack_top->u.s.user = 0; } - stack_top->u.s.literal_type = - ESTACK_STRING_LITERAL_TYPE_NONE; + stack_top->u.s.literal_type = ESTACK_STRING_LITERAL_TYPE_NONE; stack_top->type = REG_STRING; break; } @@ -654,8 +746,13 @@ again: break; case REG_STRING: output->type = LTTNG_INTERPRETER_TYPE_STRING; - output->u.str.str = ax->u.s.str; output->u.str.len = ax->u.s.seq_len; + output->u.str.user = ax->u.s.user; + if (ax->u.s.user) { + output->u.str.user_str = ax->u.s.user_str; + } else { + output->u.str.str = ax->u.s.str; + } break; case REG_PTR: switch (ax->u.ptr.object_type) { @@ -1791,6 +1888,7 @@ int lttng_bytecode_interpret(struct lttng_kernel_bytecode_runtime *kernel_byteco estack_ax(stack, top)->u.s.literal_type = ESTACK_STRING_LITERAL_TYPE_NONE; estack_ax(stack, top)->type = REG_STRING; + estack_ax(stack, top)->u.s.user = 0; next_pc += sizeof(struct load_op); PO; } @@ -1811,6 +1909,7 @@ int lttng_bytecode_interpret(struct lttng_kernel_bytecode_runtime *kernel_byteco estack_ax(stack, top)->u.s.literal_type = ESTACK_STRING_LITERAL_TYPE_NONE; estack_ax(stack, top)->type = REG_STRING; + estack_ax(stack, top)->u.s.user = 0; next_pc += sizeof(struct load_op); PO; } diff --git a/src/lttng-bytecode-specialize.c b/src/lttng-bytecode-specialize.c index f8b5f19d..936e342d 100644 --- a/src/lttng-bytecode-specialize.c +++ b/src/lttng-bytecode-specialize.c @@ -77,57 +77,68 @@ static int specialize_load_field(struct vstack_entry *stack_top, case OBJECT_TYPE_S8: dbg_printk("op load field s8\n"); stack_top->type = REG_S64; - if (!stack_top->load.rev_bo) + if (!stack_top->load.user) insn->op = BYTECODE_OP_LOAD_FIELD_S8; break; case OBJECT_TYPE_S16: dbg_printk("op load field s16\n"); stack_top->type = REG_S64; - if (!stack_top->load.rev_bo) + if (!stack_top->load.rev_bo && !stack_top->load.user) insn->op = BYTECODE_OP_LOAD_FIELD_S16; break; case OBJECT_TYPE_S32: dbg_printk("op load field s32\n"); stack_top->type = REG_S64; - if (!stack_top->load.rev_bo) + if (!stack_top->load.rev_bo && !stack_top->load.user) insn->op = BYTECODE_OP_LOAD_FIELD_S32; break; case OBJECT_TYPE_S64: dbg_printk("op load field s64\n"); stack_top->type = REG_S64; - if (!stack_top->load.rev_bo) + if (!stack_top->load.rev_bo && !stack_top->load.user) insn->op = BYTECODE_OP_LOAD_FIELD_S64; break; case OBJECT_TYPE_SIGNED_ENUM: dbg_printk("op load field signed enumeration\n"); - stack_top->type = REG_PTR; + if (stack_top->load.user) { + printk(KERN_WARNING "LTTng: bytecode: user enum unsupported\n"); + ret = -EINVAL; + goto end; + } + stack_top->type = REG_S64; break; case OBJECT_TYPE_U8: dbg_printk("op load field u8\n"); stack_top->type = REG_S64; - insn->op = BYTECODE_OP_LOAD_FIELD_U8; + if (!stack_top->load.user) + insn->op = BYTECODE_OP_LOAD_FIELD_U8; break; case OBJECT_TYPE_U16: dbg_printk("op load field u16\n"); stack_top->type = REG_S64; - if (!stack_top->load.rev_bo) + if (!stack_top->load.rev_bo && !stack_top->load.user) insn->op = BYTECODE_OP_LOAD_FIELD_U16; break; case OBJECT_TYPE_U32: dbg_printk("op load field u32\n"); stack_top->type = REG_S64; - if (!stack_top->load.rev_bo) + if (!stack_top->load.rev_bo && !stack_top->load.user) insn->op = BYTECODE_OP_LOAD_FIELD_U32; break; case OBJECT_TYPE_U64: dbg_printk("op load field u64\n"); stack_top->type = REG_S64; - if (!stack_top->load.rev_bo) + if (!stack_top->load.rev_bo && !stack_top->load.user) insn->op = BYTECODE_OP_LOAD_FIELD_U64; break; case OBJECT_TYPE_UNSIGNED_ENUM: dbg_printk("op load field unsigned enumeration\n"); - stack_top->type = REG_PTR; + if (stack_top->load.user) { + printk(KERN_WARNING "LTTng: bytecode: user enum unsupported\n"); + ret = -EINVAL; + goto end; + } + stack_top->type = REG_U64; break; case OBJECT_TYPE_DOUBLE: printk(KERN_WARNING "LTTng: bytecode: Double type unsupported\n\n"); @@ -136,12 +147,14 @@ static int specialize_load_field(struct vstack_entry *stack_top, case OBJECT_TYPE_STRING: dbg_printk("op load field string\n"); stack_top->type = REG_STRING; - insn->op = BYTECODE_OP_LOAD_FIELD_STRING; + if (!stack_top->load.user) + insn->op = BYTECODE_OP_LOAD_FIELD_STRING; break; case OBJECT_TYPE_STRING_SEQUENCE: dbg_printk("op load field string sequence\n"); stack_top->type = REG_STRING; - insn->op = BYTECODE_OP_LOAD_FIELD_SEQUENCE; + if (!stack_top->load.user) + insn->op = BYTECODE_OP_LOAD_FIELD_SEQUENCE; break; case OBJECT_TYPE_DYNAMIC: ret = -EINVAL; @@ -237,9 +250,8 @@ static int specialize_get_index(struct bytecode_runtime *runtime, gid.array_len = num_elems * (elem_len / CHAR_BIT); gid.elem.type = stack_top->load.object_type; gid.elem.len = elem_len; - if (integer_type->reverse_byte_order) - gid.elem.rev_bo = true; - stack_top->load.rev_bo = gid.elem.rev_bo; + stack_top->load.rev_bo = gid.elem.rev_bo = integer_type->reverse_byte_order; + stack_top->load.user = gid.elem.user = integer_type->user; break; } case OBJECT_TYPE_SEQUENCE: @@ -266,9 +278,8 @@ static int specialize_get_index(struct bytecode_runtime *runtime, gid.offset = index * (elem_len / CHAR_BIT); gid.elem.type = stack_top->load.object_type; gid.elem.len = elem_len; - if (integer_type->reverse_byte_order) - gid.elem.rev_bo = true; - stack_top->load.rev_bo = gid.elem.rev_bo; + stack_top->load.rev_bo = gid.elem.rev_bo = integer_type->reverse_byte_order; + stack_top->load.user = gid.elem.user = integer_type->user; break; } case OBJECT_TYPE_STRUCT: @@ -332,12 +343,17 @@ static int specialize_load_object(const struct lttng_kernel_event_field *field, switch (field->type->type) { case lttng_kernel_type_integer: - if (lttng_kernel_get_type_integer(field->type)->signedness) + { + const struct lttng_kernel_type_integer *integer_type = lttng_kernel_get_type_integer(field->type); + + if (integer_type->signedness) load->object_type = OBJECT_TYPE_S64; else load->object_type = OBJECT_TYPE_U64; - load->rev_bo = false; + load->rev_bo = integer_type->reverse_byte_order; + load->user = integer_type->user; break; + } case lttng_kernel_type_enum: { const struct lttng_kernel_type_enum *enum_type = lttng_kernel_get_type_enum(field->type); @@ -347,25 +363,30 @@ static int specialize_load_object(const struct lttng_kernel_event_field *field, load->object_type = OBJECT_TYPE_SIGNED_ENUM; else load->object_type = OBJECT_TYPE_UNSIGNED_ENUM; - load->rev_bo = false; + load->rev_bo = integer_type->reverse_byte_order; + load->user = integer_type->user; break; } case lttng_kernel_type_array: { const struct lttng_kernel_type_array *array_type = lttng_kernel_get_type_array(field->type); + const struct lttng_kernel_type_integer *integer_type; if (!lttng_kernel_type_is_bytewise_integer(array_type->elem_type)) { printk(KERN_WARNING "LTTng: bytecode: Array nesting only supports integer types.\n"); return -EINVAL; } + integer_type = lttng_kernel_get_type_integer(array_type->elem_type); if (is_context) { load->object_type = OBJECT_TYPE_STRING; + load->user = integer_type->user; } else { if (array_type->encoding == lttng_kernel_string_encoding_none) { load->object_type = OBJECT_TYPE_ARRAY; load->field = field; } else { load->object_type = OBJECT_TYPE_STRING_SEQUENCE; + load->user = integer_type->user; } } break; @@ -373,26 +394,35 @@ static int specialize_load_object(const struct lttng_kernel_event_field *field, case lttng_kernel_type_sequence: { const struct lttng_kernel_type_sequence *sequence_type = lttng_kernel_get_type_sequence(field->type); + const struct lttng_kernel_type_integer *integer_type; if (!lttng_kernel_type_is_bytewise_integer(sequence_type->elem_type)) { printk(KERN_WARNING "LTTng: bytecode: Sequence nesting only supports integer types.\n"); return -EINVAL; } + integer_type = lttng_kernel_get_type_integer(sequence_type->elem_type); if (is_context) { load->object_type = OBJECT_TYPE_STRING; + load->user = integer_type->user; } else { if (sequence_type->encoding == lttng_kernel_string_encoding_none) { load->object_type = OBJECT_TYPE_SEQUENCE; load->field = field; } else { load->object_type = OBJECT_TYPE_STRING_SEQUENCE; + load->user = integer_type->user; } } break; } case lttng_kernel_type_string: + { + const struct lttng_kernel_type_string *string_type = lttng_kernel_get_type_string(field->type); + load->object_type = OBJECT_TYPE_STRING; + load->user = string_type->user; break; + } case lttng_kernel_type_struct: printk(KERN_WARNING "LTTng: bytecode: Structure type cannot be loaded.\n"); return -EINVAL; @@ -432,6 +462,7 @@ static int specialize_context_lookup(struct lttng_kernel_ctx *ctx, gid.ctx_index = idx; gid.elem.type = load->object_type; gid.elem.rev_bo = load->rev_bo; + gid.elem.user = load->user; gid.field = field; data_offset = bytecode_push_data(runtime, &gid, __alignof__(gid), sizeof(gid)); @@ -503,6 +534,7 @@ static int specialize_payload_lookup(const struct lttng_kernel_event_desc *event gid.offset = field_offset; gid.elem.type = load->object_type; gid.elem.rev_bo = load->rev_bo; + gid.elem.user = load->user; gid.field = field; data_offset = bytecode_push_data(runtime, &gid, __alignof__(gid), sizeof(gid));