Skip to content

Commit

Permalink
update(modern_bpf): reduce the execve instrumentation time with new…
Browse files Browse the repository at this point in the history
… APIs

Signed-off-by: Andrea Terzolo <[email protected]>
  • Loading branch information
Andreagit97 committed Oct 2, 2022
1 parent 454832d commit 3bcbd53
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 69 deletions.
33 changes: 0 additions & 33 deletions driver/modern_bpf/helpers/extract/extract_from_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,39 +210,6 @@ static __always_inline u64 extract__capability(struct task_struct *task, enum ca
return capabilities_to_scap(((unsigned long)cap_struct.cap[1] << 32) | cap_struct.cap[0]);
}

///////////////////////////
// CHARBUF EXTRACION
///////////////////////////

/**
* @brief Extract a specif charbuf pointer from an array of charbuf pointers
* using `index`.
*
* Please note: Here we don't care about the result of `bpf_probe_read_...()`
* if we obtain a not-valid pointer we will manage it in the caller
* functions.
*
* @param array charbuf pointers array.
* @param index at which we want to extract the charbuf pointer.
* @param mem from which memory we need to read: user-space or kernel-space.
* @return unsigned long return the extracted charbuf pointer or an invalid pointer in
* case of failure.
*/
static __always_inline unsigned long extract__charbuf_pointer_from_array(unsigned long array, u16 index, enum read_memory mem)
{
char **charbuf_array = (char **)array;
char *charbuf_pointer = NULL;
if(mem == KERNEL)
{
bpf_probe_read_kernel(&charbuf_pointer, sizeof(charbuf_pointer), &charbuf_array[index]);
}
else
{
bpf_probe_read_user(&charbuf_pointer, sizeof(charbuf_pointer), &charbuf_array[index]);
}
return (unsigned long)charbuf_pointer;
}

/////////////////////////
// PIDS EXTRACION
////////////////////////
Expand Down
68 changes: 38 additions & 30 deletions driver/modern_bpf/helpers/store/auxmap_store_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ enum connection_direction
/* Maximum number of charbuf pointers that we assume an array can have. */
#define MAX_CHARBUF_POINTERS 16

/* Maximum length of an `execve` arg. */
#define MAX_EXECVE_ARG_LEN 4096

/* Concept of auxamp (auxiliary map):
*
* For variable size events we cannot directly reserve space into the ringbuf,
Expand Down Expand Up @@ -344,58 +347,63 @@ static __always_inline u16 auxmap__store_bytebuf_param(struct auxiliary_map *aux
}

/**
* @brief Use `auxmap__store_single_charbuf_param_from_array` when
* you have to store a charbuf from a charbuf pointer array.
* You have to provide the index of the charbuf pointer inside the
* array. Indexes start from '0' as usual.
* Once we obtain the pointer with `extract__charbuf_pointer_from_array`,
* we can store the charbuf with `auxmap__store_charbuf_param`.
* @brief Use `auxmap__store_execve_exe` when you have to store the
* `exe` name from an execve-family syscall.
* By convention, `exe` is `argv[0]`, this is the reason why here we pass the `argv` array.
*
* @param auxmap pointer to the auxmap in which we are storing the param.
* @param array charbuf pointer array.
* @param index position at which we want to extract our charbuf.
* @param mem from which memory we need to read: user-space or kernel-space.
* @param array charbuf pointer array, obtained directly from the syscall (`argv`).
*/
static __always_inline void auxmap__store_single_charbuf_param_from_array(struct auxiliary_map *auxmap, unsigned long array, u16 index, enum read_memory mem)
static __always_inline void auxmap__store_execve_exe(struct auxiliary_map *auxmap, char **array)
{
unsigned long charbuf_pointer = extract__charbuf_pointer_from_array(array, index, mem);
auxmap__store_charbuf_param(auxmap, charbuf_pointer, mem);
unsigned long charbuf_pointer = 0;
u16 exe_len = 0;

if(bpf_probe_read_user(&charbuf_pointer, sizeof(charbuf_pointer), &array[0]))
{
push__param_len(auxmap->data, &auxmap->lengths_pos, exe_len);
return;
}

exe_len = push__charbuf(auxmap->data, &auxmap->payload_pos, charbuf_pointer, MAX_EXECVE_ARG_LEN, USER);
push__param_len(auxmap->data, &auxmap->lengths_pos, exe_len);
}

/**
* @brief Use `auxmap__store_multiple_charbufs_param_from_array` when
* you have to store multiple charbufs from a charbuf pointer
* array. You have to provide an index that states where to start
* the charbuf collection. If you want to store all the charbufs
* pointed in the array, you can use '0' as 'index'.
* @brief Use `auxmap__store_execve_args` when you have to store
* `argv` or `envp` params from an execve-family syscall.
* You have to provide an index that states where to start
* the charbuf collection. This is becuase with `argv` we want to avoid
* the first param (`argv[0]`), since it is already collected with
* `auxmap__store_execve_exe`.
*
* Please note: right now we assume that our arrays have no more
* than `MAX_CHARBUF_POINTERS`
*
* @param auxmap pointer to the auxmap in which we are storing the param.
* @param array charbuf pointer array
* @param array charbuf pointer array, obtained directly from the syscall (`argv` or `envp`).
* @param index position at which we start to collect our charbufs.
* @param mem from which memory we need to read: user-space or kernel-space.
*/
static __always_inline void auxmap__store_multiple_charbufs_param_from_array(struct auxiliary_map *auxmap, unsigned long array, u16 index, enum read_memory mem)
static __always_inline void auxmap__store_execve_args(struct auxiliary_map *auxmap, char **array, u16 index)
{
unsigned long charbuf_pointer;
u16 charbuf_len = 0;
unsigned long charbuf_pointer = 0;
u16 arg_len = 0;
u16 total_len = 0;
/* We push in the auxmap all the charbufs that we find.
* We push the overall length only at the end of the
* for loop with `push__param_len`.
*/

for(; index < MAX_CHARBUF_POINTERS; ++index)
{
charbuf_pointer = extract__charbuf_pointer_from_array(array, index, mem);
charbuf_len = push__charbuf(auxmap->data, &auxmap->payload_pos, charbuf_pointer, MAX_PARAM_SIZE, mem);
if(!charbuf_len)
if(bpf_probe_read_user(&charbuf_pointer, sizeof(charbuf_pointer), &array[index]))
{
break;
}
total_len += charbuf_len;
arg_len = push__charbuf(auxmap->data, &auxmap->payload_pos, charbuf_pointer, MAX_EXECVE_ARG_LEN, USER);
if(!arg_len)
{
break;
}
total_len += arg_len;
}

push__param_len(auxmap->data, &auxmap->lengths_pos, total_len);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@ int BPF_PROG(execve_x,
unsigned long argv = extract__syscall_argument(regs, 1);

/* Parameter 2: exe (type: PT_CHARBUF) */
auxmap__store_single_charbuf_param_from_array(auxmap, argv, 0, USER);
auxmap__store_execve_exe(auxmap, (char **)argv);

/* Parameter 3: args (type: PT_CHARBUFARRAY) */
auxmap__store_multiple_charbufs_param_from_array(auxmap, argv, 1, USER);
auxmap__store_execve_args(auxmap, (char **)argv, 1);
}

/* Parameter 4: tid (type: PT_PID) */
Expand Down Expand Up @@ -209,7 +209,7 @@ int BPF_PROG(t1_execve_x,
{
/* Parameter 16: env (type: PT_CHARBUFARRAY) */
unsigned long envp = extract__syscall_argument(regs, 2);
auxmap__store_multiple_charbufs_param_from_array(auxmap, envp, 0, USER);
auxmap__store_execve_args(auxmap, (char **)envp, 0);
}

/* Parameter 17: tty (type: PT_INT32) */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ int BPF_PROG(execveat_x,
unsigned long argv = extract__syscall_argument(regs, 2);

/* Parameter 2: exe (type: PT_CHARBUF) */
auxmap__store_single_charbuf_param_from_array(auxmap, argv, 0, USER);
auxmap__store_execve_exe(auxmap, (char **)argv);

/* Parameter 3: args (type: PT_CHARBUFARRAY) */
auxmap__store_multiple_charbufs_param_from_array(auxmap, argv, 1, USER);
auxmap__store_execve_args(auxmap, (char **)argv, 1);

/* Parameter 4: tid (type: PT_PID) */
/* this is called `tid` but it is the `pid`. */
Expand Down Expand Up @@ -167,7 +167,7 @@ int BPF_PROG(t1_execveat_x,

/* Parameter 16: env (type: PT_CHARBUFARRAY) */
unsigned long envp = extract__syscall_argument(regs, 3);
auxmap__store_multiple_charbufs_param_from_array(auxmap, envp, 0, USER);
auxmap__store_execve_args(auxmap, (char **)envp, 0);

/* Parameter 17: tty (type: PT_INT32) */
u32 tty = exctract__tty(task);
Expand Down

0 comments on commit 3bcbd53

Please sign in to comment.