Skip to content

Commit

Permalink
Fix go http2 internal support (#1590)
Browse files Browse the repository at this point in the history
  • Loading branch information
grcevski authored Jan 29, 2025
1 parent 6885a35 commit 0b47146
Show file tree
Hide file tree
Showing 21 changed files with 164 additions and 98 deletions.
84 changes: 44 additions & 40 deletions bpf/go_grpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -743,37 +743,6 @@ int beyla_uprobe_grpcFramerWriteHeaders_returns(struct pt_regs *ctx) {
if (buf_arr && n < (cap - HTTP2_ENCODED_HEADER_LEN)) {
uint8_t tp_str[TP_MAX_VAL_LENGTH];

u8 type_byte = 0;
u8 key_len = TP_ENCODED_LEN | 0x80; // high tagged to signify hpack encoded value
u8 val_len = TP_MAX_VAL_LENGTH;

// We don't hpack encode the value of the traceparent field, because that will require that
// we use bpf_loop, which in turn increases the kernel requirement to 5.17+.
make_tp_string(tp_str, &f_info->tp);
//bpf_dbg_printk("Will write %s, type = %d, key_len = %d, val_len = %d", tp_str, type_byte, key_len, val_len);

bpf_probe_write_user(buf_arr + (n & 0x0ffff), &type_byte, sizeof(type_byte));
n++;
// Write the length of the key = 8
bpf_probe_write_user(buf_arr + (n & 0x0ffff), &key_len, sizeof(key_len));
n++;
// Write 'traceparent' encoded as hpack
bpf_probe_write_user(buf_arr + (n & 0x0ffff), tp_encoded, sizeof(tp_encoded));
;
n += TP_ENCODED_LEN;
// Write the length of the hpack encoded traceparent field
bpf_probe_write_user(buf_arr + (n & 0x0ffff), &val_len, sizeof(val_len));
n++;
bpf_probe_write_user(buf_arr + (n & 0x0ffff), tp_str, sizeof(tp_str));
n += TP_MAX_VAL_LENGTH;
// Update the value of n in w to reflect the new size
bpf_probe_write_user(
(void *)(w_ptr +
go_offset_of(ot,
(go_offset){.v = _grpc_transport_buf_writer_offset_pos})),
&n,
sizeof(n));

// http2 encodes the length of the headers in the first 3 bytes of buf, we need to update those
u8 size_1 = 0;
u8 size_2 = 0;
Expand All @@ -786,16 +755,51 @@ int beyla_uprobe_grpcFramerWriteHeaders_returns(struct pt_regs *ctx) {
bpf_dbg_printk("size 1:%x, 2:%x, 3:%x", size_1, size_2, size_3);

u32 original_size = ((u32)(size_1) << 16) | ((u32)(size_2) << 8) | size_3;
u32 new_size = original_size + HTTP2_ENCODED_HEADER_LEN;

bpf_dbg_printk("Changing size from %d to %d", original_size, new_size);
size_1 = (u8)(new_size >> 16);
size_2 = (u8)(new_size >> 8);
size_3 = (u8)(new_size);

bpf_probe_write_user((void *)(buf_arr + off), &size_1, sizeof(size_1));
bpf_probe_write_user((void *)(buf_arr + off + 1), &size_2, sizeof(size_2));
bpf_probe_write_user((void *)(buf_arr + off + 2), &size_3, sizeof(size_3));
if (original_size > 0) {
u8 type_byte = 0;
u8 key_len =
TP_ENCODED_LEN | 0x80; // high tagged to signify hpack encoded value
u8 val_len = TP_MAX_VAL_LENGTH;

// We don't hpack encode the value of the traceparent field, because that will require that
// we use bpf_loop, which in turn increases the kernel requirement to 5.17+.
make_tp_string(tp_str, &f_info->tp);
//bpf_dbg_printk("Will write %s, type = %d, key_len = %d, val_len = %d", tp_str, type_byte, key_len, val_len);

bpf_probe_write_user(buf_arr + (n & 0x0ffff), &type_byte, sizeof(type_byte));
n++;
// Write the length of the key = 8
bpf_probe_write_user(buf_arr + (n & 0x0ffff), &key_len, sizeof(key_len));
n++;
// Write 'traceparent' encoded as hpack
bpf_probe_write_user(buf_arr + (n & 0x0ffff), tp_encoded, sizeof(tp_encoded));
;
n += TP_ENCODED_LEN;
// Write the length of the hpack encoded traceparent field
bpf_probe_write_user(buf_arr + (n & 0x0ffff), &val_len, sizeof(val_len));
n++;
bpf_probe_write_user(buf_arr + (n & 0x0ffff), tp_str, sizeof(tp_str));
n += TP_MAX_VAL_LENGTH;
// Update the value of n in w to reflect the new size
bpf_probe_write_user(
(void *)(w_ptr +
go_offset_of(
ot, (go_offset){.v = _grpc_transport_buf_writer_offset_pos})),
&n,
sizeof(n));

u32 new_size = original_size + HTTP2_ENCODED_HEADER_LEN;

bpf_dbg_printk("Changing size from %d to %d", original_size, new_size);
size_1 = (u8)(new_size >> 16);
size_2 = (u8)(new_size >> 8);
size_3 = (u8)(new_size);

bpf_probe_write_user((void *)(buf_arr + off), &size_1, sizeof(size_1));
bpf_probe_write_user((void *)(buf_arr + off + 1), &size_2, sizeof(size_2));
bpf_probe_write_user((void *)(buf_arr + off + 2), &size_3, sizeof(size_3));
}
}
}
}
Expand Down
88 changes: 50 additions & 38 deletions bpf/go_nethttp.h
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,7 @@ int beyla_uprobe_http2FramerWriteHeaders(struct pt_regs *ctx) {
sizeof(n),
(void *)(w_ptr + go_offset_of(ot, (go_offset){.v = _io_writer_n_pos})));

bpf_dbg_printk("Found initial n = %d", n);
bpf_dbg_printk("Found initial n = %d, framer_ptr %llx", n, framer);

// The offset is 0 on all connections we've tested with.
// If we read some very large offset, we don't do anything since it might be a situation
Expand Down Expand Up @@ -933,6 +933,11 @@ int beyla_uprobe_http2FramerWriteHeaders_returns(struct pt_regs *ctx) {
sizeof(w_ptr),
(void *)(f_info->framer_ptr + go_offset_of(ot, (go_offset){.v = _framer_w_pos}) + 8));

bpf_dbg_printk("framer_ptr %llx, w_ptr %llx, w_pos %d",
f_info->framer_ptr,
w_ptr,
go_offset_of(ot, (go_offset){.v = _framer_w_pos}) + 8);

u64 io_writer_n_pos = go_offset_of(ot, (go_offset){.v = _io_writer_n_pos});

if (w_ptr) {
Expand All @@ -953,36 +958,12 @@ int beyla_uprobe_http2FramerWriteHeaders_returns(struct pt_regs *ctx) {

bpf_clamp_umax(initial_n, MAX_W_PTR_N);

//bpf_dbg_printk("Found f_info, this is the place to write to w = %llx, buf=%llx, n=%lld, size=%lld", w_ptr, buf_arr, n, cap);
bpf_dbg_printk(
"Found f_info, this is the place to write to w = %llx, buf=%llx", w_ptr, buf_arr);
bpf_dbg_printk("Found f_info, this is the place to write to n=%lld, size=%lld", n, cap);
if (buf_arr && n < (cap - HTTP2_ENCODED_HEADER_LEN)) {
uint8_t tp_str[TP_MAX_VAL_LENGTH];

u8 type_byte = 0;
u8 key_len = TP_ENCODED_LEN | 0x80; // high tagged to signify hpack encoded value
u8 val_len = TP_MAX_VAL_LENGTH;

// We don't hpack encode the value of the traceparent field, because that will require that
// we use bpf_loop, which in turn increases the kernel requirement to 5.17+.
make_tp_string(tp_str, &f_info->tp);
//bpf_dbg_printk("Will write %s, type = %d, key_len = %d, val_len = %d", tp_str, type_byte, key_len, val_len);

bpf_probe_write_user(buf_arr + (n & 0x0ffff), &type_byte, sizeof(type_byte));
n++;
// Write the length of the key = 8
bpf_probe_write_user(buf_arr + (n & 0x0ffff), &key_len, sizeof(key_len));
n++;
// Write 'traceparent' encoded as hpack
bpf_probe_write_user(buf_arr + (n & 0x0ffff), tp_encoded, sizeof(tp_encoded));
;
n += TP_ENCODED_LEN;
// Write the length of the hpack encoded traceparent field
bpf_probe_write_user(buf_arr + (n & 0x0ffff), &val_len, sizeof(val_len));
n++;
bpf_probe_write_user(buf_arr + (n & 0x0ffff), tp_str, sizeof(tp_str));
n += TP_MAX_VAL_LENGTH;
// Update the value of n in w to reflect the new size
bpf_probe_write_user((void *)(w_ptr + io_writer_n_pos), &n, sizeof(n));

// http2 encodes the length of the headers in the first 3 bytes of buf, we need to update those
u8 size_1 = 0;
u8 size_2 = 0;
Expand All @@ -995,16 +976,47 @@ int beyla_uprobe_http2FramerWriteHeaders_returns(struct pt_regs *ctx) {
bpf_dbg_printk("size 1:%x, 2:%x, 3:%x", size_1, size_2, size_3);

u32 original_size = ((u32)(size_1) << 16) | ((u32)(size_2) << 8) | size_3;
u32 new_size = original_size + HTTP2_ENCODED_HEADER_LEN;

bpf_dbg_printk("Changing size from %d to %d", original_size, new_size);
size_1 = (u8)(new_size >> 16);
size_2 = (u8)(new_size >> 8);
size_3 = (u8)(new_size);

bpf_probe_write_user((void *)(buf_arr + initial_n), &size_1, sizeof(size_1));
bpf_probe_write_user((void *)(buf_arr + initial_n + 1), &size_2, sizeof(size_2));
bpf_probe_write_user((void *)(buf_arr + initial_n + 2), &size_3, sizeof(size_3));
if (original_size > 0) {
u8 type_byte = 0;
u8 key_len =
TP_ENCODED_LEN | 0x80; // high tagged to signify hpack encoded value
u8 val_len = TP_MAX_VAL_LENGTH;

// We don't hpack encode the value of the traceparent field, because that will require that
// we use bpf_loop, which in turn increases the kernel requirement to 5.17+.
make_tp_string(tp_str, &f_info->tp);
//bpf_dbg_printk("Will write %s, type = %d, key_len = %d, val_len = %d", tp_str, type_byte, key_len, val_len);

bpf_probe_write_user(buf_arr + (n & 0x0ffff), &type_byte, sizeof(type_byte));
n++;
// Write the length of the key = 8
bpf_probe_write_user(buf_arr + (n & 0x0ffff), &key_len, sizeof(key_len));
n++;
// Write 'traceparent' encoded as hpack
bpf_probe_write_user(buf_arr + (n & 0x0ffff), tp_encoded, sizeof(tp_encoded));
;
n += TP_ENCODED_LEN;
// Write the length of the hpack encoded traceparent field
bpf_probe_write_user(buf_arr + (n & 0x0ffff), &val_len, sizeof(val_len));
n++;
bpf_probe_write_user(buf_arr + (n & 0x0ffff), tp_str, sizeof(tp_str));
n += TP_MAX_VAL_LENGTH;
// Update the value of n in w to reflect the new size
bpf_probe_write_user((void *)(w_ptr + io_writer_n_pos), &n, sizeof(n));

u32 new_size = original_size + HTTP2_ENCODED_HEADER_LEN;

bpf_dbg_printk("Changing size from %d to %d", original_size, new_size);
size_1 = (u8)(new_size >> 16);
size_2 = (u8)(new_size >> 8);
size_3 = (u8)(new_size);

bpf_probe_write_user((void *)(buf_arr + initial_n), &size_1, sizeof(size_1));
bpf_probe_write_user(
(void *)(buf_arr + initial_n + 1), &size_2, sizeof(size_2));
bpf_probe_write_user(
(void *)(buf_arr + initial_n + 2), &size_3, sizeof(size_3));
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions configs/offsets/tracker_input.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@
],
"net/http.http2serverConn": [
"conn"
],
"net/http.http2Framer": [
"w"
],
"net/http.http2MetaHeadersFrame": [
"Fields"
]
}
},
Expand Down
2 changes: 1 addition & 1 deletion pkg/internal/ebpf/generictracer/bpf_arm64_bpfel.o
Git LFS file not shown
2 changes: 1 addition & 1 deletion pkg/internal/ebpf/generictracer/bpf_debug_arm64_bpfel.o
Git LFS file not shown
2 changes: 1 addition & 1 deletion pkg/internal/ebpf/generictracer/bpf_debug_x86_bpfel.o
Git LFS file not shown
2 changes: 1 addition & 1 deletion pkg/internal/ebpf/generictracer/bpf_tp_arm64_bpfel.o
Git LFS file not shown
2 changes: 1 addition & 1 deletion pkg/internal/ebpf/generictracer/bpf_tp_debug_arm64_bpfel.o
Git LFS file not shown
2 changes: 1 addition & 1 deletion pkg/internal/ebpf/generictracer/bpf_tp_debug_x86_bpfel.o
Git LFS file not shown
2 changes: 1 addition & 1 deletion pkg/internal/ebpf/generictracer/bpf_tp_x86_bpfel.o
Git LFS file not shown
2 changes: 1 addition & 1 deletion pkg/internal/ebpf/generictracer/bpf_x86_bpfel.o
Git LFS file not shown
2 changes: 1 addition & 1 deletion pkg/internal/ebpf/gotracer/bpf_arm64_bpfel.o
Git LFS file not shown
2 changes: 1 addition & 1 deletion pkg/internal/ebpf/gotracer/bpf_debug_arm64_bpfel.o
Git LFS file not shown
2 changes: 1 addition & 1 deletion pkg/internal/ebpf/gotracer/bpf_debug_x86_bpfel.o
Git LFS file not shown
4 changes: 2 additions & 2 deletions pkg/internal/ebpf/gotracer/bpf_tp_arm64_bpfel.o
Git LFS file not shown
4 changes: 2 additions & 2 deletions pkg/internal/ebpf/gotracer/bpf_tp_debug_arm64_bpfel.o
Git LFS file not shown
4 changes: 2 additions & 2 deletions pkg/internal/ebpf/gotracer/bpf_tp_debug_x86_bpfel.o
Git LFS file not shown
4 changes: 2 additions & 2 deletions pkg/internal/ebpf/gotracer/bpf_tp_x86_bpfel.o
Git LFS file not shown
2 changes: 1 addition & 1 deletion pkg/internal/ebpf/gotracer/bpf_x86_bpfel.o
Git LFS file not shown
32 changes: 32 additions & 0 deletions pkg/internal/goexec/offsets.json
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,38 @@
]
}
},
"net/http.http2Framer": {
"w": {
"versions": {
"oldest": "1.17.0",
"newest": "1.23.5"
},
"offsets": [
{
"offset": 112,
"since": "1.17.0"
},
{
"offset": 120,
"since": "1.18.0"
}
]
}
},
"net/http.http2MetaHeadersFrame": {
"Fields": {
"versions": {
"oldest": "1.17.0",
"newest": "1.23.5"
},
"offsets": [
{
"offset": 8,
"since": "1.17.0"
}
]
}
},
"net/http.http2serverConn": {
"conn": {
"versions": {
Expand Down
12 changes: 12 additions & 0 deletions pkg/internal/goexec/structmembers.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ var structMembers = map[string]structInfo{
"tconn": CcTconnPos,
},
},
"net/http.http2Framer": {
lib: "go",
fields: map[string]GoOffset{
"w": FramerWPos,
},
},
"golang.org/x/net/http2.Framer": {
lib: "golang.org/x/net",
fields: map[string]GoOffset{
Expand All @@ -190,6 +196,12 @@ var structMembers = map[string]structInfo{
"Fields": MetaHeadersFrameFieldsPtrPos,
},
},
"net/http.http2MetaHeadersFrame": {
lib: "go",
fields: map[string]GoOffset{
"Fields": MetaHeadersFrameFieldsPtrPos,
},
},
"golang.org/x/net/http2.serverConn": {
lib: "golang.org/x/net",
fields: map[string]GoOffset{
Expand Down

0 comments on commit 0b47146

Please sign in to comment.