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

feat(driver): support process_vm_readv and process_vm_writev syscalls #1675

Merged
merged 7 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 1 addition & 1 deletion driver/SCHEMA_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.15.1
2.16.1
71 changes: 71 additions & 0 deletions driver/bpf/fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -7319,4 +7319,75 @@ FILLER(sys_newfstatat_x, true)
uint32_t flags = bpf_syscall_get_argument(data, 3);
return bpf_push_u32_to_ring(data, newfstatat_flags_to_scap(flags));
}


FILLER(sys_process_vm_readv_x, true)
{
const struct iovec __user *iov;
unsigned long iovcnt;

/* Parameter 1: ret (type: PT_INT64) */
long retval = bpf_syscall_get_retval(data->ctx);
int res = bpf_push_s64_to_ring(data, (int32_t)retval);
CHECK_RES(res);

/* Parameter 2: pid (type: PT_PID) */
pid_t pid = (int32_t)bpf_syscall_get_argument(data, 0);
res = bpf_push_s64_to_ring(data, (int64_t)pid);
CHECK_RES(res);

/* Parameter 3: data (type: PT_BYTEBUF) */
if (retval > 0)
{
iov = (const struct iovec __user *)bpf_syscall_get_argument(data, 3);
therealbobo marked this conversation as resolved.
Show resolved Hide resolved
iovcnt = bpf_syscall_get_argument(data, 4);

res = bpf_parse_readv_writev_bufs(data,
iov,
iovcnt,
retval,
PRB_FLAG_PUSH_DATA);
}
else
{
res = bpf_push_empty_param(data);
}

return res;
}

FILLER(sys_process_vm_writev_x, true)
{
const struct iovec __user *iov;
unsigned long iovcnt;

/* Parameter 1: ret (type: PT_INT64) */
long retval = bpf_syscall_get_retval(data->ctx);
int res = bpf_push_s64_to_ring(data, (int32_t)retval);
CHECK_RES(res);

/* Parameter 2: pid (type: PT_PID) */
pid_t pid = (int32_t)bpf_syscall_get_argument(data, 0);
res = bpf_push_s64_to_ring(data, (int64_t)pid);
CHECK_RES(res);

/* Parameter 3: data (type: PT_BYTEBUF) */
if (retval > 0)
{
iov = (const struct iovec __user *)bpf_syscall_get_argument(data, 1);
iovcnt = bpf_syscall_get_argument(data, 2);

res = bpf_parse_readv_writev_bufs(data,
iov,
iovcnt,
retval,
PRB_FLAG_PUSH_DATA);
}
else
{
res = bpf_push_empty_param(data);
}

return res;
}
#endif
2 changes: 1 addition & 1 deletion driver/event_stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ or GPL2.txt for full copies of the license.
#pragma once

/* These numbers must be updated when we add new events in the event table */
#define SYSCALL_EVENTS_NUM 372
#define SYSCALL_EVENTS_NUM 376
#define TRACEPOINT_EVENTS_NUM 6
#define METAEVENTS_NUM 20
#define PLUGIN_EVENTS_NUM 1
Expand Down
4 changes: 4 additions & 0 deletions driver/event_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,10 @@ const struct ppm_event_info g_event_info[] = {
[PPME_SYSCALL_MKNODAT_X] = {"mknodat", EC_OTHER | EC_SYSCALL, EF_USES_FD, 5, {{"res", PT_ERRNO, PF_DEC}, {"dirfd", PT_FD, PF_DEC}, {"path", PT_FSRELPATH, PF_NA, DIRFD_PARAM(1)},{"mode", PT_MODE, PF_OCT, mknod_mode},{"dev", PT_UINT32, PF_DEC}}},
[PPME_SYSCALL_NEWFSTATAT_E] = {"newfstatat", EC_FILE | EC_SYSCALL, EF_NONE, 0},
[PPME_SYSCALL_NEWFSTATAT_X] = {"newfstatat", EC_FILE | EC_SYSCALL, EF_USES_FD, 4, {{"res", PT_ERRNO, PF_DEC}, {"dirfd", PT_FD, PF_DEC}, {"path", PT_FSRELPATH, PF_NA, DIRFD_PARAM(1)}, {"flags", PT_FLAGS32, PF_HEX, newfstatat_flags}}},
[PPME_SYSCALL_PROCESS_VM_READV_E] = {"process_vm_readv", EC_SYSCALL | EC_IPC, EF_NONE, 0},
[PPME_SYSCALL_PROCESS_VM_READV_X] = {"process_vm_readv", EC_SYSCALL | EC_IPC, EF_NONE, 3, {{"res", PT_INT64, PF_DEC}, {"pid", PT_PID, PF_DEC}, {"data", PT_BYTEBUF, PF_NA}}},
[PPME_SYSCALL_PROCESS_VM_WRITEV_E] = {"process_vm_writev", EC_SYSCALL | EC_IPC, EF_NONE, 0},
[PPME_SYSCALL_PROCESS_VM_WRITEV_X] = {"process_vm_writev", EC_SYSCALL | EC_IPC, EF_NONE, 3, {{"res", PT_INT64, PF_DEC}, {"pid", PT_PID, PF_DEC}, {"data", PT_BYTEBUF, PF_NA}}},
};
#pragma GCC diagnostic pop

Expand Down
6 changes: 5 additions & 1 deletion driver/fillers_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,10 @@ const struct ppm_event_entry g_ppm_events[PPM_EVENT_MAX] = {
[PPME_SYSCALL_MKNODAT_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_MKNODAT_X] = {FILLER_REF(sys_mknodat_x)},
[PPME_SYSCALL_NEWFSTATAT_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_NEWFSTATAT_X] = {FILLER_REF(sys_newfstatat_x)}
[PPME_SYSCALL_NEWFSTATAT_X] = {FILLER_REF(sys_newfstatat_x)},
[PPME_SYSCALL_PROCESS_VM_READV_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_PROCESS_VM_READV_X] = {FILLER_REF(sys_process_vm_readv_x)},
[PPME_SYSCALL_PROCESS_VM_WRITEV_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_PROCESS_VM_WRITEV_X] = {FILLER_REF(sys_process_vm_writev_x)}
};
#pragma GCC diagnostic pop
2 changes: 2 additions & 0 deletions driver/modern_bpf/definitions/events_dimensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@
#define MKNOD_E_SIZE HEADER_LEN
#define MKNODAT_E_SIZE HEADER_LEN
#define NEWFSTATAT_E_SIZE HEADER_LEN
#define PROCESS_VM_READV_E_SIZE HEADER_LEN
#define PROCESS_VM_WRITEV_E_SIZE HEADER_LEN

/* Generic tracepoints events. */
#define SCHED_SWITCH_SIZE HEADER_LEN + sizeof(int64_t) + sizeof(uint64_t) * 2 + sizeof(uint32_t) * 3 + PARAM_LEN * 6
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/*
* Copyright (C) 2024 The Falco Authors.
*
* This file is dual licensed under either the MIT or GPL 2. See MIT.txt
* or GPL2.txt for full copies of the license.
*/

#include <helpers/interfaces/fixed_size_event.h>
#include <helpers/interfaces/variable_size_event.h>

/*=============================== ENTER EVENT ===========================*/

SEC("tp_btf/sys_enter")
int BPF_PROG(process_vm_readv_e,
struct pt_regs *regs,
long id)
{
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, ctx, PROCESS_VM_READV_E_SIZE, PPME_SYSCALL_PROCESS_VM_READV_E))
{
return 0;
}

ringbuf__store_event_header(&ringbuf);

/*=============================== COLLECT PARAMETERS ===========================*/

// Here we have no parameters to collect.

/*=============================== COLLECT PARAMETERS ===========================*/

ringbuf__submit_event(&ringbuf);

return 0;
}

/*=============================== ENTER EVENT ===========================*/

/*=============================== EXIT EVENT ===========================*/

SEC("tp_btf/sys_exit")
int BPF_PROG(process_vm_readv_x,
struct pt_regs *regs,
long ret)
{
struct auxiliary_map *auxmap = auxmap__get();
if(!auxmap)
{
return 0;
}

auxmap__preload_event_header(auxmap, PPME_SYSCALL_PROCESS_VM_READV_X);


/*=============================== COLLECT PARAMETERS ===========================*/

/* Parameter 1: res (type: PT_INT64) */
auxmap__store_s64_param(auxmap, ret);

/* Parameter 2: pid (type: PT_PID) */
int64_t pid = extract__syscall_argument(regs, 0);
auxmap__store_s64_param(auxmap, pid);
Comment on lines +62 to +63
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same in the other syscall, otherwise cases with -1 won't be handled

pid_t pid = (int32_t)extract__syscall_argument(regs, 0);
auxmap__store_s64_param(auxmap, (int64_t)pid);


if(ret > 0)
{
/* We read the minimum between `snaplen` and what we really
* have in the buffer.
*/
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, true);
if(snaplen > ret)
{
snaplen = ret;
}

unsigned long iov_pointer = extract__syscall_argument(regs, 3);
unsigned long iov_cnt = extract__syscall_argument(regs, 4);

/* Parameter 3: data (type: PT_BYTEBUF) */
auxmap__store_iovec_data_param(auxmap, iov_pointer, iov_cnt, snaplen);
}
else
{
/* Parameter 3: data (type: PT_BYTEBUF) */
auxmap__store_empty_param(auxmap);
}

/*=============================== COLLECT PARAMETERS ===========================*/

auxmap__finalize_event_header(auxmap);

auxmap__submit_event(auxmap, ctx);

return 0;
}

/*=============================== EXIT EVENT ===========================*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/*
* Copyright (C) 2024 The Falco Authors.
*
* This file is dual licensed under either the MIT or GPL 2. See MIT.txt
* or GPL2.txt for full copies of the license.
*/

#include <helpers/interfaces/fixed_size_event.h>
#include <helpers/interfaces/variable_size_event.h>

/*=============================== ENTER EVENT ===========================*/

SEC("tp_btf/sys_enter")
int BPF_PROG(process_vm_writev_e,
struct pt_regs *regs,
long id)
{
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, ctx, PROCESS_VM_WRITEV_E_SIZE, PPME_SYSCALL_PROCESS_VM_WRITEV_E))
{
return 0;
}

ringbuf__store_event_header(&ringbuf);

/*=============================== COLLECT PARAMETERS ===========================*/

// Here we have no parameters to collect.

/*=============================== COLLECT PARAMETERS ===========================*/

ringbuf__submit_event(&ringbuf);

return 0;
}

/*=============================== ENTER EVENT ===========================*/

/*=============================== EXIT EVENT ===========================*/

SEC("tp_btf/sys_exit")
int BPF_PROG(process_vm_writev_x,
struct pt_regs *regs,
long ret)
{
struct auxiliary_map *auxmap = auxmap__get();
if(!auxmap)
{
return 0;
}

auxmap__preload_event_header(auxmap, PPME_SYSCALL_PROCESS_VM_WRITEV_X);


/*=============================== COLLECT PARAMETERS ===========================*/

/* Parameter 1: res (type: PT_INT64) */
auxmap__store_s64_param(auxmap, ret);

/* Parameter 2: pid (type: PT_PID) */
int64_t pid = extract__syscall_argument(regs, 0);
auxmap__store_s64_param(auxmap, pid);

if(ret > 0)
{
/* We read the minimum between `snaplen` and what we really
* have in the buffer.
*/
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, true);
if(snaplen > ret)
{
snaplen = ret;
}

unsigned long iov_pointer = extract__syscall_argument(regs, 1);
unsigned long iov_cnt = extract__syscall_argument(regs, 2);

//* Parameter 3: data (type: PT_BYTEBUF) */
auxmap__store_iovec_data_param(auxmap, iov_pointer, iov_cnt, snaplen);
}
else
{
/* Parameter 3: data (type: PT_BYTEBUF) */
auxmap__store_empty_param(auxmap);
}

/*=============================== COLLECT PARAMETERS ===========================*/

auxmap__finalize_event_header(auxmap);

auxmap__submit_event(auxmap, ctx);

return 0;
}

/*=============================== EXIT EVENT ===========================*/
6 changes: 5 additions & 1 deletion driver/ppm_events_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -1422,7 +1422,11 @@ typedef enum {
PPME_SYSCALL_MKNODAT_X = 417,
PPME_SYSCALL_NEWFSTATAT_E = 418,
PPME_SYSCALL_NEWFSTATAT_X = 419,
PPM_EVENT_MAX = 420
PPME_SYSCALL_PROCESS_VM_READV_E = 420,
PPME_SYSCALL_PROCESS_VM_READV_X = 421,
PPME_SYSCALL_PROCESS_VM_WRITEV_E = 422,
PPME_SYSCALL_PROCESS_VM_WRITEV_X = 423,
PPM_EVENT_MAX = 424
} ppm_event_code;
/*@}*/

Expand Down
Loading
Loading