vivarium 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CONTEXT.md +535 -0
- data/README.md +16 -12
- data/examples/execve_demo.rb +4 -1
- data/examples/file_operation_demo.rb +4 -1
- data/examples/network_client_demo.rb +5 -1
- data/examples/privilege_event_demo.rb +5 -1
- data/examples/raise_demo.rb +46 -0
- data/examples/signal_kill_demo.rb +5 -1
- data/examples/ssl_write_demo.rb +37 -0
- data/examples/sudo_attempt_demo.rb +18 -0
- data/exe/vivarium +6 -0
- data/image.png +0 -0
- data/lib/vivarium/cli.rb +40 -0
- data/lib/vivarium/correlator.rb +139 -0
- data/lib/vivarium/display_filter.rb +158 -0
- data/lib/vivarium/http_decoder.rb +237 -0
- data/lib/vivarium/tree_renderer.rb +593 -0
- data/lib/vivarium/version.rb +1 -1
- data/lib/vivarium.rb +446 -175
- data/logo-simple.png +0 -0
- metadata +31 -5
- data/lib/vivarium/logger.rb +0 -80
data/lib/vivarium.rb
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
require "fiddle"
|
|
4
4
|
require "fileutils"
|
|
5
|
+
require "net/http"
|
|
5
6
|
require "optparse"
|
|
6
7
|
require "pathname"
|
|
7
8
|
require "rbbcc"
|
|
8
9
|
require "socket"
|
|
9
10
|
require_relative "vivarium/version"
|
|
10
|
-
require_relative "vivarium/
|
|
11
|
+
require_relative "vivarium/cli"
|
|
11
12
|
|
|
12
13
|
module Vivarium
|
|
13
14
|
class Error < StandardError; end
|
|
@@ -16,8 +17,7 @@ module Vivarium
|
|
|
16
17
|
CONFIG_ROOT_TARGETS_PIN = File.join(PIN_DIR, "config_root_targets")
|
|
17
18
|
CONFIG_SPAWNED_TARGETS_PIN = File.join(PIN_DIR, "config_spawned_targets")
|
|
18
19
|
CONFIG_TARGETS_PIN = CONFIG_ROOT_TARGETS_PIN
|
|
19
|
-
|
|
20
|
-
EVENT_WRITE_POS_PIN = File.join(PIN_DIR, "event_write_pos")
|
|
20
|
+
EVENTS_PIN = File.join(PIN_DIR, "events")
|
|
21
21
|
|
|
22
22
|
EVENT_NAME_SIZE = 16
|
|
23
23
|
EVENT_PAYLOAD_SIZE = 256
|
|
@@ -27,9 +27,55 @@ module Vivarium
|
|
|
27
27
|
EVENT_STRUCT_SIZE = 288
|
|
28
28
|
EVENT_TS_OFFSET = 0
|
|
29
29
|
EVENT_PID_OFFSET = 8
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
EVENT_TID_OFFSET = 12
|
|
31
|
+
EVENT_NAME_OFFSET = 16
|
|
32
|
+
EVENT_PAYLOAD_OFFSET = 32
|
|
33
|
+
EVENTS_RINGBUF_PAGES = 256
|
|
34
|
+
|
|
35
|
+
SSL_WRITE_PAYLOAD_DATA_LEN_OFFSET = 0
|
|
36
|
+
SSL_WRITE_PAYLOAD_CAP_LEN_OFFSET = 4
|
|
37
|
+
SSL_WRITE_PAYLOAD_DATA_OFFSET = 8
|
|
38
|
+
SSL_WRITE_PAYLOAD_DATA_MAX = EVENT_PAYLOAD_SIZE - SSL_WRITE_PAYLOAD_DATA_OFFSET
|
|
39
|
+
|
|
40
|
+
LIBSSL_SEARCH_PATHS = [
|
|
41
|
+
"/lib/x86_64-linux-gnu/libssl.so.3",
|
|
42
|
+
"/lib/x86_64-linux-gnu/libssl.so.1.1",
|
|
43
|
+
"/lib/aarch64-linux-gnu/libssl.so.3",
|
|
44
|
+
"/lib/aarch64-linux-gnu/libssl.so.1.1",
|
|
45
|
+
"/usr/lib/x86_64-linux-gnu/libssl.so.3",
|
|
46
|
+
"/usr/lib/x86_64-linux-gnu/libssl.so.1.1",
|
|
47
|
+
"/usr/lib/aarch64-linux-gnu/libssl.so.3",
|
|
48
|
+
"/usr/lib/aarch64-linux-gnu/libssl.so.1.1",
|
|
49
|
+
"/usr/lib64/libssl.so.3",
|
|
50
|
+
"/usr/lib64/libssl.so.1.1",
|
|
51
|
+
"/usr/lib/libssl.so.3",
|
|
52
|
+
"/usr/lib/libssl.so.1.1"
|
|
53
|
+
].freeze
|
|
54
|
+
|
|
55
|
+
SPAN_ALLOWCLASSES = [
|
|
56
|
+
Socket,
|
|
57
|
+
BasicSocket,
|
|
58
|
+
IPSocket,
|
|
59
|
+
TCPSocket,
|
|
60
|
+
UDPSocket,
|
|
61
|
+
UNIXSocket,
|
|
62
|
+
File,
|
|
63
|
+
Dir,
|
|
64
|
+
Signal,
|
|
65
|
+
Process,
|
|
66
|
+
Process::UID,
|
|
67
|
+
Process::GID,
|
|
68
|
+
Net::HTTP,
|
|
69
|
+
]
|
|
70
|
+
SPAN_ALLOWLIST = [
|
|
71
|
+
"Kernel#system",
|
|
72
|
+
"Kernel#require",
|
|
73
|
+
"Kernel#require_relative",
|
|
74
|
+
"Kernel#load",
|
|
75
|
+
"Kernel#eval",
|
|
76
|
+
"Object#instance_eval",
|
|
77
|
+
"Object#instance_exec",
|
|
78
|
+
].freeze
|
|
33
79
|
EVENT_SEVERITY_HIGH = %w[
|
|
34
80
|
capable_check bprm_creds setid_change task_kill
|
|
35
81
|
ptrace_check sb_mount kernel_read_file
|
|
@@ -83,49 +129,12 @@ module Vivarium
|
|
|
83
129
|
end
|
|
84
130
|
end
|
|
85
131
|
|
|
86
|
-
Event = Struct.new(:ktime_ns, :pid, :event_name, :payload, keyword_init: true) do
|
|
87
|
-
def empty?
|
|
88
|
-
ktime_ns.to_i.zero? && pid.to_i.zero? && event_name.to_s.empty? && payload.to_s.empty?
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def severity
|
|
92
|
-
Vivarium.event_severity(event_name)
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def self.from_binary(raw)
|
|
96
|
-
bytes = raw.to_s.b
|
|
97
|
-
bytes = bytes.ljust(EVENT_STRUCT_SIZE, "\x00")
|
|
98
|
-
|
|
99
|
-
ktime_ns = bytes[EVENT_TS_OFFSET, EVENT_TS_SIZE].unpack1("Q<")
|
|
100
|
-
pid = bytes[EVENT_PID_OFFSET, 4].unpack1("L<")
|
|
101
|
-
event_name = c_string(bytes[EVENT_NAME_OFFSET, EVENT_NAME_SIZE])
|
|
102
|
-
raw_payload = bytes[EVENT_PAYLOAD_OFFSET, EVENT_PAYLOAD_SIZE]
|
|
103
|
-
raw_payload_events = %w[
|
|
104
|
-
dns_req sock_connect odd_socket proc_exec
|
|
105
|
-
file_symlink file_hardlink file_rename file_chmod file_getdents
|
|
106
|
-
ptrace_check sb_mount kernel_read_file task_kill
|
|
107
|
-
setid_change capable_check bprm_creds
|
|
108
|
-
]
|
|
109
|
-
payload = if raw_payload_events.include?(event_name)
|
|
110
|
-
raw_payload
|
|
111
|
-
else
|
|
112
|
-
c_string(raw_payload)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
new(ktime_ns: ktime_ns, pid: pid, event_name: event_name, payload: payload)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def self.c_string(bytes)
|
|
119
|
-
str = bytes.to_s.b
|
|
120
|
-
nul = str.index("\x00")
|
|
121
|
-
return str if nul.nil?
|
|
122
|
-
|
|
123
|
-
str[0, nul]
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
132
|
def self.c_string(bytes)
|
|
128
|
-
|
|
133
|
+
str = bytes.to_s.b
|
|
134
|
+
nul = str.index("\x00")
|
|
135
|
+
return str if nul.nil?
|
|
136
|
+
|
|
137
|
+
str[0, nul]
|
|
129
138
|
end
|
|
130
139
|
|
|
131
140
|
def self.event_severity(event_name)
|
|
@@ -330,6 +339,68 @@ module Vivarium
|
|
|
330
339
|
"has_file=#{has_file} file=#{path.inspect}"
|
|
331
340
|
end
|
|
332
341
|
|
|
342
|
+
def self.decode_proc_fork_payload(raw_payload)
|
|
343
|
+
bytes = raw_payload.to_s.b
|
|
344
|
+
return "" if bytes.bytesize < 8
|
|
345
|
+
|
|
346
|
+
child_pid = bytes[0, 4].unpack1("L<")
|
|
347
|
+
child_tid = bytes[4, 4].unpack1("L<")
|
|
348
|
+
"child_pid=#{child_pid} child_tid=#{child_tid}"
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def self.decode_span_payload(raw_payload)
|
|
352
|
+
bytes = raw_payload.to_s.b
|
|
353
|
+
return "" if bytes.bytesize < 8
|
|
354
|
+
|
|
355
|
+
method_id = bytes[0, 8].unpack1("q<")
|
|
356
|
+
result = format("method_id=0x%016X", method_id & 0xFFFF_FFFF_FFFF_FFFF)
|
|
357
|
+
|
|
358
|
+
if bytes.bytesize >= 24
|
|
359
|
+
file_id = bytes[8, 8].unpack1("q<")
|
|
360
|
+
lineno = bytes[16, 8].unpack1("q<")
|
|
361
|
+
result += format(" file_id=0x%016X", file_id & 0xFFFF_FFFF_FFFF_FFFF) if file_id != -1
|
|
362
|
+
result += " lineno=#{lineno}" if lineno > 0
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
result
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
def self.decode_ssl_write_payload(raw_payload)
|
|
369
|
+
bytes = raw_payload.to_s.b
|
|
370
|
+
return { data_len: 0, cap_len: 0, data: "".b } if bytes.bytesize < SSL_WRITE_PAYLOAD_DATA_OFFSET
|
|
371
|
+
|
|
372
|
+
data_len = bytes[SSL_WRITE_PAYLOAD_DATA_LEN_OFFSET, 4].unpack1("L<")
|
|
373
|
+
cap_len = bytes[SSL_WRITE_PAYLOAD_CAP_LEN_OFFSET, 4].unpack1("L<")
|
|
374
|
+
cap_len = SSL_WRITE_PAYLOAD_DATA_MAX if cap_len > SSL_WRITE_PAYLOAD_DATA_MAX
|
|
375
|
+
data = bytes[SSL_WRITE_PAYLOAD_DATA_OFFSET, cap_len] || "".b
|
|
376
|
+
{ data_len: data_len, cap_len: cap_len, data: data }
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def self.decode_span_raise_payload(raw_payload)
|
|
380
|
+
bytes = raw_payload.to_s.b
|
|
381
|
+
return "" if bytes.bytesize < 8
|
|
382
|
+
|
|
383
|
+
error_id = bytes[0, 8].unpack1("q<")
|
|
384
|
+
result = format("error_id=0x%016X", error_id & 0xFFFF_FFFF_FFFF_FFFF)
|
|
385
|
+
|
|
386
|
+
if bytes.bytesize >= 16
|
|
387
|
+
message_id = bytes[8, 8].unpack1("q<")
|
|
388
|
+
result += format(" message_id=0x%016X", message_id & 0xFFFF_FFFF_FFFF_FFFF)
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
if bytes.bytesize >= 24
|
|
392
|
+
file_id = bytes[16, 8].unpack1("q<")
|
|
393
|
+
result += format(" file_id=0x%016X", file_id & 0xFFFF_FFFF_FFFF_FFFF) if file_id != -1
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
if bytes.bytesize >= 32
|
|
397
|
+
lineno = bytes[24, 8].unpack1("q<")
|
|
398
|
+
result += " lineno=#{lineno}" if lineno > 0
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
result
|
|
402
|
+
end
|
|
403
|
+
|
|
333
404
|
def self.render_event_payload(event)
|
|
334
405
|
case event.event_name
|
|
335
406
|
when "dns_req"
|
|
@@ -365,6 +436,15 @@ module Vivarium
|
|
|
365
436
|
when "bprm_creds"
|
|
366
437
|
decoded = decode_bprm_creds_payload(event.payload)
|
|
367
438
|
decoded.empty? ? event.payload.inspect : decoded
|
|
439
|
+
when "proc_fork"
|
|
440
|
+
decoded = decode_proc_fork_payload(event.payload)
|
|
441
|
+
decoded.empty? ? event.payload.inspect : decoded
|
|
442
|
+
when "span_start", "span_stop"
|
|
443
|
+
decoded = decode_span_payload(event.payload)
|
|
444
|
+
decoded.empty? ? event.payload.inspect : decoded
|
|
445
|
+
when "span_raise"
|
|
446
|
+
decoded = decode_span_raise_payload(event.payload)
|
|
447
|
+
decoded.empty? ? event.payload.inspect : decoded
|
|
368
448
|
when "file_symlink"
|
|
369
449
|
decoded = decode_file_symlink_payload(event.payload)
|
|
370
450
|
decoded.empty? ? event.payload.inspect : decoded
|
|
@@ -380,11 +460,21 @@ module Vivarium
|
|
|
380
460
|
when "file_getdents"
|
|
381
461
|
decoded = decode_file_getdents_payload(event.payload)
|
|
382
462
|
decoded.empty? ? event.payload.inspect : decoded
|
|
463
|
+
when "ssl_write"
|
|
464
|
+
decoded = decode_ssl_write_payload(event.payload)
|
|
465
|
+
"data_len=#{decoded[:data_len]} cap_len=#{decoded[:cap_len]}"
|
|
383
466
|
else
|
|
384
|
-
event.payload.inspect
|
|
467
|
+
strip_to_first_null(event.payload).inspect
|
|
385
468
|
end
|
|
386
469
|
end
|
|
387
470
|
|
|
471
|
+
def self.strip_to_first_null(bytes)
|
|
472
|
+
nul = bytes.index("\x00")
|
|
473
|
+
return bytes if nul.nil?
|
|
474
|
+
|
|
475
|
+
bytes[0, nul]
|
|
476
|
+
end
|
|
477
|
+
|
|
388
478
|
class MapStore
|
|
389
479
|
def initialize(pin_dir: Vivarium.bpf_pin_dir)
|
|
390
480
|
@pin_dir = pin_dir
|
|
@@ -402,20 +492,6 @@ module Vivarium
|
|
|
402
492
|
keysize: 4,
|
|
403
493
|
leafsize: 1
|
|
404
494
|
)
|
|
405
|
-
@event_invoked = RbBCC::ArrayTable.from_pin(
|
|
406
|
-
File.join(@pin_dir, "event_invoked"),
|
|
407
|
-
"unsigned int",
|
|
408
|
-
"char[#{EVENT_STRUCT_SIZE}]",
|
|
409
|
-
keysize: 4,
|
|
410
|
-
leafsize: EVENT_STRUCT_SIZE
|
|
411
|
-
)
|
|
412
|
-
@event_write_pos = RbBCC::ArrayTable.from_pin(
|
|
413
|
-
File.join(@pin_dir, "event_write_pos"),
|
|
414
|
-
"unsigned int",
|
|
415
|
-
"unsigned int",
|
|
416
|
-
keysize: 4,
|
|
417
|
-
leafsize: 4
|
|
418
|
-
)
|
|
419
495
|
rescue StandardError => e
|
|
420
496
|
raise Error, "failed to open pinned maps under #{@pin_dir}: #{e.class}: #{e.message}"
|
|
421
497
|
end
|
|
@@ -430,31 +506,6 @@ module Vivarium
|
|
|
430
506
|
rescue KeyError
|
|
431
507
|
nil
|
|
432
508
|
end
|
|
433
|
-
|
|
434
|
-
def drain_events
|
|
435
|
-
events = []
|
|
436
|
-
EVENT_CAPACITY.times do |idx|
|
|
437
|
-
ptr = @event_invoked[idx]
|
|
438
|
-
next unless ptr
|
|
439
|
-
|
|
440
|
-
event = Event.from_binary(ptr[0, EVENT_STRUCT_SIZE])
|
|
441
|
-
next if event.empty?
|
|
442
|
-
|
|
443
|
-
events << event
|
|
444
|
-
@event_invoked[idx] = zeroed_event_ptr
|
|
445
|
-
end
|
|
446
|
-
|
|
447
|
-
@event_write_pos[0] = 0
|
|
448
|
-
events
|
|
449
|
-
end
|
|
450
|
-
|
|
451
|
-
private
|
|
452
|
-
|
|
453
|
-
def zeroed_event_ptr
|
|
454
|
-
ptr = Fiddle::Pointer.malloc(EVENT_STRUCT_SIZE)
|
|
455
|
-
ptr[0, EVENT_STRUCT_SIZE] = "\x00" * EVENT_STRUCT_SIZE
|
|
456
|
-
ptr
|
|
457
|
-
end
|
|
458
509
|
end
|
|
459
510
|
|
|
460
511
|
class Daemon
|
|
@@ -565,6 +616,7 @@ module Vivarium
|
|
|
565
616
|
struct event_t {
|
|
566
617
|
u64 ktime_ns;
|
|
567
618
|
u32 pid;
|
|
619
|
+
u32 tid;
|
|
568
620
|
char event_name[16];
|
|
569
621
|
char payload[#{EVENT_PAYLOAD_SIZE}];
|
|
570
622
|
};
|
|
@@ -572,8 +624,7 @@ module Vivarium
|
|
|
572
624
|
BPF_HASH(config_root_targets, u32, u8, 1024);
|
|
573
625
|
BPF_HASH(config_spawned_targets, u32, u8, 8192);
|
|
574
626
|
BPF_HASH(dns_connected_tids, u32, u8, 8192);
|
|
575
|
-
|
|
576
|
-
BPF_ARRAY(event_write_pos, u32, 1);
|
|
627
|
+
BPF_RINGBUF_OUTPUT(events, #{EVENTS_RINGBUF_PAGES});
|
|
577
628
|
|
|
578
629
|
static __always_inline int target_enabled(u32 pid, u32 tid)
|
|
579
630
|
{
|
|
@@ -613,19 +664,18 @@ module Vivarium
|
|
|
613
664
|
}
|
|
614
665
|
}
|
|
615
666
|
|
|
616
|
-
static __always_inline void submit_event(struct event_t *
|
|
667
|
+
static __always_inline void submit_event(struct event_t *src)
|
|
617
668
|
{
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
if (!write_pos) {
|
|
669
|
+
struct event_t *ev = events.ringbuf_reserve(sizeof(struct event_t));
|
|
670
|
+
if (!ev) {
|
|
621
671
|
return;
|
|
622
672
|
}
|
|
623
673
|
|
|
674
|
+
__builtin_memcpy(ev, src, sizeof(*ev));
|
|
624
675
|
ev->ktime_ns = bpf_ktime_get_ns();
|
|
676
|
+
ev->tid = (u32)bpf_get_current_pid_tgid();
|
|
625
677
|
|
|
626
|
-
|
|
627
|
-
__sync_fetch_and_add(write_pos, 1);
|
|
628
|
-
event_invoked.update(&idx, ev);
|
|
678
|
+
events.ringbuf_submit(ev, 0);
|
|
629
679
|
}
|
|
630
680
|
|
|
631
681
|
static __always_inline int is_dns_destination(void *addr)
|
|
@@ -696,16 +746,28 @@ module Vivarium
|
|
|
696
746
|
u32 parent = args->parent_pid;
|
|
697
747
|
u32 child = args->child_pid;
|
|
698
748
|
u8 one = 1;
|
|
749
|
+
int is_target = 0;
|
|
699
750
|
|
|
700
751
|
u8 *enabled_root = config_root_targets.lookup(&parent);
|
|
701
752
|
if (enabled_root && *enabled_root == 1) {
|
|
753
|
+
is_target = 1;
|
|
702
754
|
config_spawned_targets.update(&child, &one);
|
|
703
|
-
|
|
755
|
+
} else {
|
|
756
|
+
u8 *enabled_spawned = config_spawned_targets.lookup(&parent);
|
|
757
|
+
if (enabled_spawned && *enabled_spawned == 1) {
|
|
758
|
+
is_target = 1;
|
|
759
|
+
config_spawned_targets.update(&child, &one);
|
|
760
|
+
}
|
|
704
761
|
}
|
|
705
762
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
763
|
+
if (is_target) {
|
|
764
|
+
u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
765
|
+
struct event_t ev = {};
|
|
766
|
+
ev.pid = pid_tgid >> 32;
|
|
767
|
+
__builtin_memcpy(ev.event_name, "proc_fork", 10);
|
|
768
|
+
__builtin_memcpy(&ev.payload[0], &child, sizeof(child));
|
|
769
|
+
__builtin_memcpy(&ev.payload[4], &child, sizeof(child));
|
|
770
|
+
submit_event(&ev);
|
|
709
771
|
}
|
|
710
772
|
|
|
711
773
|
return 0;
|
|
@@ -724,7 +786,6 @@ module Vivarium
|
|
|
724
786
|
u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
725
787
|
u32 pid = pid_tgid >> 32;
|
|
726
788
|
u32 tid = (u32)pid_tgid;
|
|
727
|
-
bpf_trace_printk("vivarium: invoked pid=%d\\n", pid);
|
|
728
789
|
if (!target_enabled(pid, tid)) {
|
|
729
790
|
return 0;
|
|
730
791
|
}
|
|
@@ -738,11 +799,9 @@ module Vivarium
|
|
|
738
799
|
if (path_ret < 0) {
|
|
739
800
|
if (ev.payload[0] == 0) {
|
|
740
801
|
__builtin_memcpy(ev.payload, "<path_error>", 13);
|
|
741
|
-
bpf_trace_printk("vivarium: failed to obtain full path. pid=%d path=%s\\n", pid, ev.payload);
|
|
742
802
|
}
|
|
743
803
|
}
|
|
744
804
|
|
|
745
|
-
bpf_trace_printk("vivarium: pid=%d path=%s\\n", pid, ev.payload);
|
|
746
805
|
submit_event(&ev);
|
|
747
806
|
|
|
748
807
|
return 0;
|
|
@@ -1262,10 +1321,132 @@ module Vivarium
|
|
|
1262
1321
|
submit_event(&ev);
|
|
1263
1322
|
return 0;
|
|
1264
1323
|
}
|
|
1324
|
+
|
|
1325
|
+
int on_span_start(struct pt_regs *ctx)
|
|
1326
|
+
{
|
|
1327
|
+
u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
1328
|
+
u32 pid = pid_tgid >> 32;
|
|
1329
|
+
u32 tid = (u32)pid_tgid;
|
|
1330
|
+
|
|
1331
|
+
if (!target_enabled(pid, tid)) {
|
|
1332
|
+
return 0;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
u64 method_id = 0;
|
|
1336
|
+
u64 file_id = 0;
|
|
1337
|
+
u64 lineno = 0;
|
|
1338
|
+
bpf_usdt_readarg(1, ctx, &method_id);
|
|
1339
|
+
bpf_usdt_readarg(2, ctx, &file_id);
|
|
1340
|
+
bpf_usdt_readarg(3, ctx, &lineno);
|
|
1341
|
+
|
|
1342
|
+
struct event_t ev = {};
|
|
1343
|
+
ev.pid = pid;
|
|
1344
|
+
__builtin_memcpy(ev.event_name, "span_start", 11);
|
|
1345
|
+
__builtin_memcpy(&ev.payload[0], &method_id, sizeof(method_id));
|
|
1346
|
+
__builtin_memcpy(&ev.payload[8], &file_id, sizeof(file_id));
|
|
1347
|
+
__builtin_memcpy(&ev.payload[16], &lineno, sizeof(lineno));
|
|
1348
|
+
submit_event(&ev);
|
|
1349
|
+
return 0;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
int on_span_stop(struct pt_regs *ctx)
|
|
1353
|
+
{
|
|
1354
|
+
u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
1355
|
+
u32 pid = pid_tgid >> 32;
|
|
1356
|
+
u32 tid = (u32)pid_tgid;
|
|
1357
|
+
|
|
1358
|
+
if (!target_enabled(pid, tid)) {
|
|
1359
|
+
return 0;
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
u64 method_id = 0;
|
|
1363
|
+
u64 file_id = 0;
|
|
1364
|
+
u64 lineno = 0;
|
|
1365
|
+
bpf_usdt_readarg(1, ctx, &method_id);
|
|
1366
|
+
bpf_usdt_readarg(2, ctx, &file_id);
|
|
1367
|
+
bpf_usdt_readarg(3, ctx, &lineno);
|
|
1368
|
+
|
|
1369
|
+
struct event_t ev = {};
|
|
1370
|
+
ev.pid = pid;
|
|
1371
|
+
__builtin_memcpy(ev.event_name, "span_stop", 10);
|
|
1372
|
+
__builtin_memcpy(&ev.payload[0], &method_id, sizeof(method_id));
|
|
1373
|
+
__builtin_memcpy(&ev.payload[8], &file_id, sizeof(file_id));
|
|
1374
|
+
__builtin_memcpy(&ev.payload[16], &lineno, sizeof(lineno));
|
|
1375
|
+
submit_event(&ev);
|
|
1376
|
+
return 0;
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
int on_ssl_write(struct pt_regs *ctx)
|
|
1380
|
+
{
|
|
1381
|
+
u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
1382
|
+
u32 pid = pid_tgid >> 32;
|
|
1383
|
+
u32 tid = (u32)pid_tgid;
|
|
1384
|
+
|
|
1385
|
+
if (!target_enabled(pid, tid)) {
|
|
1386
|
+
return 0;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
const char *buf = (const char *)PT_REGS_PARM2(ctx);
|
|
1390
|
+
int num = (int)PT_REGS_PARM3(ctx);
|
|
1391
|
+
if (!buf || num <= 0) {
|
|
1392
|
+
return 0;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
struct event_t ev = {};
|
|
1396
|
+
ev.pid = pid;
|
|
1397
|
+
__builtin_memcpy(ev.event_name, "ssl_write", 10);
|
|
1398
|
+
|
|
1399
|
+
u32 data_len = (u32)num;
|
|
1400
|
+
u32 cap = data_len;
|
|
1401
|
+
if (cap > #{SSL_WRITE_PAYLOAD_DATA_MAX}) {
|
|
1402
|
+
cap = #{SSL_WRITE_PAYLOAD_DATA_MAX};
|
|
1403
|
+
}
|
|
1404
|
+
__builtin_memcpy(&ev.payload[#{SSL_WRITE_PAYLOAD_DATA_LEN_OFFSET}], &data_len, sizeof(data_len));
|
|
1405
|
+
__builtin_memcpy(&ev.payload[#{SSL_WRITE_PAYLOAD_CAP_LEN_OFFSET}], &cap, sizeof(cap));
|
|
1406
|
+
if (bpf_probe_read_user(&ev.payload[#{SSL_WRITE_PAYLOAD_DATA_OFFSET}], cap, buf) < 0) {
|
|
1407
|
+
u32 zero = 0;
|
|
1408
|
+
__builtin_memcpy(&ev.payload[#{SSL_WRITE_PAYLOAD_CAP_LEN_OFFSET}], &zero, sizeof(zero));
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
submit_event(&ev);
|
|
1412
|
+
return 0;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
int on_span_raise(struct pt_regs *ctx)
|
|
1416
|
+
{
|
|
1417
|
+
u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
1418
|
+
u32 pid = pid_tgid >> 32;
|
|
1419
|
+
u32 tid = (u32)pid_tgid;
|
|
1420
|
+
|
|
1421
|
+
if (!target_enabled(pid, tid)) {
|
|
1422
|
+
return 0;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
u64 error_id = 0;
|
|
1426
|
+
u64 message_id = 0;
|
|
1427
|
+
u64 file_id = 0;
|
|
1428
|
+
u64 lineno = 0;
|
|
1429
|
+
bpf_usdt_readarg(1, ctx, &error_id);
|
|
1430
|
+
bpf_usdt_readarg(2, ctx, &message_id);
|
|
1431
|
+
bpf_usdt_readarg(3, ctx, &file_id);
|
|
1432
|
+
bpf_usdt_readarg(4, ctx, &lineno);
|
|
1433
|
+
|
|
1434
|
+
struct event_t ev = {};
|
|
1435
|
+
ev.pid = pid;
|
|
1436
|
+
__builtin_memcpy(ev.event_name, "span_raise", 11);
|
|
1437
|
+
__builtin_memcpy(&ev.payload[0], &error_id, sizeof(error_id));
|
|
1438
|
+
__builtin_memcpy(&ev.payload[8], &message_id, sizeof(message_id));
|
|
1439
|
+
__builtin_memcpy(&ev.payload[16], &file_id, sizeof(file_id));
|
|
1440
|
+
__builtin_memcpy(&ev.payload[24], &lineno, sizeof(lineno));
|
|
1441
|
+
submit_event(&ev);
|
|
1442
|
+
return 0;
|
|
1443
|
+
}
|
|
1265
1444
|
CLANG
|
|
1266
1445
|
|
|
1267
|
-
def initialize(pin_dir: Vivarium.bpf_pin_dir)
|
|
1446
|
+
def initialize(pin_dir: Vivarium.bpf_pin_dir, ssl_trace: true, libssl_path: nil)
|
|
1268
1447
|
@pin_dir = pin_dir
|
|
1448
|
+
@ssl_trace = ssl_trace
|
|
1449
|
+
@libssl_path = libssl_path
|
|
1269
1450
|
end
|
|
1270
1451
|
|
|
1271
1452
|
def run
|
|
@@ -1278,42 +1459,73 @@ module Vivarium
|
|
|
1278
1459
|
.gsub("__VIVARIUM_F_PATH_OFFSET__", f_path_offset.to_s)
|
|
1279
1460
|
.gsub("__VIVARIUM_DENTRY_D_NAME_OFFSET__", d_name_offset.to_s)
|
|
1280
1461
|
|
|
1281
|
-
|
|
1282
|
-
|
|
1462
|
+
usdt_so_path = ENV.fetch("VIVARIUM_USDT_SO_PATH") { Vivarium.locate_vivarium_usdt_so }
|
|
1463
|
+
usdt = RbBCC::USDT.new(path: usdt_so_path)
|
|
1464
|
+
usdt.enable_probe(probe: "start_probe", fn_name: "on_span_start")
|
|
1465
|
+
usdt.enable_probe(probe: "stop_probe", fn_name: "on_span_stop")
|
|
1466
|
+
usdt.enable_probe(probe: "raise_probe", fn_name: "on_span_raise")
|
|
1467
|
+
|
|
1468
|
+
bpf = RbBCC::BCC.new(text: program, usdt_contexts: [usdt])
|
|
1469
|
+
|
|
1470
|
+
attach_ssl_write_uprobe(bpf) if @ssl_trace
|
|
1283
1471
|
|
|
1284
1472
|
config_root_targets = bpf["config_root_targets"]
|
|
1285
1473
|
config_spawned_targets = bpf["config_spawned_targets"]
|
|
1286
|
-
|
|
1287
|
-
event_write_pos = bpf["event_write_pos"]
|
|
1474
|
+
events_ringbuf = bpf["events"]
|
|
1288
1475
|
|
|
1289
|
-
clear_event_slots(event_invoked)
|
|
1290
|
-
event_write_pos[0] = 0
|
|
1291
1476
|
config_spawned_targets.clear
|
|
1292
1477
|
|
|
1293
1478
|
pin_map(config_root_targets, File.join(@pin_dir, "config_root_targets"))
|
|
1294
1479
|
pin_map(config_spawned_targets, File.join(@pin_dir, "config_spawned_targets"))
|
|
1295
|
-
pin_map(
|
|
1296
|
-
pin_map(event_write_pos, File.join(@pin_dir, "event_write_pos"))
|
|
1480
|
+
pin_map(events_ringbuf, File.join(@pin_dir, "events"))
|
|
1297
1481
|
|
|
1298
1482
|
puts "[vivariumd] started"
|
|
1299
1483
|
puts "[vivariumd] pinned maps in #{@pin_dir}"
|
|
1300
1484
|
puts "[vivariumd] watching LSM file_open (f_path offset=#{f_path_offset})"
|
|
1301
|
-
puts "[vivariumd]
|
|
1485
|
+
puts "[vivariumd] USDT attached via #{usdt_so_path}"
|
|
1302
1486
|
|
|
1303
1487
|
loop do
|
|
1304
1488
|
sleep 1
|
|
1305
1489
|
end
|
|
1306
1490
|
rescue Interrupt
|
|
1307
1491
|
puts "\n[vivariumd] stopping"
|
|
1308
|
-
ensure
|
|
1309
|
-
if kprint_thread
|
|
1310
|
-
kprint_thread.kill
|
|
1311
|
-
kprint_thread.join(0.2)
|
|
1312
|
-
end
|
|
1313
1492
|
end
|
|
1314
1493
|
|
|
1315
1494
|
private
|
|
1316
1495
|
|
|
1496
|
+
def attach_ssl_write_uprobe(bpf)
|
|
1497
|
+
path = resolve_libssl_path
|
|
1498
|
+
unless path
|
|
1499
|
+
warn "[vivariumd] libssl not found; SSL_write uprobe disabled " \
|
|
1500
|
+
"(set --libssl PATH or VIVARIUM_LIBSSL_PATH to override)"
|
|
1501
|
+
return
|
|
1502
|
+
end
|
|
1503
|
+
|
|
1504
|
+
bpf.attach_uprobe(name: path, sym: "SSL_write", fn_name: "on_ssl_write")
|
|
1505
|
+
puts "[vivariumd] SSL_write uprobe attached via #{path}"
|
|
1506
|
+
rescue StandardError => e
|
|
1507
|
+
warn "[vivariumd] SSL_write uprobe attach failed: #{e.class}: #{e.message}"
|
|
1508
|
+
end
|
|
1509
|
+
|
|
1510
|
+
def resolve_libssl_path
|
|
1511
|
+
if @libssl_path
|
|
1512
|
+
return @libssl_path if File.exist?(@libssl_path)
|
|
1513
|
+
|
|
1514
|
+
warn "[vivariumd] --libssl path does not exist: #{@libssl_path}"
|
|
1515
|
+
return nil
|
|
1516
|
+
end
|
|
1517
|
+
|
|
1518
|
+
env_path = ENV["VIVARIUM_LIBSSL_PATH"]
|
|
1519
|
+
if env_path && !env_path.empty?
|
|
1520
|
+
return env_path if File.exist?(env_path)
|
|
1521
|
+
|
|
1522
|
+
warn "[vivariumd] VIVARIUM_LIBSSL_PATH does not exist: #{env_path}"
|
|
1523
|
+
return nil
|
|
1524
|
+
end
|
|
1525
|
+
|
|
1526
|
+
LIBSSL_SEARCH_PATHS.find { |p| File.exist?(p) }
|
|
1527
|
+
end
|
|
1528
|
+
|
|
1317
1529
|
def ensure_root!
|
|
1318
1530
|
return if Process.uid.zero?
|
|
1319
1531
|
|
|
@@ -1325,34 +1537,6 @@ module Vivarium
|
|
|
1325
1537
|
RbBCC::BCC.pin!(table.map_fd, path)
|
|
1326
1538
|
end
|
|
1327
1539
|
|
|
1328
|
-
def clear_event_slots(table)
|
|
1329
|
-
ptr = Fiddle::Pointer.malloc(EVENT_STRUCT_SIZE)
|
|
1330
|
-
ptr[0, EVENT_STRUCT_SIZE] = "\x00" * EVENT_STRUCT_SIZE
|
|
1331
|
-
EVENT_CAPACITY.times do |idx|
|
|
1332
|
-
table[idx] = ptr
|
|
1333
|
-
end
|
|
1334
|
-
end
|
|
1335
|
-
|
|
1336
|
-
def start_kprint_logger(bpf)
|
|
1337
|
-
Thread.new do
|
|
1338
|
-
begin
|
|
1339
|
-
bpf.trace_fields do |_task, pid, _cpu, _flags, ts, msg|
|
|
1340
|
-
line = msg.to_s.strip
|
|
1341
|
-
next unless line.start_with?("vivarium:")
|
|
1342
|
-
|
|
1343
|
-
puts "[vivariumd:kprint #{ts} pid=#{pid}] #{line}"
|
|
1344
|
-
end
|
|
1345
|
-
rescue IOError, Errno::EINTR
|
|
1346
|
-
nil
|
|
1347
|
-
rescue StandardError => e
|
|
1348
|
-
warn "[vivariumd] kprint stream stopped: #{e.class}: #{e.message}"
|
|
1349
|
-
end
|
|
1350
|
-
end
|
|
1351
|
-
rescue StandardError => e
|
|
1352
|
-
warn "[vivariumd] failed to start kprint logger: #{e.class}: #{e.message}"
|
|
1353
|
-
nil
|
|
1354
|
-
end
|
|
1355
|
-
|
|
1356
1540
|
def detect_f_path_offset
|
|
1357
1541
|
env_offset = ENV["VIVARIUM_FILE_F_PATH_OFFSET"]
|
|
1358
1542
|
return Integer(env_offset, 10) if env_offset
|
|
@@ -1465,84 +1649,171 @@ module Vivarium
|
|
|
1465
1649
|
end
|
|
1466
1650
|
|
|
1467
1651
|
class ObservationSession
|
|
1468
|
-
def initialize(store:, pid:, tracer:)
|
|
1652
|
+
def initialize(store:, pid:, tracer:, correlator:)
|
|
1469
1653
|
@store = store
|
|
1470
1654
|
@pid = pid
|
|
1471
1655
|
@tracer = tracer
|
|
1656
|
+
@correlator = correlator
|
|
1472
1657
|
@stopped = false
|
|
1473
1658
|
end
|
|
1474
1659
|
|
|
1475
1660
|
def stop
|
|
1476
1661
|
return if @stopped
|
|
1477
1662
|
|
|
1663
|
+
@stopped = true
|
|
1478
1664
|
@tracer.disable
|
|
1479
1665
|
@store.unregister_pid(@pid)
|
|
1480
|
-
@
|
|
1666
|
+
@correlator.stop
|
|
1481
1667
|
end
|
|
1482
1668
|
end
|
|
1483
1669
|
|
|
1484
|
-
def self.observe(pin_dir: bpf_pin_dir,
|
|
1485
|
-
return scoped_observe(pin_dir: pin_dir,
|
|
1670
|
+
def self.observe(pin_dir: bpf_pin_dir, dest: $stdout, filter: nil, &block)
|
|
1671
|
+
return scoped_observe(pin_dir: pin_dir, dest: dest, filter: filter, &block) if block_given?
|
|
1486
1672
|
|
|
1487
|
-
top_observe(pin_dir: pin_dir,
|
|
1673
|
+
top_observe(pin_dir: pin_dir, dest: dest, filter: filter)
|
|
1488
1674
|
end
|
|
1489
1675
|
|
|
1490
|
-
def self.top_observe(pin_dir: bpf_pin_dir,
|
|
1491
|
-
|
|
1676
|
+
def self.top_observe(pin_dir: bpf_pin_dir, dest: $stdout, filter: nil)
|
|
1677
|
+
require "vivarium_usdt"
|
|
1678
|
+
|
|
1492
1679
|
store = MapStore.new(pin_dir: pin_dir)
|
|
1493
1680
|
pid = Process.pid
|
|
1494
1681
|
store.register_pid(pid)
|
|
1495
|
-
logger.info("top-level observing with pid=#{pid}")
|
|
1496
1682
|
|
|
1497
|
-
|
|
1683
|
+
method_id_queue = Thread::Queue.new
|
|
1684
|
+
main_tid = gettid
|
|
1685
|
+
|
|
1686
|
+
correlator = Correlator.new(
|
|
1687
|
+
pin_dir: pin_dir,
|
|
1688
|
+
observer_pid: pid,
|
|
1689
|
+
main_tid: main_tid,
|
|
1690
|
+
method_id_queue: method_id_queue,
|
|
1691
|
+
filter: filter,
|
|
1692
|
+
dest: dest
|
|
1693
|
+
)
|
|
1694
|
+
correlator.start
|
|
1695
|
+
|
|
1696
|
+
tracer = build_observe_tracepoint(method_id_queue)
|
|
1498
1697
|
tracer.enable
|
|
1499
1698
|
|
|
1500
|
-
session = ObservationSession.new(
|
|
1699
|
+
session = ObservationSession.new(
|
|
1700
|
+
store: store, pid: pid, tracer: tracer, correlator: correlator
|
|
1701
|
+
)
|
|
1501
1702
|
at_exit { session.stop }
|
|
1502
1703
|
session
|
|
1503
1704
|
end
|
|
1504
1705
|
|
|
1505
|
-
def self.scoped_observe(pin_dir:,
|
|
1506
|
-
|
|
1706
|
+
def self.scoped_observe(pin_dir:, dest:, filter: nil)
|
|
1707
|
+
require "vivarium_usdt"
|
|
1708
|
+
|
|
1507
1709
|
store = MapStore.new(pin_dir: pin_dir)
|
|
1508
1710
|
pid = Process.pid
|
|
1509
1711
|
store.register_pid(pid)
|
|
1510
|
-
logger.info("scoped observing with pid=#{pid}")
|
|
1511
1712
|
|
|
1512
|
-
|
|
1713
|
+
method_id_queue = Thread::Queue.new
|
|
1714
|
+
main_tid = gettid
|
|
1715
|
+
|
|
1716
|
+
correlator = Correlator.new(
|
|
1717
|
+
pin_dir: pin_dir,
|
|
1718
|
+
observer_pid: pid,
|
|
1719
|
+
main_tid: main_tid,
|
|
1720
|
+
method_id_queue: method_id_queue,
|
|
1721
|
+
filter: filter,
|
|
1722
|
+
dest: dest
|
|
1723
|
+
)
|
|
1724
|
+
correlator.start
|
|
1725
|
+
|
|
1726
|
+
tracer = build_observe_tracepoint(method_id_queue)
|
|
1513
1727
|
tracer.enable
|
|
1514
1728
|
|
|
1515
1729
|
yield
|
|
1516
1730
|
ensure
|
|
1517
1731
|
tracer&.disable
|
|
1518
1732
|
store&.unregister_pid(pid)
|
|
1733
|
+
correlator&.stop
|
|
1519
1734
|
end
|
|
1520
1735
|
|
|
1521
|
-
def self.build_observe_tracepoint(
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1736
|
+
def self.build_observe_tracepoint(method_id_queue)
|
|
1737
|
+
allow_classes = SPAN_ALLOWCLASSES
|
|
1738
|
+
allowlist = SPAN_ALLOWLIST
|
|
1739
|
+
TracePoint.new(:call, :c_call, :return, :c_return, :raise) do |tp|
|
|
1740
|
+
if tp.event == :raise
|
|
1741
|
+
# FIXME: handle threaded events in the future
|
|
1742
|
+
if tp.raised_exception.kind_of?(ThreadError)
|
|
1743
|
+
next
|
|
1744
|
+
end
|
|
1525
1745
|
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1746
|
+
Vivarium::Usdt.raise(
|
|
1747
|
+
tp.raised_exception.class.to_s,
|
|
1748
|
+
tp.raised_exception.message.to_s,
|
|
1749
|
+
file: tp.path,
|
|
1750
|
+
lineno: tp.lineno
|
|
1751
|
+
)
|
|
1752
|
+
next
|
|
1753
|
+
end
|
|
1754
|
+
|
|
1755
|
+
signature = "#{tp.defined_class}##{tp.method_id}"
|
|
1756
|
+
is_target = allowlist.include?(signature) || \
|
|
1757
|
+
allow_classes.any? { |klass| tp.defined_class == klass } || \
|
|
1758
|
+
allow_classes.any? { |klass| tp.defined_class == klass.singleton_class }
|
|
1759
|
+
next unless is_target
|
|
1760
|
+
|
|
1761
|
+
case tp.event
|
|
1762
|
+
when :call, :c_call
|
|
1763
|
+
method_id = Vivarium::Usdt.start(tp.defined_class.to_s, tp.method_id.to_s, file: tp.path, lineno: tp.lineno)
|
|
1764
|
+
method_id_queue << [method_id, signature]
|
|
1765
|
+
when :return, :c_return
|
|
1766
|
+
Vivarium::Usdt.stop(tp.defined_class.to_s, tp.method_id.to_s, file: tp.path, lineno: tp.lineno)
|
|
1767
|
+
end
|
|
1529
1768
|
end
|
|
1530
1769
|
end
|
|
1531
1770
|
|
|
1532
|
-
def self.
|
|
1533
|
-
|
|
1534
|
-
|
|
1771
|
+
def self.gettid
|
|
1772
|
+
@gettid_func ||= begin
|
|
1773
|
+
libc = Fiddle.dlopen("libc.so.6")
|
|
1774
|
+
Fiddle::Function.new(libc["gettid"], [], Fiddle::TYPE_INT)
|
|
1775
|
+
rescue Fiddle::DLError
|
|
1776
|
+
libc = Fiddle.dlopen(nil)
|
|
1777
|
+
Fiddle::Function.new(libc["gettid"], [], Fiddle::TYPE_INT)
|
|
1778
|
+
end
|
|
1779
|
+
@gettid_func.call
|
|
1780
|
+
end
|
|
1535
1781
|
|
|
1536
|
-
|
|
1782
|
+
def self.monotonic_ktime_ns
|
|
1783
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
|
|
1784
|
+
end
|
|
1785
|
+
|
|
1786
|
+
def self.locate_vivarium_usdt_so
|
|
1787
|
+
require "vivarium_usdt/vivarium_usdt"
|
|
1788
|
+
so = $LOADED_FEATURES.find { |p| p =~ %r{vivarium_usdt/vivarium_usdt\.(so|bundle|dylib)\z} }
|
|
1789
|
+
raise Error, "vivarium_usdt native extension not found in $LOADED_FEATURES" unless so
|
|
1790
|
+
|
|
1791
|
+
File.realpath(so)
|
|
1792
|
+
rescue LoadError => e
|
|
1793
|
+
raise Error, "failed to load vivarium_usdt: #{e.message}"
|
|
1537
1794
|
end
|
|
1538
1795
|
|
|
1539
1796
|
def self.run_daemon!(argv = ARGV)
|
|
1540
|
-
options = { pin_dir: bpf_pin_dir }
|
|
1797
|
+
options = { pin_dir: bpf_pin_dir, ssl_trace: true, libssl_path: nil }
|
|
1541
1798
|
OptionParser.new do |opts|
|
|
1542
|
-
opts.banner = "Usage: vivariumd [--pin-dir PATH]"
|
|
1799
|
+
opts.banner = "Usage: vivariumd [--pin-dir PATH] [--no-ssl-trace] [--libssl PATH]"
|
|
1543
1800
|
opts.on("--pin-dir PATH", "Pinned map directory") { |v| options[:pin_dir] = v }
|
|
1801
|
+
opts.on("--[no-]ssl-trace", "Attach OpenSSL SSL_write uprobe (default: enabled)") do |v|
|
|
1802
|
+
options[:ssl_trace] = v
|
|
1803
|
+
end
|
|
1804
|
+
opts.on("--libssl PATH", "Path to libssl.so to attach SSL_write to") do |v|
|
|
1805
|
+
options[:libssl_path] = v
|
|
1806
|
+
end
|
|
1544
1807
|
end.parse!(argv)
|
|
1545
1808
|
|
|
1546
|
-
Daemon.new(
|
|
1809
|
+
Daemon.new(
|
|
1810
|
+
pin_dir: options[:pin_dir],
|
|
1811
|
+
ssl_trace: options[:ssl_trace],
|
|
1812
|
+
libssl_path: options[:libssl_path]
|
|
1813
|
+
).run
|
|
1547
1814
|
end
|
|
1548
1815
|
end
|
|
1816
|
+
|
|
1817
|
+
require_relative "vivarium/correlator"
|
|
1818
|
+
require_relative "vivarium/display_filter"
|
|
1819
|
+
require_relative "vivarium/tree_renderer"
|