Skip to content
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
6 changes: 6 additions & 0 deletions driver/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,12 @@ static long ppm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if(put_user(PPM_SCHEMA_CURRENT_VERSION, out))
ret = -EINVAL;
goto cleanup_ioctl_nolock;
} else if (cmd == PPM_IOCTL_GET_TPMASK) {
u32 __user *out = (u32 __user *) arg;
ret = 0;
if(put_user(g_tracepoints_attached, out))
ret = -EINVAL;
goto cleanup_ioctl_nolock;
}

mutex_lock(&g_consumer_mutex);
Expand Down
1 change: 1 addition & 0 deletions driver/ppm_events_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -1741,6 +1741,7 @@ struct ppm_evt_hdr {
#define PPM_IOCTL_GET_API_VERSION _IO(PPM_IOCTL_MAGIC, 24)
#define PPM_IOCTL_GET_SCHEMA_VERSION _IO(PPM_IOCTL_MAGIC, 25)
#define PPM_IOCTL_MANAGE_TP _IO(PPM_IOCTL_MAGIC, 26)
#define PPM_IOCTL_GET_TPMASK _IO(PPM_IOCTL_MAGIC, 27)
#endif // CYGWING_AGENT

extern const struct ppm_name_value socket_families[];
Expand Down
10 changes: 8 additions & 2 deletions userspace/libscap/engine/bpf/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,22 @@ limitations under the License.

#define BPF_MAPS_MAX 32

struct bpf_prog {
int fd;
int efd;
char name[NAME_MAX];
};

struct bpf_engine
{
struct scap_device_set m_dev_set;
size_t m_ncpus;
char* m_lasterr;
int m_bpf_prog_fds[BPF_PROGS_MAX];
struct bpf_prog m_bpf_progs[BPF_PROGS_MAX];
int m_bpf_prog_cnt;
int m_bpf_event_fd[BPF_PROGS_MAX];
int m_bpf_map_fds[BPF_MAPS_MAX];
int m_bpf_prog_array_map_idx;
char m_filepath[PATH_MAX];
};

#define SCAP_HANDLE_T struct bpf_engine
117 changes: 93 additions & 24 deletions userspace/libscap/engine/bpf/scap_bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ static int32_t load_tracepoint(struct bpf_engine* handle, const char *event, str
return SCAP_FAILURE;
}

const char *full_event = event;
if(memcmp(event, "raw_tracepoint/", sizeof("raw_tracepoint/") - 1) == 0)
{
raw_tp = true;
Expand Down Expand Up @@ -547,7 +548,9 @@ static int32_t load_tracepoint(struct bpf_engine* handle, const char *event, str
return SCAP_FAILURE;
}

handle->m_bpf_prog_fds[handle->m_bpf_prog_cnt++] = fd;
handle->m_bpf_progs[handle->m_bpf_prog_cnt].fd = fd;
strncpy(handle->m_bpf_progs[handle->m_bpf_prog_cnt].name, full_event, NAME_MAX);
handle->m_bpf_prog_cnt++;

if(memcmp(event, "filler/", sizeof("filler/") - 1) == 0)
{
Expand Down Expand Up @@ -645,7 +648,7 @@ static int32_t load_tracepoint(struct bpf_engine* handle, const char *event, str

// by this point m_bpf_prog_cnt has already been checked for
// being inbounds, so this is safe.
handle->m_bpf_event_fd[handle->m_bpf_prog_cnt - 1] = efd;
handle->m_bpf_progs[handle->m_bpf_prog_cnt - 1].efd = efd;

return SCAP_SUCCESS;
}
Expand All @@ -663,7 +666,7 @@ static bool is_tp_enabled(interesting_tp_set *tp_of_interest, const char *shname
}

static int32_t load_bpf_file(
struct bpf_engine *handle, const char *path,
struct bpf_engine *handle,
uint64_t *api_version_p,
uint64_t *schema_version_p,
scap_open_args *oargs)
Expand Down Expand Up @@ -697,11 +700,11 @@ static int32_t load_bpf_file(
return SCAP_FAILURE;
}

int program_fd = open(path, O_RDONLY, 0);
int program_fd = open(handle->m_filepath, O_RDONLY, 0);
if(program_fd < 0)
{
char buf[SCAP_LASTERR_SIZE];
snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "can't open BPF probe '%s': %s", path, scap_strerror_r(buf, errno));
snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "can't open BPF probe '%s': %s", handle->m_filepath, scap_strerror_r(buf, errno));
return SCAP_FAILURE;
}

Expand Down Expand Up @@ -826,9 +829,21 @@ static int32_t load_bpf_file(
{
if(is_tp_enabled(&(oargs->tp_of_interest), shname))
{
if(load_tracepoint(handle, shname, data->d_buf, data->d_size) != SCAP_SUCCESS)
bool already_attached = false;
for (int i = 0; i < handle->m_bpf_prog_cnt && !already_attached; i++)
{
if (strcmp(handle->m_bpf_progs[i].name, shname) == 0)
{
already_attached = true;
}
}

if (!already_attached)
{
goto cleanup;
if(load_tracepoint(handle, shname, data->d_buf, data->d_size) != SCAP_SUCCESS)
{
goto cleanup;
}
}
}
}
Expand Down Expand Up @@ -1257,6 +1272,19 @@ int32_t scap_bpf_enable_tracers_capture(struct scap_engine_handle engine)
return SCAP_SUCCESS;
}

static void close_prog(struct bpf_prog *prog)
{
if(prog->efd > 0)
{
close(prog->efd);
}
if(prog->fd > 0)
{
close(prog->fd);
}
memset(prog, 0, sizeof(*prog));
}

int32_t scap_bpf_close(struct scap_engine_handle engine)
{
struct bpf_engine *handle = engine.m_handle;
Expand All @@ -1266,22 +1294,9 @@ int32_t scap_bpf_close(struct scap_engine_handle engine)

devset_free(devset);

for(j = 0; j < sizeof(handle->m_bpf_event_fd) / sizeof(handle->m_bpf_event_fd[0]); ++j)
for(j = 0; j < sizeof(handle->m_bpf_progs) / sizeof(handle->m_bpf_progs[0]); ++j)
{
if(handle->m_bpf_event_fd[j] > 0)
{
close(handle->m_bpf_event_fd[j]);
handle->m_bpf_event_fd[j] = 0;
}
}

for(j = 0; j < sizeof(handle->m_bpf_prog_fds) / sizeof(handle->m_bpf_prog_fds[0]); ++j)
{
if(handle->m_bpf_prog_fds[j] > 0)
{
close(handle->m_bpf_prog_fds[j]);
handle->m_bpf_prog_fds[j] = 0;
}
close_prog(&handle->m_bpf_progs[j]);
}

for(j = 0; j < sizeof(handle->m_bpf_map_fds) / sizeof(handle->m_bpf_map_fds[0]); ++j)
Expand Down Expand Up @@ -1422,7 +1437,8 @@ int32_t scap_bpf_load(
return SCAP_FAILURE;
}

if(load_bpf_file(handle, bpf_probe, api_version_p, schema_version_p, oargs) != SCAP_SUCCESS)
snprintf(handle->m_filepath, PATH_MAX, "%s", bpf_probe);
if(load_bpf_file(handle, api_version_p, schema_version_p, oargs) != SCAP_SUCCESS)
{
return SCAP_FAILURE;
}
Expand Down Expand Up @@ -1621,13 +1637,64 @@ static int32_t unsupported_config(struct scap_engine_handle engine, const char*
return SCAP_FAILURE;
}

static int32_t scap_bpf_handle_tp_mask(struct scap_engine_handle engine, uint32_t op, uint32_t tp)
{
struct bpf_engine *handle = engine.m_handle;

int prg_idx = -1;
for (int i = 0; i < handle->m_bpf_prog_cnt; i++)
{
const tp_values val = tp_from_name(handle->m_bpf_progs[i].name);
if (val == tp)
{
prg_idx = i;
break;
}
}

// We want to unload a never loaded tracepoint
if (prg_idx == -1 && op != SCAP_TPMASK_SET)
{
return SCAP_SUCCESS;
}
// We want to load an already loaded tracepoint
if (prg_idx >= 0 && op != SCAP_TPMASK_UNSET)
{
return SCAP_SUCCESS;
}

if (op == SCAP_TPMASK_UNSET)
{
// Algo:
// Close the event and tracepoint fds,
// reduce number of prog cnt
// move left remaining array elements
// reset last array element
close_prog(&handle->m_bpf_progs[prg_idx]);
handle->m_bpf_prog_cnt--;
size_t byte_size = (handle->m_bpf_prog_cnt - prg_idx) * sizeof(handle->m_bpf_progs[prg_idx]);
if (byte_size > 0)
{
memmove(&handle->m_bpf_progs[prg_idx], &handle->m_bpf_progs[prg_idx + 1], byte_size);
}
memset(&handle->m_bpf_progs[handle->m_bpf_prog_cnt], 0, sizeof(handle->m_bpf_progs[handle->m_bpf_prog_cnt]));
return SCAP_SUCCESS;
}

uint64_t api_version_p;
uint64_t schema_version_p;
scap_open_args oargs = {0};
oargs.tp_of_interest.tp[tp] = 1;
return load_bpf_file(handle, &api_version_p, &schema_version_p, &oargs);
}

static int32_t scap_bpf_handle_event_mask(struct scap_engine_handle engine, uint32_t op, uint32_t ppm_sc)
{
int32_t ret = SCAP_SUCCESS;
switch(op)
{
case SCAP_EVENTMASK_ZERO:
for(int ppm_sc = 0; ppm_sc < PPM_SC_MAX && ret==SCAP_SUCCESS; ppm_sc++)
for(ppm_sc = 0; ppm_sc < PPM_SC_MAX && ret==SCAP_SUCCESS; ppm_sc++)
{
ret = update_interesting_syscalls_map(engine, SCAP_EVENTMASK_UNSET, ppm_sc);
}
Expand Down Expand Up @@ -1668,6 +1735,8 @@ static int32_t configure(struct scap_engine_handle engine, enum scap_setting set
return scap_bpf_set_snaplen(engine, arg1);
case SCAP_EVENTMASK:
return scap_bpf_handle_event_mask(engine, arg1, arg2);
case SCAP_TPMASK:
return scap_bpf_handle_tp_mask(engine, arg1, arg2);
case SCAP_DYNAMIC_SNAPLEN:
if(arg1 == 0)
{
Expand Down
56 changes: 44 additions & 12 deletions userspace/libscap/engine/kmod/scap_kmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,46 @@ static int32_t enforce_into_kmod_buffer_bytes_dim(scap_t *handle, unsigned long
}


/// TODO: we need to pass directly the system syscall number not the `ppm_sc` here.
int32_t scap_kmod_handle_tp_mask(struct scap_engine_handle engine, uint32_t op, uint32_t tp)
{
struct scap_device_set *devset = &engine.m_handle->m_dev_set;

uint32_t curr_set;
if(ioctl(devset->m_devs[0].m_fd, PPM_IOCTL_GET_TPMASK, &curr_set))
{
snprintf(engine.m_handle->m_lasterr, SCAP_LASTERR_SIZE,
"%s(%d) failed",
__FUNCTION__, op);
ASSERT(false);
return SCAP_FAILURE;
}

uint32_t new_set;
if (op == SCAP_TPMASK_SET)
{
new_set = curr_set | (1 << tp);
}
else
{
new_set = curr_set & ~(1 << tp);
}
if(new_set == curr_set)
{
return SCAP_SUCCESS;
}

if(ioctl(devset->m_devs[0].m_fd, PPM_IOCTL_MANAGE_TP, new_set))
{
snprintf(engine.m_handle->m_lasterr, SCAP_LASTERR_SIZE,
"%s(%d) failed for tpmask %d",
__FUNCTION__, op, new_set);
ASSERT(false);
return SCAP_FAILURE;
}
return SCAP_SUCCESS;
}

/// TODO: it would be better to pass directly the system syscall number not the `ppm_sc` here.
int32_t scap_kmod_handle_event_mask(struct scap_engine_handle engine, uint32_t op, uint32_t ppm_sc)
{
struct scap_device_set *devset = &engine.m_handle->m_dev_set;
Expand Down Expand Up @@ -371,19 +410,10 @@ int32_t scap_kmod_init(scap_t *handle, scap_open_args *oargs)
}

/* Set interesting Tracepoints */
uint32_t tp_of_interest = 0;
for (int i = 0; i < TP_VAL_MAX; i++)
{
if (oargs->tp_of_interest.tp[i])
{
tp_of_interest |= (1 << i);
}
}
if(ioctl(devset->m_devs[0].m_fd, PPM_IOCTL_MANAGE_TP, tp_of_interest))
{
strncpy(handle->m_lasterr, "PPM_IOCTL_MANAGE_TP failed", SCAP_LASTERR_SIZE);
ASSERT(false);
return SCAP_FAILURE;
uint32_t op = oargs->tp_of_interest.tp[i] ? SCAP_TPMASK_SET : SCAP_TPMASK_UNSET;
scap_kmod_handle_tp_mask(engine, op, i);
}

return SCAP_SUCCESS;
Expand Down Expand Up @@ -729,6 +759,8 @@ static int32_t configure(struct scap_engine_handle engine, enum scap_setting set
return scap_kmod_set_snaplen(engine, arg1);
case SCAP_EVENTMASK:
return scap_kmod_handle_event_mask(engine, arg1, arg2);
case SCAP_TPMASK:
return scap_kmod_handle_tp_mask(engine, arg1, arg2);
case SCAP_DYNAMIC_SNAPLEN:
if(arg1 == 0)
{
Expand Down
Loading