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

tetragon: Add support for uprobe arguments #1978

Merged
merged 14 commits into from
Jan 25, 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 api/v1/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions api/v1/tetragon/codegen/eventchecker/eventchecker.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

293 changes: 153 additions & 140 deletions api/v1/tetragon/tetragon.pb.go

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions api/v1/tetragon/tetragon.proto
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,8 @@ message ProcessUprobe {
string policy_name = 5;
// Short message of the Tracing Policy to inform users what is going on.
string message = 6;
// Arguments definition of the observed uprobe.
repeated KprobeArgument args = 7;
}

message KernelModule {
Expand Down
10 changes: 5 additions & 5 deletions bpf/process/generic_calls.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,11 @@ generic_process_event_and_setup(struct pt_regs *ctx,

#ifdef GENERIC_UPROBE
/* no arguments for uprobes for now */
e->a0 = 0;
e->a1 = 0;
e->a2 = 0;
e->a3 = 0;
e->a4 = 0;
e->a0 = PT_REGS_PARM1_CORE(ctx);
e->a1 = PT_REGS_PARM2_CORE(ctx);
e->a2 = PT_REGS_PARM3_CORE(ctx);
e->a3 = PT_REGS_PARM4_CORE(ctx);
e->a4 = PT_REGS_PARM5_CORE(ctx);
generic_process_init(e, MSG_OP_GENERIC_UPROBE, config);
#endif

Expand Down
17 changes: 17 additions & 0 deletions bpf/process/types/basic.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ enum {

syscall64_type = 28,

s16_ty = 29,
u16_ty = 30,
s8_ty = 31,
u8_ty = 32,

nop_s64_ty = -10,
nop_u64_ty = -11,
nop_u32_ty = -12,
Expand Down Expand Up @@ -2454,6 +2459,18 @@ read_call_arg(void *ctx, struct msg_generic_kprobe *e, int index, int type,
probe_read(args, sizeof(__u32), &arg);
size = sizeof(__u32);
break;
case s16_ty:
case u16_ty:
/* read 2 bytes, but send 4 to keep alignment */
probe_read(args, sizeof(__u16), &arg);
size = sizeof(__u32);
break;
case s8_ty:
case u8_ty:
kkourt marked this conversation as resolved.
Show resolved Hide resolved
/* read 1 byte, but send 4 to keep alignment */
probe_read(args, sizeof(__u8), &arg);
size = sizeof(__u32);
break;
case skb_type:
size = copy_skb(args, arg);
break;
Expand Down
30 changes: 30 additions & 0 deletions contrib/tester-progs/uprobe-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,33 @@ int uprobe_test_lib()
printf("uprobe_test_lib called\n");
return 0;
}

int uprobe_test_lib_arg1(int a1)
{
printf("uprobe_test_lib_arg1 called\n");
return 0;
}

int uprobe_test_lib_arg2(char a1, short a2)
{
printf("uprobe_test_lib_arg2 called\n");
return 0;
}

int uprobe_test_lib_arg3(unsigned long a1, unsigned int a2, void *a3)
{
printf("uprobe_test_lib_arg3 called\n");
return 0;
}

int uprobe_test_lib_arg4(long a1, int a2, char a3, void *a4)
{
printf("uprobe_test_lib_arg3 called\n");
return 0;
}

int uprobe_test_lib_arg5(int a1, char a2, unsigned long a3, short a4, void *a5)
{
printf("uprobe_test_lib_arg3 called\n");
return 0;
}
12 changes: 12 additions & 0 deletions contrib/tester-progs/uprobe-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,19 @@

void uprobe_test_lib(void);

// argument test functions
int uprobe_test_lib_arg1(int a1);
int uprobe_test_lib_arg2(char a1, short a2);
int uprobe_test_lib_arg3(unsigned long a1, unsigned int a2, void *a3);
int uprobe_test_lib_arg4(long a1, int a2, char a3, void *a4);
int uprobe_test_lib_arg5(int a1, char a2, unsigned long a3, short a4, void *a5);

int main(void)
{
uprobe_test_lib();
uprobe_test_lib_arg1(123);
uprobe_test_lib_arg2('a', 4321);
uprobe_test_lib_arg3(1, 0xdeadbeef, NULL);
uprobe_test_lib_arg4(-321, -2, 'b', (void *) 1);
uprobe_test_lib_arg5(1, 'c', 0xcafe, 1234, (void *) 2);
}
3 changes: 2 additions & 1 deletion docs/content/en/docs/concepts/tracing-policy/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ metadata:
spec:
uprobes:
- path: "/bin/bash"
symbol: "readline"
symbols:
- "readline"
```

This example shows how to use uprobes to hook into the readline function
Expand Down
1 change: 1 addition & 0 deletions docs/content/en/docs/reference/grpc-api.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions pkg/api/tracingapi/client_kprobe.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,20 @@ func (m MsgGenericKprobeArgSize) IsReturnArg() bool {
return m.Index == ReturnArgIndex
}

type MsgGenericKprobeArgLong struct {
Index uint64
Value int64
Label string
}

func (m MsgGenericKprobeArgLong) GetIndex() uint64 {
return m.Index
}

func (m MsgGenericKprobeArgLong) IsReturnArg() bool {
return m.Index == ReturnArgIndex
}

type MsgGenericKprobeTuple struct {
Saddr [2]uint64
Daddr [2]uint64
Expand Down
34 changes: 32 additions & 2 deletions pkg/btf/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,13 @@ func ValidateKprobeSpec(bspec *btf.Spec, call string, kspec *v1alpha1.KProbeSpec
func getKernelType(arg btf.Type) string {
suffix := ""
ptr, ok := arg.(*btf.Pointer)

if ok {
arg = ptr.Target
_, ok = arg.(*btf.Void)
if ok {
return "void *"
}
suffix = suffix + " *"
}
num, ok := arg.(*btf.Int)
Expand All @@ -144,14 +149,39 @@ func getKernelType(arg btf.Type) string {

func typesCompatible(specTy string, kernelTy string) bool {
switch specTy {
case "uint64":
switch kernelTy {
case "u64", "void *":
return true
}
case "int64":
switch kernelTy {
case "s64":
return true
}
case "int16":
switch kernelTy {
case "s16", "short int":
return true
}
case "uint16":
switch kernelTy {
case "u16", "short unsigned int":
return true
}
case "uint8":
switch kernelTy {
case "u8", "unsigned char":
return true
}
case "size_t":
switch kernelTy {
case "size_t":
return true
}
case "char_buf", "string":
case "char_buf", "string", "int8":
switch kernelTy {
case "const char *", "char *":
case "const char *", "char *", "char":
return true
}
case "char_iovec":
Expand Down
13 changes: 13 additions & 0 deletions pkg/generictypes/generictypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ const (

GenericSyscall64 = 28

GenericS16Type = 29
GenericU16Type = 30
GenericS8Type = 31
GenericU8Type = 32

GenericNopType = -1
GenericInvalidType = -2
)
Expand Down Expand Up @@ -101,6 +106,14 @@ func GenericTypeFromString(arg string) int {
return GenericKernelModule
case "syscall64":
return GenericSyscall64
case "sint16", "int16":
return GenericS16Type
case "uint16":
return GenericU16Type
case "sint8", "int8":
return GenericS8Type
case "uint8":
return GenericU8Type
default:
return GenericInvalidType
}
Expand Down
Loading
Loading