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

fix(modern): perform an exact check on BPF_TRACE_RAW_TP attach type #1404

Merged
merged 3 commits into from
Oct 18, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
147 changes: 142 additions & 5 deletions userspace/libpman/src/configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,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 libbpf_print(enum libbpf_print_level level, const char* format, va_list args)
{
Expand Down Expand Up @@ -171,15 +175,138 @@ int pman_init_state(falcosecurity_log_fn log_fn, unsigned long buf_bytes_dim, ui

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",
Andreagit97 marked this conversation as resolved.
Show resolved Hide resolved
"/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;
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");
Expand All @@ -189,8 +316,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