The instructions for recursive traversal through composed types
are used by the 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.
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.
This prevents events with userspace input arguments (e.g. pipe2 system
call fildes field) from oopsing the kernel or reading arbitrary kernel
memory when used by the filter bytecode.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: Id9c373ff1a70e162ba913e5592437249a4947c96
#include <lttng-filter.h>
#include <lttng-string-utils.h>
#include <lttng-filter.h>
#include <lttng-string-utils.h>
+#include <probes/lttng-probe-user.h>
LTTNG_STACK_FRAME_NON_STANDARD(lttng_filter_interpret_bytecode);
LTTNG_STACK_FRAME_NON_STANDARD(lttng_filter_interpret_bytecode);
ptr->ptr = &ptr->u.u64;
}
ptr->rev_bo = field->type.u.basic.integer.reverse_byte_order;
ptr->ptr = &ptr->u.u64;
}
ptr->rev_bo = field->type.u.basic.integer.reverse_byte_order;
+ ptr->user = field->type.u.basic.integer.user;
break;
case atype_enum:
{
break;
case atype_enum:
{
ptr->ptr = &ptr->u.u64;
}
ptr->rev_bo = itype->reverse_byte_order;
ptr->ptr = &ptr->u.u64;
}
ptr->rev_bo = itype->reverse_byte_order;
+ ptr->user = itype->user;
break;
}
case atype_array:
break;
}
case atype_array:
ptr->object_type = OBJECT_TYPE_STRING;
ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
ptr->ptr = v.str;
ptr->object_type = OBJECT_TYPE_STRING;
ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
ptr->ptr = v.str;
+ ptr->user = field->type.u.array.elem_type.u.basic.integer.user;
break;
case atype_sequence:
if (field->type.u.sequence.elem_type.atype != atype_integer) {
break;
case atype_sequence:
if (field->type.u.sequence.elem_type.atype != atype_integer) {
ptr->object_type = OBJECT_TYPE_STRING;
ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
ptr->ptr = v.str;
ptr->object_type = OBJECT_TYPE_STRING;
ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
ptr->ptr = v.str;
+ ptr->user = field->type.u.sequence.elem_type.u.basic.integer.user;
break;
case atype_array_bitfield:
printk(KERN_WARNING "Bitfield array type is not supported.\n");
break;
case atype_array_bitfield:
printk(KERN_WARNING "Bitfield array type is not supported.\n");
ptr->object_type = OBJECT_TYPE_STRING;
ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
ptr->ptr = v.str;
ptr->object_type = OBJECT_TYPE_STRING;
ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
ptr->ptr = v.str;
+ ptr->user = field->type.u.basic.string.user;
break;
case atype_struct:
printk(KERN_WARNING "Structure type cannot be loaded.\n");
break;
case atype_struct:
printk(KERN_WARNING "Structure type cannot be loaded.\n");
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.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;
/* field is only used for types nested within variants. */
stack_top->u.ptr.field = NULL;
break;
/* field is only used for types nested within variants. */
stack_top->u.ptr.field = NULL;
break;
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.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;
/* field is only used for types nested within variants. */
stack_top->u.ptr.field = NULL;
break;
/* field is only used for types nested within variants. */
stack_top->u.ptr.field = NULL;
break;
/* field is only used for types nested within variants. */
stack_top->u.ptr.field = NULL;
stack_top->u.ptr.rev_bo = gid->elem.rev_bo;
/* field is only used for types nested within variants. */
stack_top->u.ptr.field = NULL;
stack_top->u.ptr.rev_bo = gid->elem.rev_bo;
+ stack_top->u.ptr.user = gid->elem.user;
switch (stack_top->u.ptr.object_type) {
case OBJECT_TYPE_S8:
dbg_printk("op load field s8\n");
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;
+ }
break;
case OBJECT_TYPE_S16:
{
int16_t tmp;
dbg_printk("op load field s16\n");
break;
case OBJECT_TYPE_S16:
{
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;
if (stack_top->u.ptr.rev_bo)
__swab16s(&tmp);
stack_top->u.v = tmp;
int32_t tmp;
dbg_printk("op load field s32\n");
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;
if (stack_top->u.ptr.rev_bo)
__swab32s(&tmp);
stack_top->u.v = tmp;
int64_t tmp;
dbg_printk("op load field s64\n");
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;
if (stack_top->u.ptr.rev_bo)
__swab64s(&tmp);
stack_top->u.v = tmp;
}
case OBJECT_TYPE_U8:
dbg_printk("op load field u8\n");
}
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;
+ }
break;
case OBJECT_TYPE_U16:
{
uint16_t tmp;
dbg_printk("op load field s16\n");
break;
case OBJECT_TYPE_U16:
{
uint16_t tmp;
dbg_printk("op load field s16\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;
if (stack_top->u.ptr.rev_bo)
__swab16s(&tmp);
stack_top->u.v = tmp;
uint32_t tmp;
dbg_printk("op load field u32\n");
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;
if (stack_top->u.ptr.rev_bo)
__swab32s(&tmp);
stack_top->u.v = tmp;
uint64_t tmp;
dbg_printk("op load field u64\n");
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;
if (stack_top->u.ptr.rev_bo)
__swab64s(&tmp);
stack_top->u.v = tmp;
}
case OBJECT_TYPE_STRING:
{
}
case OBJECT_TYPE_STRING:
{
+ 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("Filter 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.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;
break;
}
case OBJECT_TYPE_STRING_SEQUENCE:
break;
}
case OBJECT_TYPE_STRING_SEQUENCE:
dbg_printk("op load field string sequence\n");
ptr = stack_top->u.ptr.ptr;
stack_top->u.s.seq_len = *(unsigned long *) ptr;
dbg_printk("op load field string sequence\n");
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("Filter 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;
break;
}
case OBJECT_TYPE_DYNAMIC:
break;
}
case OBJECT_TYPE_DYNAMIC:
estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
estack_ax(stack, top)->u.s.literal_type =
ESTACK_STRING_LITERAL_TYPE_NONE;
estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
estack_ax(stack, top)->u.s.literal_type =
ESTACK_STRING_LITERAL_TYPE_NONE;
+ estack_ax(stack, top)->u.s.user = 0;
next_pc += sizeof(struct load_op);
PO;
}
next_pc += sizeof(struct load_op);
PO;
}
}
estack_ax(stack, top)->u.s.literal_type =
ESTACK_STRING_LITERAL_TYPE_NONE;
}
estack_ax(stack, top)->u.s.literal_type =
ESTACK_STRING_LITERAL_TYPE_NONE;
+ estack_ax(stack, top)->u.s.user = 0;
next_pc += sizeof(struct load_op);
PO;
}
next_pc += sizeof(struct load_op);
PO;
}
case OBJECT_TYPE_S8:
dbg_printk("op load field s8\n");
stack_top->type = REG_S64;
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 = FILTER_OP_LOAD_FIELD_S8;
break;
case OBJECT_TYPE_S16:
dbg_printk("op load field s16\n");
stack_top->type = REG_S64;
insn->op = FILTER_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 = FILTER_OP_LOAD_FIELD_S16;
break;
case OBJECT_TYPE_S32:
dbg_printk("op load field s32\n");
stack_top->type = REG_S64;
insn->op = FILTER_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 = FILTER_OP_LOAD_FIELD_S32;
break;
case OBJECT_TYPE_S64:
dbg_printk("op load field s64\n");
stack_top->type = REG_S64;
insn->op = FILTER_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 = FILTER_OP_LOAD_FIELD_S64;
break;
case OBJECT_TYPE_U8:
dbg_printk("op load field u8\n");
stack_top->type = REG_S64;
insn->op = FILTER_OP_LOAD_FIELD_S64;
break;
case OBJECT_TYPE_U8:
dbg_printk("op load field u8\n");
stack_top->type = REG_S64;
- insn->op = FILTER_OP_LOAD_FIELD_U8;
+ if (!stack_top->load.user)
+ insn->op = FILTER_OP_LOAD_FIELD_U8;
break;
case OBJECT_TYPE_U16:
dbg_printk("op load field u16\n");
stack_top->type = REG_S64;
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 = FILTER_OP_LOAD_FIELD_U16;
break;
case OBJECT_TYPE_U32:
dbg_printk("op load field u32\n");
stack_top->type = REG_S64;
insn->op = FILTER_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 = FILTER_OP_LOAD_FIELD_U32;
break;
case OBJECT_TYPE_U64:
dbg_printk("op load field u64\n");
stack_top->type = REG_S64;
insn->op = FILTER_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 = FILTER_OP_LOAD_FIELD_U64;
break;
case OBJECT_TYPE_DOUBLE:
insn->op = FILTER_OP_LOAD_FIELD_U64;
break;
case OBJECT_TYPE_DOUBLE:
case OBJECT_TYPE_STRING:
dbg_printk("op load field string\n");
stack_top->type = REG_STRING;
case OBJECT_TYPE_STRING:
dbg_printk("op load field string\n");
stack_top->type = REG_STRING;
- insn->op = FILTER_OP_LOAD_FIELD_STRING;
+ if (!stack_top->load.user)
+ insn->op = FILTER_OP_LOAD_FIELD_STRING;
break;
case OBJECT_TYPE_STRING_SEQUENCE:
dbg_printk("op load field string sequence\n");
stack_top->type = REG_STRING;
break;
case OBJECT_TYPE_STRING_SEQUENCE:
dbg_printk("op load field string sequence\n");
stack_top->type = REG_STRING;
- insn->op = FILTER_OP_LOAD_FIELD_SEQUENCE;
+ if (!stack_top->load.user)
+ insn->op = FILTER_OP_LOAD_FIELD_SEQUENCE;
break;
case OBJECT_TYPE_DYNAMIC:
ret = -EINVAL;
break;
case OBJECT_TYPE_DYNAMIC:
ret = -EINVAL;
gid.array_len = num_elems * (elem_len / CHAR_BIT);
gid.elem.type = stack_top->load.object_type;
gid.elem.len = elem_len;
gid.array_len = num_elems * (elem_len / CHAR_BIT);
gid.elem.type = stack_top->load.object_type;
gid.elem.len = elem_len;
- if (field->type.u.array.elem_type.u.basic.integer.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 = field->type.u.array.elem_type.u.basic.integer.reverse_byte_order;
+ stack_top->load.user = gid.elem.user = field->type.u.array.elem_type.u.basic.integer.user;
break;
}
case OBJECT_TYPE_SEQUENCE:
break;
}
case OBJECT_TYPE_SEQUENCE:
gid.offset = index * (elem_len / CHAR_BIT);
gid.elem.type = stack_top->load.object_type;
gid.elem.len = elem_len;
gid.offset = index * (elem_len / CHAR_BIT);
gid.elem.type = stack_top->load.object_type;
gid.elem.len = elem_len;
- if (field->type.u.sequence.elem_type.u.basic.integer.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 = field->type.u.sequence.elem_type.u.basic.integer.reverse_byte_order;
+ stack_top->load.user = gid.elem.user = field->type.u.sequence.elem_type.u.basic.integer.user;
break;
}
case OBJECT_TYPE_STRUCT:
break;
}
case OBJECT_TYPE_STRUCT:
load->object_type = OBJECT_TYPE_S64;
else
load->object_type = OBJECT_TYPE_U64;
load->object_type = OBJECT_TYPE_S64;
else
load->object_type = OBJECT_TYPE_U64;
+ load->rev_bo = field->type.u.basic.integer.reverse_byte_order;
+ load->user = field->type.u.basic.integer.user;
break;
case atype_enum:
{
break;
case atype_enum:
{
load->object_type = OBJECT_TYPE_S64;
else
load->object_type = OBJECT_TYPE_U64;
load->object_type = OBJECT_TYPE_S64;
else
load->object_type = OBJECT_TYPE_U64;
+ load->rev_bo = itype->reverse_byte_order;
+ load->user = itype->user;
break;
}
case atype_array:
break;
}
case atype_array:
}
if (is_context) {
load->object_type = OBJECT_TYPE_STRING;
}
if (is_context) {
load->object_type = OBJECT_TYPE_STRING;
+ load->user = field->type.u.array.elem_type.u.basic.integer.user;
} else {
if (field->type.u.array.elem_type.u.basic.integer.encoding == lttng_encode_none) {
load->object_type = OBJECT_TYPE_ARRAY;
load->field = field;
} else {
load->object_type = OBJECT_TYPE_STRING_SEQUENCE;
} else {
if (field->type.u.array.elem_type.u.basic.integer.encoding == lttng_encode_none) {
load->object_type = OBJECT_TYPE_ARRAY;
load->field = field;
} else {
load->object_type = OBJECT_TYPE_STRING_SEQUENCE;
+ load->user = field->type.u.array.elem_type.u.basic.integer.user;
}
if (is_context) {
load->object_type = OBJECT_TYPE_STRING;
}
if (is_context) {
load->object_type = OBJECT_TYPE_STRING;
+ load->user = field->type.u.sequence.elem_type.u.basic.integer.user;
} else {
if (field->type.u.sequence.elem_type.u.basic.integer.encoding == lttng_encode_none) {
load->object_type = OBJECT_TYPE_SEQUENCE;
load->field = field;
} else {
load->object_type = OBJECT_TYPE_STRING_SEQUENCE;
} else {
if (field->type.u.sequence.elem_type.u.basic.integer.encoding == lttng_encode_none) {
load->object_type = OBJECT_TYPE_SEQUENCE;
load->field = field;
} else {
load->object_type = OBJECT_TYPE_STRING_SEQUENCE;
+ load->user = field->type.u.sequence.elem_type.u.basic.integer.user;
return -EINVAL;
case atype_string:
load->object_type = OBJECT_TYPE_STRING;
return -EINVAL;
case atype_string:
load->object_type = OBJECT_TYPE_STRING;
+ load->user = field->type.u.basic.string.user;
break;
case atype_struct:
printk(KERN_WARNING "Structure type cannot be loaded.\n");
break;
case atype_struct:
printk(KERN_WARNING "Structure type cannot be loaded.\n");
gid.ctx_index = idx;
gid.elem.type = load->object_type;
gid.elem.rev_bo = load->rev_bo;
gid.ctx_index = idx;
gid.elem.type = load->object_type;
gid.elem.rev_bo = load->rev_bo;
+ gid.elem.user = load->user;
data_offset = bytecode_push_data(runtime, &gid,
__alignof__(gid), sizeof(gid));
if (data_offset < 0) {
data_offset = bytecode_push_data(runtime, &gid,
__alignof__(gid), sizeof(gid));
if (data_offset < 0) {
gid.offset = field_offset;
gid.elem.type = load->object_type;
gid.elem.rev_bo = load->rev_bo;
gid.offset = field_offset;
gid.elem.type = load->object_type;
gid.elem.rev_bo = load->rev_bo;
+ gid.elem.user = load->user;
data_offset = bytecode_push_data(runtime, &gid,
__alignof__(gid), sizeof(gid));
if (data_offset < 0) {
data_offset = bytecode_push_data(runtime, &gid,
__alignof__(gid), sizeof(gid));
if (data_offset < 0) {
size_t len;
enum object_type type;
bool rev_bo; /* reverse byte order */
size_t len;
enum object_type type;
bool rev_bo; /* reverse byte order */
+ bool user; /* from userspace */
enum object_type object_type;
const struct lttng_event_field *field;
bool rev_bo; /* reverse byte order */
enum object_type object_type;
const struct lttng_event_field *field;
bool rev_bo; /* reverse byte order */
+ bool user; /* from userspace */
enum object_type object_type;
const void *ptr;
bool rev_bo;
enum object_type object_type;
const void *ptr;
bool rev_bo;
+ bool user; /* from userspace */
/* Temporary place-holders for contexts. */
union {
int64_t s64;
/* Temporary place-holders for contexts. */
union {
int64_t s64;
const char __user *user_str;
size_t seq_len;
enum estack_string_literal_type literal_type;
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;
} s;
struct load_ptr ptr;
} u;