Skip to content

Commit a152444

Browse files
committed
enable TLS interception for containerized k8s like minikube and kind
1 parent 29a8f90 commit a152444

File tree

7 files changed

+104
-26
lines changed

7 files changed

+104
-26
lines changed

bpf/fd_to_address_tracepoints.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct sys_enter_accept4_ctx {
2929

3030
SEC("tracepoint/syscalls/sys_enter_accept4")
3131
void sys_enter_accept4(struct sys_enter_accept4_ctx* ctx) {
32-
__u64 id = bpf_get_current_pid_tgid();
32+
__u64 id = tracer_get_current_pid_tgid();
3333

3434
if (!should_watch(id >> 32)) {
3535
return;
@@ -55,7 +55,7 @@ struct sys_exit_accept4_ctx {
5555

5656
SEC("tracepoint/syscalls/sys_exit_accept4")
5757
void sys_exit_accept4(struct sys_exit_accept4_ctx* ctx) {
58-
__u64 id = bpf_get_current_pid_tgid();
58+
__u64 id = tracer_get_current_pid_tgid();
5959

6060
if (!should_watch(id >> 32)) {
6161
return;
@@ -122,7 +122,7 @@ struct sys_enter_connect_ctx {
122122

123123
SEC("tracepoint/syscalls/sys_enter_connect")
124124
void sys_enter_connect(struct sys_enter_connect_ctx* ctx) {
125-
__u64 id = bpf_get_current_pid_tgid();
125+
__u64 id = tracer_get_current_pid_tgid();
126126

127127
if (!should_watch(id >> 32)) {
128128
return;
@@ -149,7 +149,7 @@ struct sys_exit_connect_ctx {
149149

150150
SEC("tracepoint/syscalls/sys_exit_connect")
151151
void sys_exit_connect(struct sys_exit_connect_ctx* ctx) {
152-
__u64 id = bpf_get_current_pid_tgid();
152+
__u64 id = tracer_get_current_pid_tgid();
153153

154154
if (!should_watch(id >> 32)) {
155155
return;

bpf/fd_tracepoints.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static __always_inline void fd_tracepoints_handle_go(struct sys_enter_read_write
5959

6060
SEC("tracepoint/syscalls/sys_enter_read")
6161
void sys_enter_read(struct sys_enter_read_write_ctx* ctx) {
62-
__u64 id = bpf_get_current_pid_tgid();
62+
__u64 id = tracer_get_current_pid_tgid();
6363

6464
if (!should_watch(id >> 32)) {
6565
return;
@@ -76,7 +76,7 @@ void sys_enter_read(struct sys_enter_read_write_ctx* ctx) {
7676

7777
SEC("tracepoint/syscalls/sys_enter_write")
7878
void sys_enter_write(struct sys_enter_read_write_ctx* ctx) {
79-
__u64 id = bpf_get_current_pid_tgid();
79+
__u64 id = tracer_get_current_pid_tgid();
8080

8181
if (!should_watch(id >> 32)) {
8282
return;
@@ -93,15 +93,15 @@ void sys_enter_write(struct sys_enter_read_write_ctx* ctx) {
9393

9494
SEC("tracepoint/syscalls/sys_exit_read")
9595
void sys_exit_read(struct sys_exit_read_write_ctx* ctx) {
96-
__u64 id = bpf_get_current_pid_tgid();
96+
__u64 id = tracer_get_current_pid_tgid();
9797
// Delete from go map. The value is not used after exiting this syscall.
9898
// Keep value in openssl map.
9999
bpf_map_delete_elem(&go_kernel_read_context, &id);
100100
}
101101

102102
SEC("tracepoint/syscalls/sys_exit_write")
103103
void sys_exit_write(struct sys_exit_read_write_ctx* ctx) {
104-
__u64 id = bpf_get_current_pid_tgid();
104+
__u64 id = tracer_get_current_pid_tgid();
105105
// Delete from go map. The value is not used after exiting this syscall.
106106
// Keep value in openssl map.
107107
bpf_map_delete_elem(&go_kernel_write_context, &id);

bpf/go_uprobes.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ static __always_inline int go_crypto_tls_get_fd_from_tcp_conn(struct pt_regs* ct
175175
}
176176

177177
static __always_inline void go_crypto_tls_uprobe(struct pt_regs* ctx, struct bpf_map_def* go_context, enum ABI abi) {
178-
__u64 pid_tgid = bpf_get_current_pid_tgid();
178+
__u64 pid_tgid = tracer_get_current_pid_tgid();
179179
__u64 pid = pid_tgid >> 32;
180180
if (!should_target(pid)) {
181181
return;
@@ -251,7 +251,7 @@ static __always_inline void go_crypto_tls_uprobe(struct pt_regs* ctx, struct bpf
251251
}
252252

253253
static __always_inline void go_crypto_tls_ex_uprobe(struct pt_regs* ctx, struct bpf_map_def* go_context, struct bpf_map_def* go_user_kernel_context, __u32 flags, enum ABI abi) {
254-
__u64 pid_tgid = bpf_get_current_pid_tgid();
254+
__u64 pid_tgid = tracer_get_current_pid_tgid();
255255
__u64 pid = pid_tgid >> 32;
256256
if (!should_target(pid)) {
257257
return;

bpf/include/pids.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,34 @@ int _pid_in_map(struct bpf_map_def* pmap, __u32 pid) {
1919
return shouldTargetGlobally != NULL && *shouldTargetGlobally == 1;
2020
}
2121

22+
const volatile __u64 TRACER_NS_INO = 0;
23+
#define TRACER_NAMESPACES_MAX 4
24+
static __always_inline __u64 tracer_get_current_pid_tgid() {
25+
unsigned int inum;
26+
27+
__u64 base_pid_tgid = bpf_get_current_pid_tgid();
28+
29+
if (TRACER_NS_INO == 0) {
30+
return base_pid_tgid;
31+
}
32+
33+
struct task_struct* task = (struct task_struct*)bpf_get_current_task();
34+
35+
int level = BPF_CORE_READ(task, group_leader, nsproxy, pid_ns_for_children, level);
36+
37+
for (int i = 0; i < TRACER_NAMESPACES_MAX; i++) {
38+
if ((level - i) < 0) {
39+
break;
40+
}
41+
inum = BPF_CORE_READ(task, group_leader, thread_pid, numbers[level - i].ns, ns.inum);
42+
if (inum == TRACER_NS_INO) {
43+
__u64 ret = BPF_CORE_READ(task, group_leader, thread_pid, numbers[level - i].nr);
44+
ret = (ret << 32) | (base_pid_tgid & 0xFFFFFFFF);
45+
return ret;
46+
}
47+
}
48+
return base_pid_tgid;
49+
}
2250

2351
int should_target(__u32 pid) {
2452
return _pid_in_map(&target_pids_map, pid);

bpf/openssl_uprobes.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static __always_inline int get_count_bytes(struct pt_regs* ctx, struct ssl_info*
4242
static __always_inline void ssl_uprobe(struct pt_regs* ctx, void* ssl, void* buffer, int num, struct bpf_map_def* map_fd, size_t* count_ptr) {
4343
long err;
4444

45-
__u64 id = bpf_get_current_pid_tgid();
45+
__u64 id = tracer_get_current_pid_tgid();
4646

4747
if (!should_target(id >> 32)) {
4848
return;
@@ -61,7 +61,7 @@ static __always_inline void ssl_uprobe(struct pt_regs* ctx, void* ssl, void* buf
6161
}
6262

6363
static __always_inline void ssl_uretprobe(struct pt_regs* ctx, struct bpf_map_def* map_fd, __u32 flags) {
64-
__u64 id = bpf_get_current_pid_tgid();
64+
__u64 id = tracer_get_current_pid_tgid();
6565

6666
if (!should_target(id >> 32)) {
6767
return;

bpf/tcp_kprobes.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ static void __always_inline tcp_kprobes_forward_openssl(struct ssl_info* info_pt
7979
static __always_inline void tcp_kprobe(struct pt_regs* ctx, struct bpf_map_def* map_fd_openssl, struct bpf_map_def* map_fd_go_kernel, struct bpf_map_def* map_fd_go_user_kernel) {
8080
long err;
8181

82-
__u64 id = bpf_get_current_pid_tgid();
82+
__u64 id = tracer_get_current_pid_tgid();
8383

8484
if (!should_watch(id >> 32)) {
8585
return;
@@ -108,12 +108,12 @@ static __always_inline void tcp_kprobe(struct pt_regs* ctx, struct bpf_map_def*
108108

109109
SEC("kprobe/tcp_sendmsg")
110110
void BPF_KPROBE(tcp_sendmsg) {
111-
__u64 id = bpf_get_current_pid_tgid();
111+
__u64 id = tracer_get_current_pid_tgid();
112112
tcp_kprobe(ctx, &openssl_write_context, &go_kernel_write_context, &go_user_kernel_write_context);
113113
}
114114

115115
SEC("kprobe/tcp_recvmsg")
116116
void BPF_KPROBE(tcp_recvmsg) {
117-
__u64 id = bpf_get_current_pid_tgid();
117+
__u64 id = tracer_get_current_pid_tgid();
118118
tcp_kprobe(ctx, &openssl_read_context, &go_kernel_read_context, &go_user_kernel_read_context);
119119
}

tracer.go

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package main
33
import (
44
"fmt"
55

6+
"bytes"
7+
"os"
68
"strconv"
79
"syscall"
810

@@ -50,6 +52,45 @@ type pidOffset struct {
5052
offset uint64
5153
}
5254

55+
type BpfObjectsImpl struct {
56+
bpfObjs tracerObjects
57+
specs *ebpf.CollectionSpec
58+
}
59+
60+
func (objs *BpfObjectsImpl) loadBpfObjects(bpfConstants map[string]uint64) error {
61+
const permUser = 0700
62+
var err error
63+
opts := ebpf.CollectionOptions{
64+
Programs: ebpf.ProgramOptions{
65+
LogSize: ebpf.DefaultVerifierLogSize * 32,
66+
},
67+
}
68+
69+
reader := bytes.NewReader(_TracerBytes)
70+
objs.specs, err = ebpf.LoadCollectionSpecFromReader(reader)
71+
if err != nil {
72+
return err
73+
}
74+
75+
consts := make(map[string]interface{})
76+
for k, v := range bpfConstants {
77+
consts[k] = v
78+
}
79+
err = objs.specs.RewriteConstants(consts)
80+
if err != nil {
81+
return err
82+
}
83+
84+
err = objs.specs.LoadAndAssign(&objs.bpfObjs, &opts)
85+
if err != nil {
86+
var ve *ebpf.VerifierError
87+
if errors.As(err, &ve) {
88+
log.Error().Msg(fmt.Sprintf("Got verifier error: %+v", ve))
89+
}
90+
}
91+
return err
92+
}
93+
5394
func (t *Tracer) Init(
5495
chunksBufferSize int,
5596
logBufferSize int,
@@ -81,25 +122,34 @@ func (t *Tracer) Init(
81122

82123
log.Info().Msg(fmt.Sprintf("Detected Linux kernel version: %s cgroups version: %v", kernelVersion, cgroupsVersion))
83124

84-
t.bpfObjects = tracerObjects{}
85125
// TODO: cilium/ebpf does not support .kconfig Therefore; for now, we load object files according to kernel version.
86126
if kernel.CompareKernelVersion(*kernelVersion, kernel.VersionInfo{Kernel: 4, Major: 6, Minor: 0}) < 1 {
127+
t.bpfObjects = tracerObjects{}
87128
if err := loadTracer46Objects(&t.bpfObjects, nil); err != nil {
88129
return errors.Wrap(err, 0)
89130
}
90131
} else {
91-
opts := ebpf.CollectionOptions{
92-
Programs: ebpf.ProgramOptions{
93-
LogSize: ebpf.DefaultVerifierLogSize * 32,
94-
},
132+
var hostProcIno uint64
133+
fileInfo, err := os.Stat("/hostproc/1/ns/pid")
134+
if err != nil {
135+
// services like "apparmor" on EKS can reject access to system pid information
136+
log.Warn().Err(err).Msg("Get host netns failed")
137+
} else {
138+
hostProcIno = fileInfo.Sys().(*syscall.Stat_t).Ino
139+
log.Info().Uint64("ns", hostProcIno).Msg(fmt.Sprintf("Setting host ns"))
95140
}
96-
if err := loadTracerObjects(&t.bpfObjects, &opts); err != nil {
97-
var ve *ebpf.VerifierError
98-
if errors.As(err, &ve) {
99-
log.Error().Msg(fmt.Sprintf("Got verifier error: %+v", ve))
100-
}
101-
return errors.Wrap(err, 0)
141+
142+
objs := &BpfObjectsImpl{}
143+
144+
bpfConsts := map[string]uint64{
145+
"TRACER_NS_INO": hostProcIno,
146+
}
147+
err = objs.loadBpfObjects(bpfConsts)
148+
if err != nil {
149+
log.Error().Msg(fmt.Sprintf("load bpf objects failed: %v", err))
150+
return err
102151
}
152+
t.bpfObjects = objs.bpfObjs
103153
}
104154

105155
t.syscallHooks = syscallHooks{}

0 commit comments

Comments
 (0)