offset = header_len;
session_name_view = lttng_buffer_view_from_view(payload, offset,
header.session_name_len);
+ if (!lttng_buffer_view_is_valid(&session_name_view)) {
+ ERR("Invalid payload in \"cmd_create_session_2_11\": buffer too short to contain session name");
+ ret = -1;
+ goto error;
+ }
+
offset += header.session_name_len;
hostname_view = lttng_buffer_view_from_view(payload,
offset, header.hostname_len);
+ if (!lttng_buffer_view_is_valid(&hostname_view)) {
+ ERR("Invalid payload in \"cmd_create_session_2_11\": buffer too short to contain hostname");
+ ret = -1;
+ goto error;
+ }
+
offset += header.hostname_len;
base_path_view = lttng_buffer_view_from_view(payload,
offset, header.base_path_len);
+ if (header.base_path_len > 0 && !lttng_buffer_view_is_valid(&base_path_view)) {
+ ERR("Invalid payload in \"cmd_create_session_2_11\": buffer too short to contain base path");
+ ret = -1;
+ goto error;
+ }
/* Validate that names are NULL terminated. */
if (session_name_view.data[session_name_view.size - 1] != '\0') {
/* Validate that names are (NULL terminated. */
channel_name_view = lttng_buffer_view_from_view(payload, header_len,
- header.channel_name_len);
- pathname_view = lttng_buffer_view_from_view(payload,
- header_len + header.channel_name_len, header.pathname_len);
+ header.channel_name_len);
+ if (!lttng_buffer_view_is_valid(&channel_name_view)) {
+ ERR("Invalid payload received in \"cmd_recv_stream_2_11\": buffer too short for channel name");
+ ret = -1;
+ goto error;
+ }
if (channel_name_view.data[channel_name_view.size - 1] != '\0') {
ERR("cmd_recv_stream_2_11 channel_name is invalid (not NULL terminated)");
goto error;
}
+ pathname_view = lttng_buffer_view_from_view(payload,
+ header_len + header.channel_name_len, header.pathname_len);
+ if (!lttng_buffer_view_is_valid(&pathname_view)) {
+ ERR("Invalid payload received in \"cmd_recv_stream_2_11\": buffer too short for path name");
+ ret = -1;
+ goto error;
+ }
+
if (pathname_view.data[pathname_view.size - 1] != '\0') {
ERR("cmd_recv_stream_2_11 patname is invalid (not NULL terminated)");
ret = -1;
packet_view = lttng_buffer_view_from_view(payload,
sizeof(metadata_payload_header), metadata_payload_size);
- if (!packet_view.data) {
+ if (!lttng_buffer_view_is_valid(&packet_view)) {
ERR("Invalid metadata packet length announced by header");
ret = -1;
goto end_put;
struct lttcomm_relayd_create_trace_chunk *msg;
struct lttcomm_relayd_generic_reply reply = {};
struct lttng_buffer_view header_view;
- struct lttng_buffer_view chunk_name_view;
struct lttng_trace_chunk *chunk = NULL, *published_chunk = NULL;
enum lttng_error_code reply_code = LTTNG_OK;
enum lttng_trace_chunk_status chunk_status;
}
header_view = lttng_buffer_view_from_view(payload, 0, sizeof(*msg));
- if (!header_view.data) {
+ if (!lttng_buffer_view_is_valid(&header_view)) {
ERR("Failed to receive payload of chunk creation command");
ret = -1;
goto end_no_reply;
if (msg->override_name_length) {
const char *name;
+ const struct lttng_buffer_view chunk_name_view =
+ lttng_buffer_view_from_view(payload,
+ sizeof(*msg),
+ msg->override_name_length);
+
+ if (!lttng_buffer_view_is_valid(&chunk_name_view)) {
+ ERR("Invalid payload of chunk creation command (protocol error): buffer too short for expected name length");
+ ret = -1;
+ reply_code = LTTNG_ERR_INVALID;
+ goto end;
+ }
- chunk_name_view = lttng_buffer_view_from_view(payload,
- sizeof(*msg),
- msg->override_name_length);
name = chunk_name_view.data;
- if (!name || name[msg->override_name_length - 1]) {
- ERR("Failed to receive payload of chunk creation command");
+ if (name[msg->override_name_length - 1]) {
+ ERR("Invalid payload of chunk creation command (protocol error): name is not null-terminated");
ret = -1;
reply_code = LTTNG_ERR_INVALID;
goto end;
}
header_view = lttng_buffer_view_from_view(payload, 0, sizeof(*msg));
- if (!header_view.data) {
+ if (!lttng_buffer_view_is_valid(&header_view)) {
ERR("Failed to receive payload of chunk close command");
ret = -1;
goto end_no_reply;
}
header_view = lttng_buffer_view_from_view(payload, 0, sizeof(*msg));
- if (!header_view.data) {
+ if (!lttng_buffer_view_is_valid(&header_view)) {
ERR("Failed to receive payload of chunk exists command");
ret = -1;
goto end_no_reply;
uint64_t result_flags = 0;
header_view = lttng_buffer_view_from_view(payload, 0, sizeof(*msg));
- if (!header_view.data) {
+ if (!lttng_buffer_view_is_valid(&header_view)) {
ERR("Failed to receive payload of chunk close command");
ret = -1;
goto end_no_reply;
payload_view = lttng_buffer_view_from_dynamic_buffer(
&payload, 0, name_len);
+ if (name_len > 0 && !lttng_buffer_view_is_valid(&payload_view)) {
+ ret = LTTNG_ERR_INVALID_PROTOCOL;
+ goto error_add_remove_tracker_value;
+ }
+
/*
* Validate the value type and domains are legal for the process
* attribute tracker that is specified and convert the value to
&payload,
0,
cmd_ctx->lsm.u.create_session.home_dir_size);
+ if (cmd_ctx->lsm.u.create_session.home_dir_size > 0 &&
+ !lttng_buffer_view_is_valid(&home_dir_view)) {
+ ERR("Invalid payload in \"create session\" command: buffer too short to contain home directory");
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ goto error;
+ }
+
session_descriptor_view = lttng_buffer_view_from_dynamic_buffer(
&payload,
cmd_ctx->lsm.u.create_session.home_dir_size,
cmd_ctx->lsm.u.create_session.session_descriptor_size);
+ if (!lttng_buffer_view_is_valid(&session_descriptor_view)) {
+ ERR("Invalid payload in \"create session\" command: buffer too short to contain session descriptor");
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ goto error;
+ }
ret = lttng_session_descriptor_create_from_buffer(
&session_descriptor_view, &session_descriptor);
struct lttng_action **action)
{
ssize_t consumed_len, specific_action_consumed_len;
- const struct lttng_action_comm *action_comm;
action_create_from_payload_cb create_from_payload_cb;
+ const struct lttng_action_comm *action_comm;
+ const struct lttng_payload_view action_comm_view =
+ lttng_payload_view_from_view(
+ view, 0, sizeof(*action_comm));
if (!view || !action) {
consumed_len = -1;
goto end;
}
- action_comm = (const struct lttng_action_comm *) view->buffer.data;
+ if (!lttng_payload_view_is_valid(&action_comm_view)) {
+ /* Payload not large enough to contain the header. */
+ consumed_len = -1;
+ goto end;
+ }
+
+ action_comm = (const struct lttng_action_comm *) action_comm_view.buffer.data;
DBG("Create action from payload: action-type=%s",
lttng_action_type_string(action_comm->action_type));
lttng_payload_view_from_view(view, consumed_len,
view->buffer.size - consumed_len);
+ if (!lttng_payload_view_is_valid(&child_view)) {
+ consumed_len = -1;
+ goto end;
+ }
+
consumed_len_child = lttng_action_create_from_payload(
&child_view, &child_action);
if (consumed_len_child < 0) {
struct lttng_action **p_action)
{
ssize_t consumed_len;
- const struct lttng_action_snapshot_session_comm *comm;
const char *variable_data;
struct lttng_action *action;
enum lttng_action_status status;
struct lttng_snapshot_output *snapshot_output = NULL;
+ const struct lttng_action_snapshot_session_comm *comm;
+ const struct lttng_payload_view snapshot_session_comm_view =
+ lttng_payload_view_from_view(
+ view, 0, sizeof(*comm));
action = lttng_action_snapshot_session_create();
if (!action) {
goto error;
}
- comm = (typeof(comm)) view->buffer.data;
+ if (!lttng_payload_view_is_valid(&snapshot_session_comm_view)) {
+ /* Payload not large enough to contain the header. */
+ goto error;
+ }
+
+ comm = (typeof(comm)) snapshot_session_comm_view.buffer.data;
variable_data = (const char *) &comm->data;
consumed_len = sizeof(struct lttng_action_snapshot_session_comm);
lttng_payload_view_from_view(view, consumed_len,
comm->snapshot_output_len);
- if (!snapshot_output_buffer_view.buffer.data) {
+ if (!lttng_payload_view_is_valid(&snapshot_output_buffer_view)) {
ERR("Failed to create buffer view for snapshot output.");
goto error;
}
ssize_t ret, condition_size;
enum lttng_condition_status status;
enum lttng_domain_type domain_type;
- const struct lttng_condition_buffer_usage_comm *condition_comm;
const char *session_name, *channel_name;
struct lttng_buffer_view names_view;
+ const struct lttng_condition_buffer_usage_comm *condition_comm;
+ const struct lttng_payload_view condition_comm_view =
+ lttng_payload_view_from_view(
+ src_view, 0, sizeof(*condition_comm));
- if (src_view->buffer.size < sizeof(*condition_comm)) {
+ if (!lttng_payload_view_is_valid(&condition_comm_view)) {
ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
ret = -1;
goto end;
}
- condition_comm = (typeof(condition_comm)) src_view->buffer.data;
+ condition_comm = (typeof(condition_comm)) condition_comm_view.buffer.data;
names_view = lttng_buffer_view_from_view(&src_view->buffer,
sizeof(*condition_comm), -1);
return view;
}
+LTTNG_HIDDEN
+bool lttng_buffer_view_is_valid(const struct lttng_buffer_view *view)
+{
+ return view && view->data && view->size > 0;
+}
+
LTTNG_HIDDEN
struct lttng_buffer_view lttng_buffer_view_from_view(
const struct lttng_buffer_view *src, size_t offset,
struct lttng_buffer_view lttng_buffer_view_init(
const char *src, size_t offset, ptrdiff_t len);
+/**
+ * Checks if a buffer view is safe to access.
+ *
+ * After calling the buffer view creation functions, callers should verify
+ * if the resquested length (if any is explicitly provided) could be mapped
+ * to a new view.
+ */
+LTTNG_HIDDEN
+bool lttng_buffer_view_is_valid(const struct lttng_buffer_view *view);
+
/**
* Return a buffer view referencing a subset of the memory referenced by another
* view.
struct lttng_condition **condition)
{
ssize_t ret, condition_size = 0;
- const struct lttng_condition_comm *condition_comm;
condition_create_from_payload_cb create_from_payload = NULL;
+ const struct lttng_condition_comm *condition_comm;
+ const struct lttng_payload_view condition_comm_view =
+ lttng_payload_view_from_view(
+ view, 0, sizeof(*condition_comm));
if (!view || !condition) {
ret = -1;
goto end;
}
+ if (!lttng_payload_view_is_valid(&condition_comm_view)) {
+ /* Payload not large enough to contain the header. */
+ ret = -1;
+ goto end;
+ }
+
DBG("Deserializing condition from buffer");
- condition_comm = (typeof(condition_comm)) view->buffer.data;
+ condition_comm = (typeof(condition_comm)) condition_comm_view.buffer.data;
condition_size += sizeof(*condition_comm);
switch ((enum lttng_condition_type) condition_comm->condition_type) {
{
ssize_t ret, evaluation_size = 0;
const struct lttng_evaluation_comm *evaluation_comm;
- struct lttng_payload_view evaluation_view = src_view ?
+ struct lttng_payload_view evaluation_comm_view =
+ lttng_payload_view_from_view(
+ src_view, 0, sizeof(*evaluation_comm));
+ struct lttng_payload_view evaluation_view =
lttng_payload_view_from_view(src_view,
- sizeof(*evaluation_comm), -1) :
- (typeof(evaluation_view)) {};
+ sizeof(*evaluation_comm), -1);
if (!src_view || !evaluation) {
ret = -1;
goto end;
}
- evaluation_comm = (typeof(evaluation_comm)) src_view->buffer.data;
+ if (!lttng_payload_view_is_valid(&evaluation_comm_view)) {
+ ret = -1;
+ goto end;
+ }
+
+ evaluation_comm = (typeof(evaluation_comm)) evaluation_comm_view.buffer.data;
evaluation_size += sizeof(*evaluation_comm);
switch ((enum lttng_condition_type) evaluation_comm->type) {
struct lttng_event_rule **event_rule)
{
ssize_t ret, consumed = 0;
- const struct lttng_event_rule_comm *event_rule_comm;
event_rule_create_from_payload_cb create_from_payload = NULL;
+ const struct lttng_event_rule_comm *event_rule_comm;
+ const struct lttng_payload_view event_rule_comm_view =
+ lttng_payload_view_from_view(
+ view, 0, sizeof(*event_rule_comm));
if (!view || !event_rule) {
ret = -1;
goto end;
}
+ if (!lttng_payload_view_is_valid(&event_rule_comm_view)) {
+ ret = -1;
+ goto end;
+ }
+
DBG("Deserializing event_rule from payload.");
- event_rule_comm = (const struct lttng_event_rule_comm *) view->buffer.data;
+ event_rule_comm = (const struct lttng_event_rule_comm *) event_rule_comm_view.buffer.data;
consumed += sizeof(*event_rule_comm);
switch ((enum lttng_event_rule_type) event_rule_comm->event_rule_type) {
goto end;
}
- if (view->buffer.size < sizeof(*kprobe_comm)) {
+ current_buffer_view = lttng_buffer_view_from_view(
+ &view->buffer, offset, sizeof(*kprobe_comm));
+ if (!lttng_buffer_view_is_valid(¤t_buffer_view)) {
ERR("Failed to initialize from malformed event rule kprobe: buffer too short to contain header.");
ret = -1;
goto end;
}
- current_buffer_view = lttng_buffer_view_from_view(
- &view->buffer, offset, sizeof(*kprobe_comm));
kprobe_comm = (typeof(kprobe_comm)) current_buffer_view.data;
- if (!kprobe_comm) {
- ret = -1;
- goto end;
- }
rule = lttng_event_rule_kprobe_create();
if (!rule) {
lttng_payload_view_from_view(view, offset,
kprobe_comm->name_len);
- name = current_payload_view.buffer.data;
- if (!name) {
+ if (!lttng_payload_view_is_valid(¤t_payload_view)) {
ret = -1;
goto end;
}
+ name = current_payload_view.buffer.data;
if (!lttng_buffer_view_contains_string(
¤t_payload_view.buffer, name,
kprobe_comm->name_len)) {
lttng_payload_view_from_view(view, offset,
kprobe_comm->location_len);
+ if (!lttng_payload_view_is_valid(¤t_payload_view)) {
+ ret = -1;
+ goto end;
+ }
+
ret = lttng_kernel_probe_location_create_from_payload(
¤t_payload_view, &location);
if (ret < 0) {
current_buffer_view = lttng_buffer_view_from_view(
&view->buffer, offset, sizeof(*syscall_comm));
- syscall_comm = (typeof(syscall_comm)) current_buffer_view.data;
-
- if (!syscall_comm) {
+ if (!lttng_buffer_view_is_valid(¤t_buffer_view)) {
ret = -1;
goto end;
}
+ syscall_comm = (typeof(syscall_comm)) current_buffer_view.data;
rule = lttng_event_rule_syscall_create();
if (!rule) {
ERR("Failed to create event rule syscall");
/* Map the pattern. */
current_buffer_view = lttng_buffer_view_from_view(
&view->buffer, offset, syscall_comm->pattern_len);
- pattern = current_buffer_view.data;
- if (!pattern) {
+ if (!lttng_buffer_view_is_valid(¤t_buffer_view)) {
ret = -1;
goto end;
}
+ pattern = current_buffer_view.data;
if (!lttng_buffer_view_contains_string(¤t_buffer_view, pattern,
syscall_comm->pattern_len)) {
ret = -1;
/* Map the filter_expression. */
current_buffer_view = lttng_buffer_view_from_view(&view->buffer, offset,
syscall_comm->filter_expression_len);
- filter_expression = current_buffer_view.data;
- if (!filter_expression) {
+ if (!lttng_buffer_view_is_valid(¤t_buffer_view)) {
ret = -1;
goto end;
}
+ filter_expression = current_buffer_view.data;
if (!lttng_buffer_view_contains_string(¤t_buffer_view,
filter_expression,
syscall_comm->filter_expression_len)) {
goto end;
}
- if (view->buffer.size < sizeof(*tracepoint_comm)) {
+ current_buffer_view = lttng_buffer_view_from_view(
+ &view->buffer, offset, sizeof(*tracepoint_comm));
+ if (!lttng_buffer_view_is_valid(¤t_buffer_view)) {
ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
ret = -1;
goto end;
}
- current_buffer_view = lttng_buffer_view_from_view(
- &view->buffer, offset, sizeof(*tracepoint_comm));
tracepoint_comm = (typeof(tracepoint_comm)) current_buffer_view.data;
- if (!tracepoint_comm) {
- ret = -1;
- goto end;
- }
-
if (tracepoint_comm->domain_type <= LTTNG_DOMAIN_NONE ||
tracepoint_comm->domain_type > LTTNG_DOMAIN_PYTHON) {
/* Invalid domain value. */
/* Map the pattern. */
current_buffer_view = lttng_buffer_view_from_view(
&view->buffer, offset, tracepoint_comm->pattern_len);
- pattern = current_buffer_view.data;
- if (!pattern) {
+
+ if (!lttng_buffer_view_is_valid(¤t_buffer_view)) {
ret = -1;
goto end;
}
+ pattern = current_buffer_view.data;
if (!lttng_buffer_view_contains_string(¤t_buffer_view, pattern,
tracepoint_comm->pattern_len)) {
ret = -1;
/* Map the filter_expression. */
current_buffer_view = lttng_buffer_view_from_view(&view->buffer, offset,
tracepoint_comm->filter_expression_len);
- filter_expression = current_buffer_view.data;
- if (!filter_expression) {
+ if (!lttng_buffer_view_is_valid(¤t_buffer_view)) {
ret = -1;
goto end;
}
+ filter_expression = current_buffer_view.data;
if (!lttng_buffer_view_contains_string(¤t_buffer_view,
filter_expression,
tracepoint_comm->filter_expression_len)) {
for (i = 0; i < tracepoint_comm->exclusions_count; i++) {
current_buffer_view = lttng_buffer_view_from_view(
&view->buffer, offset, sizeof(*exclusion_len));
- exclusion_len = (typeof(exclusion_len)) current_buffer_view.data;
- if (!exclusion_len) {
+ if (!lttng_buffer_view_is_valid(¤t_buffer_view)) {
ret = -1;
goto end;
}
+ exclusion_len = (typeof(exclusion_len)) current_buffer_view.data;
offset += sizeof(*exclusion_len);
+
current_buffer_view = lttng_buffer_view_from_view(
&view->buffer, offset, *exclusion_len);
+ if (!lttng_buffer_view_is_valid(¤t_buffer_view)) {
+ ret = -1;
+ goto end;
+ }
+
exclusion = current_buffer_view.data;
if (!lttng_buffer_view_contains_string(¤t_buffer_view,
exclusion, *exclusion_len)) {
goto end;
}
- if (view->buffer.size < sizeof(*uprobe_comm)) {
- ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain header.");
- ret = -1;
- goto end;
- }
-
current_buffer_view = lttng_buffer_view_from_view(
&view->buffer, offset, sizeof(*uprobe_comm));
- uprobe_comm = (typeof(uprobe_comm)) current_buffer_view.data;
-
- if (!uprobe_comm) {
+ if (!lttng_buffer_view_is_valid(¤t_buffer_view)) {
+ ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain header");
ret = -1;
goto end;
}
+ uprobe_comm = (typeof(uprobe_comm)) current_buffer_view.data;
+
rule = lttng_event_rule_uprobe_create();
if (!rule) {
- ERR("Failed to create event rule uprobe.");
+ ERR("Failed to create event rule uprobe");
ret = -1;
goto end;
}
/* Map the name. */
current_buffer_view = lttng_buffer_view_from_view(
&view->buffer, offset, uprobe_comm->name_len);
- name = current_buffer_view.data;
- if (!name) {
+ if (!lttng_buffer_view_is_valid(¤t_buffer_view)) {
ret = -1;
goto end;
}
+ name = current_buffer_view.data;
if (!lttng_buffer_view_contains_string(¤t_buffer_view, name,
uprobe_comm->name_len)) {
ret = -1;
offset += uprobe_comm->name_len;
/* Map the location. */
- struct lttng_payload_view current_payload_view =
- lttng_payload_view_from_view(view, offset,
- uprobe_comm->location_len);
- ret = lttng_userspace_probe_location_create_from_payload(
- ¤t_payload_view, &location);
- if (ret < 0) {
- ret = -1;
- goto end;
+ {
+ struct lttng_payload_view current_payload_view =
+ lttng_payload_view_from_view(view, offset,
+ uprobe_comm->location_len);
+
+ if (!lttng_payload_view_is_valid(¤t_payload_view)) {
+ ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain location");
+ ret = -1;
+ goto end;
+ }
+
+ ret = lttng_userspace_probe_location_create_from_payload(
+ ¤t_payload_view, &location);
+ if (ret < 0) {
+ ret = -1;
+ goto end;
+ }
}
assert(ret == uprobe_comm->location_len);
struct lttng_payload_view *view,
struct lttng_kernel_probe_location **location)
{
- struct lttng_kernel_probe_location_comm *probe_location_comm;
enum lttng_kernel_probe_location_type type;
ssize_t consumed = 0;
ssize_t ret;
+ const struct lttng_kernel_probe_location_comm *probe_location_comm;
+ const struct lttng_payload_view probe_location_comm_view =
+ lttng_payload_view_from_view(
+ view, 0, sizeof(*probe_location_comm));
assert(view);
assert(location);
- if (view->buffer.size <= sizeof(*probe_location_comm)) {
+ if (!lttng_payload_view_is_valid(&probe_location_comm_view)) {
ret = -LTTNG_ERR_INVALID;
goto end;
}
- probe_location_comm = (typeof(probe_location_comm)) view->buffer.data;
+ probe_location_comm = (typeof(probe_location_comm)) probe_location_comm_view.buffer.data;
type = (enum lttng_kernel_probe_location_type) probe_location_comm->type;
consumed += sizeof(*probe_location_comm);
location_comm_view = lttng_buffer_view_from_view(view, 0,
sizeof(*location_comm));
- if (!location_comm_view.data) {
+ if (!lttng_buffer_view_is_valid(&location_comm_view)) {
goto error;
}
+
offset += location_comm_view.size;
- location_comm = (const struct lttng_trace_archive_location_comm *) view->data;
+ location_comm = (const struct lttng_trace_archive_location_comm *) location_comm_view.data;
switch ((enum lttng_trace_archive_location_type) location_comm->type) {
case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL:
lttng_buffer_view_from_view(view, offset,
location_comm->types.local.absolute_path_len);
- if (!absolute_path_view.data) {
+ if (!lttng_buffer_view_is_valid(&absolute_path_view)) {
goto error;
}
+
if (absolute_path_view.data[absolute_path_view.size - 1] != '\0') {
goto error;
}
offset + hostname_view.size,
location_comm->types.relay.relative_path_len);
- if (!hostname_view.data || !relative_path_view.data) {
+ if (!lttng_buffer_view_is_valid(&hostname_view) ||
+ !lttng_buffer_view_is_valid(
+ &relative_path_view)) {
goto error;
}
+
if (hostname_view.data[hostname_view.size - 1] != '\0') {
goto error;
}
struct lttng_notification **notification)
{
ssize_t ret, notification_size = 0, condition_size, evaluation_size;
- const struct lttng_notification_comm *notification_comm;
struct lttng_condition *condition;
struct lttng_evaluation *evaluation;
+ const struct lttng_notification_comm *notification_comm;
+ const struct lttng_payload_view notification_comm_view =
+ lttng_payload_view_from_view(
+ src_view, 0, sizeof(*notification_comm));
if (!src_view || !notification) {
ret = -1;
goto end;
}
- notification_comm = (typeof(notification_comm)) src_view->buffer.data;
+ if (!lttng_payload_view_is_valid(¬ification_comm_view)) {
+ /* Payload not large enough to contain the header. */
+ ret = -1;
+ goto end;
+ }
+
+ notification_comm = (typeof(notification_comm)) notification_comm_view.buffer.data;
notification_size += sizeof(*notification_comm);
{
/* struct lttng_condition */
#include "payload.h"
#include <stddef.h>
+LTTNG_HIDDEN
+bool lttng_payload_view_is_valid(const struct lttng_payload_view *view)
+{
+ return view && lttng_buffer_view_is_valid(&view->buffer);
+}
+
LTTNG_HIDDEN
struct lttng_payload_view lttng_payload_view_from_payload(
const struct lttng_payload *payload, size_t offset,
ptrdiff_t len)
{
- return (struct lttng_payload_view) {
+ return payload ? (struct lttng_payload_view) {
.buffer = lttng_buffer_view_from_dynamic_buffer(
&payload->buffer, offset, len),
._fd_handles = payload->_fd_handles,
- };
+ } : (struct lttng_payload_view) {};
}
LTTNG_HIDDEN
struct lttng_payload_view *view, size_t offset,
ptrdiff_t len)
{
- return (struct lttng_payload_view) {
+ return view ? (struct lttng_payload_view) {
.buffer = lttng_buffer_view_from_view(
&view->buffer, offset, len),
._fd_handles = view->_fd_handles,
._iterator.p_fd_handles_position = view->_iterator.p_fd_handles_position ?:
&view->_iterator.fd_handles_position,
- };
+ } : (struct lttng_payload_view) {};
}
LTTNG_HIDDEN
const struct lttng_dynamic_buffer *buffer, size_t offset,
ptrdiff_t len)
{
- return (struct lttng_payload_view) {
+ return buffer ? (struct lttng_payload_view) {
.buffer = lttng_buffer_view_from_dynamic_buffer(
buffer, offset, len)
- };
+ } : (struct lttng_payload_view) {};
}
LTTNG_HIDDEN
const struct lttng_buffer_view *view, size_t offset,
ptrdiff_t len)
{
- return (struct lttng_payload_view) {
+ return view ? (struct lttng_payload_view) {
.buffer = lttng_buffer_view_from_view(
view, offset, len)
- };
+ } : (struct lttng_payload_view) {};
}
LTTNG_HIDDEN
} _iterator;
};
+/**
+ * Checks if a payload view's buffer is safe to access.
+ *
+ * After calling the payload view creation functions, callers should verify
+ * if the resquested length (if any is explicitly provided) could be mapped
+ * to a new view.
+ */
+LTTNG_HIDDEN
+bool lttng_payload_view_is_valid(const struct lttng_payload_view *view);
+
/**
* Return a payload view referencing a subset of a payload.
*
{
ssize_t ret, condition_size;
enum lttng_condition_status status;
- const struct lttng_condition_session_consumed_size_comm *condition_comm;
const char *session_name;
- struct lttng_buffer_view names_view;
+ struct lttng_buffer_view session_name_view;
+ const struct lttng_condition_session_consumed_size_comm *condition_comm;
+ struct lttng_payload_view condition_comm_view = lttng_payload_view_from_view(
+ src_view, 0, sizeof(*condition_comm));
- if (src_view->buffer.size < sizeof(*condition_comm)) {
+ if (!lttng_payload_view_is_valid(&condition_comm_view)) {
ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
ret = -1;
goto end;
}
- condition_comm = (typeof(condition_comm)) src_view->buffer.data;
- names_view = lttng_buffer_view_from_view(&src_view->buffer,
- sizeof(*condition_comm), -1);
+ condition_comm = (typeof(condition_comm)) condition_comm_view.buffer.data;
+ session_name_view = lttng_buffer_view_from_view(&src_view->buffer,
+ sizeof(*condition_comm), condition_comm->session_name_len);
if (condition_comm->session_name_len > LTTNG_NAME_MAX) {
ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
goto end;
}
- if (names_view.size < condition_comm->session_name_len) {
+ if (!lttng_buffer_view_is_valid(&session_name_view)) {
ERR("Failed to initialize from malformed condition buffer: buffer too short to contain element names");
ret = -1;
goto end;
goto end;
}
- session_name = names_view.data;
+ session_name = session_name_view.data;
if (*(session_name + condition_comm->session_name_len - 1) != '\0') {
ERR("Malformed session name encountered in condition buffer");
ret = -1;
current_view = lttng_buffer_view_from_view(payload, offset,
sizeof(*base_header));
- base_header = (typeof(base_header)) current_view.data;
- if (!base_header) {
+ if (!lttng_buffer_view_is_valid(¤t_view)) {
ret = -1;
goto end;
}
+ base_header = (typeof(base_header)) current_view.data;
switch (base_header->type) {
case LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR:
case LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT:
current_view = lttng_buffer_view_from_view(payload, offset,
sizeof(*live_header));
- live_header = (typeof(live_header)) current_view.data;
- if (!live_header) {
+ if (!lttng_buffer_view_is_valid(¤t_view)) {
ret = -1;
goto end;
}
+ live_header = (typeof(live_header)) current_view.data;
live_timer_us = live_header->live_timer_us;
break;
}
/* Map the name. */
current_view = lttng_buffer_view_from_view(payload, offset,
base_header->name_len);
- name = current_view.data;
- if (!name) {
+ if (!lttng_buffer_view_is_valid(¤t_view)) {
ret = -1;
goto end;
}
+ name = current_view.data;
if (base_header->name_len == 1 ||
name[base_header->name_len - 1] ||
strlen(name) != base_header->name_len - 1) {
/* Map a URI. */
current_view = lttng_buffer_view_from_view(payload,
offset, sizeof(*uri));
- uri = (typeof(uri)) current_view.data;
- if (!uri) {
+ if (!lttng_buffer_view_is_valid(¤t_view)) {
ret = -1;
goto end;
}
+
+ uri = (typeof(uri)) current_view.data;
uris[i] = zmalloc(sizeof(*uri));
if (!uris[i]) {
ret = -1;
{
ssize_t ret, condition_size;
enum lttng_condition_status status;
- const struct lttng_condition_session_rotation_comm *condition_comm;
const char *session_name;
struct lttng_buffer_view name_view;
+ const struct lttng_condition_session_rotation_comm *condition_comm;
+ struct lttng_payload_view condition_comm_view =
+ lttng_payload_view_from_view(
+ src_view, 0, sizeof(*condition_comm));
- if (src_view->buffer.size < sizeof(*condition_comm)) {
+ if (!lttng_payload_view_is_valid(&condition_comm_view)) {
ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
ret = -1;
goto end;
condition_comm = (typeof(condition_comm)) src_view->buffer.data;
name_view = lttng_buffer_view_from_view(&src_view->buffer,
- sizeof(*condition_comm), -1);
+ sizeof(*condition_comm), condition_comm->session_name_len);
- if (condition_comm->session_name_len > LTTNG_NAME_MAX) {
- ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
+ if (!lttng_buffer_view_is_valid(&name_view)) {
+ ERR("Failed to initialize from malformed condition buffer: buffer too short to contain session name");
ret = -1;
goto end;
}
- if (name_view.size < condition_comm->session_name_len) {
- ERR("Failed to initialize from malformed condition buffer: buffer too short to contain session name");
+ if (condition_comm->session_name_len > LTTNG_NAME_MAX) {
+ ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
ret = -1;
goto end;
}
ssize_t ret, size;
struct lttng_evaluation *evaluation = NULL;
struct lttng_trace_archive_location *location = NULL;
- const struct lttng_evaluation_session_rotation_comm *comm =
- (typeof(comm)) view->buffer.data;
- struct lttng_buffer_view location_view;
+ const struct lttng_evaluation_session_rotation_comm *comm;
+ struct lttng_payload_view comm_view = lttng_payload_view_from_view(
+ view, 0, sizeof(*comm));
- if (view->buffer.size < sizeof(*comm)) {
+ if (!lttng_payload_view_is_valid(&comm_view)) {
goto error;
}
+ comm = (typeof(comm)) comm_view.buffer.data;
size = sizeof(*comm);
if (comm->has_location) {
- location_view = lttng_buffer_view_from_view(
- &view->buffer, sizeof(*comm), -1);
- if (!location_view.data) {
+ const struct lttng_buffer_view location_view =
+ lttng_buffer_view_from_view(
+ &view->buffer, sizeof(*comm), -1);
+
+ if (!lttng_buffer_view_is_valid(&location_view)) {
goto error;
}
header_view = lttng_buffer_view_from_view(
buffer_view, 0, sizeof(*header));
- if (!header_view.data) {
+ if (!lttng_buffer_view_is_valid(&header_view)) {
goto error;
}
+
offset = header_view.size;
header = (typeof(header)) header_view.data;
value_view = lttng_buffer_view_from_view(
buffer_view, offset, sizeof(*value_comm));
- if (!value_view.data) {
+ if (!lttng_buffer_view_is_valid(&value_view)) {
goto error;
}
value_name_view = lttng_buffer_view_from_view(
buffer_view, offset,
value_comm->value.name_len);
+ if (!lttng_buffer_view_is_valid(&value_name_view)) {
+ goto error;
+ }
+
offset += value_name_view.size;
}
+
ret_code = process_attr_value_from_comm(domain, process_attr,
type, &value_comm->value.integral,
&value_name_view, &value);
.uid = LTTNG_OPTIONAL_INIT_UNSET,
.gid = LTTNG_OPTIONAL_INIT_UNSET,
};
+ const struct lttng_payload_view trigger_comm_view =
+ lttng_payload_view_from_view(
+ src_view, 0, sizeof(*trigger_comm));
if (!src_view || !trigger) {
ret = -1;
goto end;
}
+ if (!lttng_payload_view_is_valid(&trigger_comm_view)) {
+ /* Payload not large enough to contain the header. */
+ ret = -1;
+ goto end;
+ }
+
/* lttng_trigger_comm header */
- trigger_comm = (typeof(trigger_comm)) src_view->buffer.data;
+ trigger_comm = (typeof(trigger_comm)) trigger_comm_view.buffer.data;
/* Set the trigger's creds. */
if (trigger_comm->uid > (uint64_t) ((uid_t) -1)) {
/* Name. */
const struct lttng_payload_view name_view =
lttng_payload_view_from_view(
- src_view, offset, trigger_comm->name_length);
+ src_view, offset,
+ trigger_comm->name_length);
+
+ if (!lttng_payload_view_is_valid(&name_view)) {
+ ret = -1;
+ goto end;
+ }
name = name_view.buffer.data;
if (!lttng_buffer_view_contains_string(&name_view.buffer, name,
struct lttng_userspace_probe_location **location)
{
struct lttng_userspace_probe_location_lookup_method *lookup_method;
- struct lttng_userspace_probe_location_comm *probe_location_comm;
enum lttng_userspace_probe_location_type type;
int consumed = 0;
int ret;
+ struct lttng_userspace_probe_location_comm *probe_location_comm;
+ struct lttng_payload_view probe_location_comm_view =
+ lttng_payload_view_from_view(
+ view, 0, sizeof(*probe_location_comm));
assert(view);
assert(location);
lookup_method = NULL;
- if (view->buffer.size <= sizeof(*probe_location_comm)) {
+ if (!lttng_payload_view_is_valid(&probe_location_comm_view)) {
ret = -LTTNG_ERR_INVALID;
goto end;
}
- probe_location_comm = (typeof(probe_location_comm)) view->buffer.data;
+ probe_location_comm = (typeof(probe_location_comm)) probe_location_comm_view.buffer.data;
type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
consumed += sizeof(*probe_location_comm);
cmd_header_view = lttng_buffer_view_from_dynamic_buffer(
&payload.buffer, 0, sizeof(*cmd_header));
- if (!cmd_header_view.data) {
+ if (!lttng_buffer_view_is_valid(&cmd_header_view)) {
ret = -LTTNG_ERR_INVALID_PROTOCOL;
goto end;
}
payload_view.buffer.data,
ext_comm->userspace_probe_location_len);
+ if (!lttng_payload_view_is_valid(&probe_location_view)) {
+ ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+ goto end;
+ }
+
/*
* Create a temporary userspace probe location
* to determine the size needed by a "flattened"
payload_copy_view.buffer.data,
ext_comm->userspace_probe_location_len);
+ if (!lttng_payload_view_is_valid(&probe_location_view)) {
+ ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+ goto free_dynamic_buffer;
+ }
+
ret = lttng_userspace_probe_location_create_from_payload(
&probe_location_view,
&probe_location);