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

agent: Support composite events #64

Merged
merged 4 commits into from
Apr 9, 2024
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
agent/src/bpf/vmlinux.h
agent/tests/agenttest/src/bpf/vmlinux.h
ueno marked this conversation as resolved.
Show resolved Hide resolved
scripts/*.csv
target/
182 changes: 174 additions & 8 deletions agent/src/bpf/audit.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
bpf_trace_printk ("%s: " format, sizeof("%s: " format), \
__PRETTY_FUNCTION__, __VA_ARGS__)

#define MAX_EVENTS 16
#define DATA_TYPE_WORD (unsigned long)-2
#define DATA_TYPE_STRING (unsigned long)-1

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

struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 4096 /* one page */);
Expand Down Expand Up @@ -150,7 +160,7 @@ record_string_data (struct pt_regs *ctx, long context, const char *key_ptr,
goto error;
}

event->size = err & (VALUE_SIZE - 1);
event->size = (unsigned long)err;

bpf_ringbuf_submit (event, 0);
return 0;
Expand All @@ -165,13 +175,19 @@ record_blob_data (struct pt_regs *ctx, long context, const char *key_ptr)
{
int err;

long value_size;
err = bpf_usdt_arg (ctx, 3, &value_size);
long value;
err = bpf_usdt_arg (ctx, 3, &value);
if (err < 0)
{
DEBUG ("unable to determine value size: %ld\n", err);
return err;
}
if (value < 0 || value > VALUE_SIZE)
{
DEBUG ("value size out of range: %ld\n", value);
return -EINVAL;
}
unsigned long value_size = (unsigned long)value;

struct audit_blob_data_event_st *event =
bpf_ringbuf_reserve (&ringbuf,
Expand Down Expand Up @@ -207,7 +223,6 @@ record_blob_data (struct pt_regs *ctx, long context, const char *key_ptr)
goto error;
}

value_size &= (VALUE_SIZE - 1);
err = bpf_probe_read_user (event->value, value_size, (void *)value_ptr);
if (err < 0)
{
Expand All @@ -226,33 +241,184 @@ 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, unsigned long value_size)
{
int err;

if (value_size > VALUE_SIZE)
{
DEBUG ("value size out of range: %lu\n", value_size);
return -EINVAL;
}

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)
{
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,
const struct crypto_auditing_data *array_ptr,
unsigned long array_size)
{
struct crypto_auditing_data events[MAX_EVENTS];
int err;

if (array_size > MAX_EVENTS)
{
DEBUG ("value size out of range: %lu\n", array_size);
return -EINVAL;
}
array_size &= MAX_EVENTS - 1;

err = bpf_probe_read_user (events,
array_size * sizeof (struct crypto_auditing_data),
array_ptr);
if (err < 0)
{
DEBUG ("unable to read from data array: %ld\n", err);
return err;
}

for (unsigned long i = 0; i < array_size; i++)
{
switch (events[i].value_size)
ueno marked this conversation as resolved.
Show resolved Hide resolved
{
case DATA_TYPE_WORD:
err = record_word_data (ctx, context,
events[i].key_ptr,
(long) events[i].value_ptr);
if (err < 0)
DEBUG ("unable to process word data: %ld\n", err);
break;

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

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

if (err < 0)
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,
unsigned 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)
{
return record_new_context(ctx, context, parent);
return record_new_context (ctx, context, parent);
}

SEC("usdt")
int
BPF_USDT(word_data, long context, const char *key_ptr, long value)
{
return record_word_data(ctx, context, key_ptr, value);
return record_word_data (ctx, context, key_ptr, value);
}

SEC("usdt")
int
BPF_USDT(string_data, long context, const char *key_ptr,
const char *value_ptr)
{
return record_string_data(ctx, context, key_ptr, value_ptr);
return record_string_data (ctx, context, key_ptr, value_ptr);
}

SEC("usdt")
int
BPF_USDT(blob_data, long context, const char *key_ptr)
{
return record_blob_data(ctx, context, key_ptr);
return record_blob_data (ctx, context, key_ptr);
}

SEC("usdt")
int
BPF_USDT(data, long context, const struct crypto_auditing_data *array_ptr,
ueno marked this conversation as resolved.
Show resolved Hide resolved
unsigned 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,
void *array_ptr, unsigned 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
Loading
Loading