Skip to content

Commit

Permalink
agent: Support composite events
Browse files Browse the repository at this point in the history
CRYPTO_AUDITING_*_DATA defines a single USDT probe point for each
invocation.  This causes multiple context switches to happen if they
are writen in series.  This adds a new macro, CRYPTO_AUDITING_DATA and
CRYPTO_AUDITING_DATAV, which take an array of events to limit the
number of context switches.

Signed-off-by: Daiki Ueno <[email protected]>
  • Loading branch information
ueno committed Dec 31, 2023
1 parent edbc692 commit 29d89b0
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 0 deletions.
131 changes: 131 additions & 0 deletions agent/src/bpf/audit.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
bpf_trace_printk ("%s: " format, sizeof("%s: " format), \
__PRETTY_FUNCTION__, __VA_ARGS__)

struct crypto_auditing_data {
char *key_ptr;
void *value_ptr;
long value_size;
};

struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 4096 /* one page */);
Expand Down Expand Up @@ -226,6 +232,114 @@ record_blob_data (struct pt_regs *ctx, long context, const char *key_ptr)
return err;
}

/* This is similar to record_blob_data but always assumes VALUE_PTR is
* present.
*/
static __always_inline int
record_blob_data_explicit (struct pt_regs *ctx, long context, const char *key_ptr,
const void *value_ptr, long value_size)
{
int err;

struct audit_blob_data_event_st *event =
bpf_ringbuf_reserve (&ringbuf,
sizeof(struct audit_blob_data_event_st),
0);
if (!event)
{
DEBUG ("unable to allocate ringbuf entry: %ld\n", -ENOMEM);
return -ENOMEM;
}

populate_event_header (&event->base.header,
AUDIT_EVENT_DATA,
sizeof(*event),
context);

event->base.type = AUDIT_DATA_BLOB;
err = bpf_probe_read_user_str (event->base.key, KEY_SIZE, (void *)key_ptr);
if (err < 0)
{
DEBUG ("unable to read event key: %ld\n", err);
goto error;
}

if (value_size > 0)
{
value_size &= (VALUE_SIZE - 1);
err = bpf_probe_read_user (event->value, value_size, (void *)value_ptr);
if (err < 0)
{
DEBUG ("unable to read event data: %ld\n", err);
goto error;
}
}

event->size = value_size;

bpf_ringbuf_submit (event, 0);
return 0;

error:
bpf_ringbuf_discard (event, 0);
return err;
}

static __always_inline int
record_data (struct pt_regs *ctx, long context,
struct crypto_auditing_data *array_ptr,
long array_size)
{
int err = 0;

for (long i = 0; i < array_size; i++)
{
switch (array_ptr[i].value_size)
{
case -2:
err = record_word_data (ctx, context,
array_ptr[i].key_ptr,
(long) array_ptr[i].value_ptr);
if (err < 0)
DEBUG ("unable to process word data: %ld\n", err);
break;

case -1:
err = record_string_data (ctx, context,
array_ptr[i].key_ptr,
(const char *) array_ptr[i].value_ptr);
if (err < 0)
DEBUG ("unable to process string data: %ld\n", err);
break;

default:
err = record_blob_data_explicit (ctx, context,
array_ptr[i].key_ptr,
array_ptr[i].value_ptr,
array_ptr[i].value_size);
if (err < 0)
DEBUG ("unable to process blob data: %ld\n", err);
break;
}
}

return err;
}

static __always_inline int
record_new_context_with_data (struct pt_regs *ctx, long context, long parent,
struct crypto_auditing_data *array_ptr,
long array_size)
{
int err;

err = record_new_context (ctx, context, parent);
if (err < 0)
return err;

return record_data (ctx, context, array_ptr, array_size);
}

SEC("usdt")
int
BPF_USDT(new_context, long context, long parent)
Expand Down Expand Up @@ -255,4 +369,21 @@ BPF_USDT(blob_data, long context, const char *key_ptr)
return record_blob_data(ctx, context, key_ptr);
}

SEC("usdt")
int
BPF_USDT(data, long context, struct crypto_auditing_data *array_ptr,
long array_size)
{
return record_data(ctx, context, array_ptr, array_size);
}

SEC("usdt")
int
BPF_USDT(new_context_with_data, long context, long parent,
struct crypto_auditing_data *array_ptr, long array_size)
{
return record_new_context_with_data(ctx, context, parent, array_ptr,
array_size);
}

char LICENSE[] SEC("license") = "GPL";
18 changes: 18 additions & 0 deletions agent/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,24 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
) {
links.push(link);
}
let prog = progs.data();
if let Ok(link) = prog.attach_usdt(
-1, // any process
library,
"crypto_auditing",
"data",
) {
links.push(link);
}
let prog = progs.new_context_with_data();
if let Ok(link) = prog.attach_usdt(
-1, // any process
library,
"crypto_auditing",
"new_context_with_data",
) {
links.push(link);
}
}

let cipher = Cipher::aes_128_ecb();
Expand Down
48 changes: 48 additions & 0 deletions dist/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,59 @@
# define CRYPTO_AUDITING_BLOB_DATA(context, key_ptr, value_ptr, value_size) \
DTRACE_PROBE4(crypto_auditing, blob_data, context, key_ptr, value_ptr, value_size)

struct crypto_auditing_data {
char *key_ptr;
void *value_ptr;
long value_size;
};

# define CRYPTO_AUDITING_WORD(key_ptr, value_ptr) \
{ key_ptr, (void *)value_ptr, -2 }
# define CRYPTO_AUDITING_STRING(key_ptr, value_ptr) \
{ key_ptr, value_ptr, -1 }
# define CRYPTO_AUDITING_BLOB(key_ptr, value_ptr, value_size) \
{ key_ptr, value_ptr, value_size }

/* Assert multiple events at once as a typed array. The VALUE_SIZE
* field indicates the type of event: -2 means a word, -1 means a
* NUL-terminated string, and any other value means a blob with the
* length of VALUE_SIZE.
*/
# define CRYPTO_AUDITING_DATA(context, array_ptr, array_size) \
DTRACE_PROBE3(crypto_auditing, data, context, array_ptr, array_size)

# define CRYPTO_AUDITING_DATAV(context, ...) ({ \
struct crypto_auditing_data __crypto_auditing_events[] = { __VA_ARGS__ }; \
CRYPTO_AUDITING_DATA(context, \
__crypto_auditing_events, \
sizeof (__crypto_auditing_events) / sizeof (__crypto_auditing_events[0])); \
})

/* Introduce a new context CONTEXT, derived from PARENT, as well as
* assert multiple events.
*/
# define CRYPTO_AUDITING_NEW_CONTEXT_WITH_DATA(context, parent, array_ptr, array_size) \
DTRACE_PROBE4(crypto_auditing, new_context_with_data, context, parent, array_ptr, array_size)

# define CRYPTO_AUDITING_NEW_CONTEXT_WITH_DATAV(context, parent, ...) ({ \
struct crypto_auditing_data __crypto_auditing_events[] = { __VA_ARGS__ }; \
CRYPTO_AUDITING_NEW_CONTEXT_WITH_DATA(context, parent, \
__crypto_auditing_events, \
sizeof (__crypto_auditing_events) / sizeof (__crypto_auditing_events[0])); \
})

#else

# define CRYPTO_AUDITING_NEW_CONTEXT(context, parent)
# define CRYPTO_AUDITING_WORD_DATA(context, key_ptr, value_ptr)
# define CRYPTO_AUDITING_STRING_DATA(context, key_ptr, value_ptr)
# define CRYPTO_AUDITING_BLOB_DATA(context, key_ptr, value_ptr, value_size)
# define CRYPTO_AUDITING_WORD(key_ptr, value_ptr)
# define CRYPTO_AUDITING_STRING(key_ptr, value_ptr)
# define CRYPTO_AUDITING_BLOB(key_ptr, value_ptr, value_size)
# define CRYPTO_AUDITING_DATA(context, array_ptr, array_size)
# define CRYPTO_AUDITING_DATAV(context, ...)
# define CRYPTO_AUDITING_NEW_CONTEXT_WITH_DATA(context, parent, array_ptr, array_size)
# define CRYPTO_AUDITING_NEW_CONTEXT_WITH_DATAV(context, parent, ...)

#endif /* ENABLE_CRYPTO_AUDITING */

0 comments on commit 29d89b0

Please sign in to comment.