Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync: release0.13.x #1438

Merged
merged 7 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 143 additions & 6 deletions userspace/libpman/src/configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ limitations under the License.

#include "state.h"
#include <sys/resource.h>
#include <linux/limits.h>
#include <sys/utsname.h>
#include <fcntl.h> /* Definition of AT_* constants */
#include <unistd.h>

static int setup_libbpf_print_verbose(enum libbpf_print_level level, const char* format, va_list args)
{
Expand Down Expand Up @@ -164,16 +168,139 @@ int pman_get_required_buffers()
return g_state.n_required_buffers;
}

bool check_location(const char* path)
{
static const char bpf_trace_raw_byte_array[] = "BPF_TRACE_RAW_TP";

bool res = false;

// On success `faccessat` returns 0.
if(faccessat(0, path, R_OK, AT_EACCESS) != 0)
{
return false;
}

char *file_content = NULL;
FILE *f = fopen(path, "r");
if(!f)
{
return false;
}

// Seek to the end of file
if(fseek(f, 0, SEEK_END))
{
goto cleanup;
}

// Return the dimension of the file
long sz = ftell(f);
if (sz < 0)
{
goto cleanup;
}

// Seek again to the beginning of the file
if(fseek(f, 0, SEEK_SET))
{
goto cleanup;
}

// pre-alloc memory to read all of BTF data
file_content = malloc(sz);
if (!file_content)
{
goto cleanup;
}

// read all of BTF data
if(fread(file_content, 1, sz, f) < sz)
{
goto cleanup;
}

// Search 'BPF_TRACE_RAW_TP' byte array
int z = 0;
for(int j = 0; j< sz; j++)
{
if(file_content[j] == bpf_trace_raw_byte_array[z])
{
z++;
if(z == sizeof(bpf_trace_raw_byte_array) / sizeof(*bpf_trace_raw_byte_array))
{
res = true;
break;
}
}
else
{
z = 0;
}
}

cleanup:
if(f)
{
fclose(f);
}
if(file_content)
{
free(file_content);
}
return res;
}

bool probe_BPF_TRACE_RAW_TP_type(void)
{
// These locations are taken from libbpf library:
// https://elixir.bootlin.com/linux/latest/source/tools/lib/bpf/btf.c#L4767
const char *locations[] = {
"/sys/kernel/btf/vmlinux",
"/boot/vmlinux-%1$s",
"/lib/modules/%1$s/vmlinux-%1$s",
"/lib/modules/%1$s/build/vmlinux",
"/usr/lib/modules/%1$s/kernel/vmlinux",
"/usr/lib/debug/boot/vmlinux-%1$s",
"/usr/lib/debug/boot/vmlinux-%1$s.debug",
"/usr/lib/debug/lib/modules/%1$s/vmlinux",
};

// Try canonical `vmlinux` BTF through `sysfs` first.
if(check_location(locations[0]))
{
return true;
}

// Fall back to trying to find `vmlinux` on disk otherwise
struct utsname buf = {};
if(uname(&buf) == -1)
{
return false;
}

char path[PATH_MAX + 1];

// Skip vmlinux since we already tested it.
for (int i = 1; i < sizeof(locations) / sizeof(*locations); i++)
{
snprintf(path, PATH_MAX, locations[i], buf.release);
if(check_location(path))
{
return true;
}
}
return false;
}


/*
* Probe the kernel for required dependencies, ring buffer maps and tracing
* progs needs to be supported.
*/
bool pman_check_support()
{
bool res;

res = libbpf_probe_bpf_map_type(BPF_MAP_TYPE_RINGBUF, NULL) > 0;
if (!res)
bool res = libbpf_probe_bpf_map_type(BPF_MAP_TYPE_RINGBUF, NULL) > 0;
if(!res)
{
pman_print_error("ring buffer map type is not supported");
return res;
Expand All @@ -182,8 +309,18 @@ bool pman_check_support()
res = libbpf_probe_bpf_prog_type(BPF_PROG_TYPE_TRACING, NULL) > 0;
if (!res)
{
pman_print_error("tracing program type is not supported");
return res;
// The above function checks for the `BPF_TRACE_FENTRY` attach type presence, while we need
// to check for the `BPF_TRACE_RAW_TP` one. If `BPF_TRACE_FENTRY` is defined we are
// sure `BPF_TRACE_RAW_TP` is defined as well, in all other cases, we need to search
// for it in the `vmlinux` file.
res = probe_BPF_TRACE_RAW_TP_type();
if(!res)
{
// Clear the errno for `pman_print_error`
errno = 0;
pman_print_error("prog 'BPF_TRACE_RAW_TP' is not supported");
return res;
}
}

/* Probe result depends on the success of map creation, no additional
Expand Down
1 change: 1 addition & 0 deletions userspace/libsinsp/filterchecks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4494,6 +4494,7 @@ int32_t sinsp_filter_check_event::parse_field_name(const char* str, bool alloc_s
res = extract_arg("evt.rawarg", val, &m_arginfo);

m_customfield.m_type = m_arginfo->type;
m_customfield.m_print_format = m_arginfo->fmt;
}
else if(STR_MATCH("evt.around"))
{
Expand Down
29 changes: 11 additions & 18 deletions userspace/libsinsp/sinsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,8 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
sinsp_evt* evt;
int32_t res;

*puevt = NULL;

//
// Check if there are fake cpu events to events
//
Expand Down Expand Up @@ -1293,8 +1295,6 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
{
m_external_event_processor->process_event(NULL, libsinsp::EVENT_RETURN_TIMEOUT);
}
*puevt = NULL;
return res;
}
else if(res == SCAP_EOF)
{
Expand All @@ -1310,8 +1310,7 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
// In this case, we restart the capture so that the internal states gets reset
// and the blocks coming from the next appended file get consumed.
restart_capture();
return SCAP_TIMEOUT;

res = SCAP_TIMEOUT;
}
else if(res == SCAP_FILTERED_EVENT)
{
Expand All @@ -1323,8 +1322,6 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
if(m_external_event_processor)
{
m_external_event_processor->process_event(NULL, libsinsp::EVENT_RETURN_FILTERED);
*puevt = NULL;
return res;
}
}
else
Expand Down Expand Up @@ -1422,24 +1419,19 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
// things like exit() or close() can be parsed.
//
uint32_t nfdr = (uint32_t)m_fds_to_remove->size();

if(nfdr != 0)
{
/* This is a removal logic we shouldn't scan /proc. If we don't have the thread
* to remove we are fine.
*/
sinsp_threadinfo* ptinfo = get_thread_ref(m_tid_of_fd_to_remove, false).get();
if(!ptinfo)
{
ASSERT(false);
return res;
}

for(uint32_t j = 0; j < nfdr; j++)
if(ptinfo)
{
ptinfo->remove_fd(m_fds_to_remove->at(j));
for(uint32_t j = 0; j < nfdr; j++)
{
ptinfo->remove_fd(m_fds_to_remove->at(j));
}
}

m_fds_to_remove->clear();
}

Expand Down Expand Up @@ -1512,6 +1504,9 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
m_dumper->dump(evt);
}

// Finally set output evt;
// From now on, any return must have the correct output being set.
*puevt = evt;
if(evt->m_filtered_out)
{
ppm_event_category cat = evt->get_category();
Expand All @@ -1520,7 +1515,6 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
// mode and the category of this event is internal.
if(!(m_isinternal_events_enabled && (cat & EC_INTERNAL)))
{
*puevt = evt;
return SCAP_FILTERED_EVENT;
}
}
Expand Down Expand Up @@ -1550,7 +1544,6 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
//
// Done
//
*puevt = evt;
return res;
}

Expand Down
Loading