vivarium 0.3.0 → 0.3.2
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/README.md +14 -10
- data/examples/dlopen_demo.rb +50 -0
- data/examples/drop_demo.rb +78 -0
- 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 +5 -1
- data/examples/signal_kill_demo.rb +5 -1
- data/examples/ssl_write_demo.rb +37 -0
- data/lib/vivarium/correlator.rb +13 -8
- data/lib/vivarium/display_filter.rb +158 -0
- data/lib/vivarium/http_decoder.rb +237 -0
- data/lib/vivarium/tree_renderer.rb +85 -10
- data/lib/vivarium/version.rb +1 -1
- data/lib/vivarium.rb +275 -11
- metadata +6 -1
data/lib/vivarium.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
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"
|
|
@@ -23,13 +24,45 @@ module Vivarium
|
|
|
23
24
|
EVENT_TS_SIZE = 8
|
|
24
25
|
PROC_EXEC_SLOT_SIZE = 64
|
|
25
26
|
PROC_EXEC_SLOT_COUNT = 4
|
|
26
|
-
EVENT_STRUCT_SIZE =
|
|
27
|
+
EVENT_STRUCT_SIZE = 296
|
|
27
28
|
EVENT_TS_OFFSET = 0
|
|
28
29
|
EVENT_PID_OFFSET = 8
|
|
29
30
|
EVENT_TID_OFFSET = 12
|
|
30
31
|
EVENT_NAME_OFFSET = 16
|
|
31
32
|
EVENT_PAYLOAD_OFFSET = 32
|
|
33
|
+
EVENT_DROPPED_OFFSET = 288
|
|
32
34
|
EVENTS_RINGBUF_PAGES = 256
|
|
35
|
+
|
|
36
|
+
SSL_WRITE_PAYLOAD_DATA_LEN_OFFSET = 0
|
|
37
|
+
SSL_WRITE_PAYLOAD_CAP_LEN_OFFSET = 4
|
|
38
|
+
SSL_WRITE_PAYLOAD_DATA_OFFSET = 8
|
|
39
|
+
SSL_WRITE_PAYLOAD_DATA_MAX = EVENT_PAYLOAD_SIZE - SSL_WRITE_PAYLOAD_DATA_OFFSET
|
|
40
|
+
|
|
41
|
+
LIBSSL_SEARCH_PATHS = [
|
|
42
|
+
"/lib/x86_64-linux-gnu/libssl.so.3",
|
|
43
|
+
"/lib/x86_64-linux-gnu/libssl.so.1.1",
|
|
44
|
+
"/lib/aarch64-linux-gnu/libssl.so.3",
|
|
45
|
+
"/lib/aarch64-linux-gnu/libssl.so.1.1",
|
|
46
|
+
"/usr/lib/x86_64-linux-gnu/libssl.so.3",
|
|
47
|
+
"/usr/lib/x86_64-linux-gnu/libssl.so.1.1",
|
|
48
|
+
"/usr/lib/aarch64-linux-gnu/libssl.so.3",
|
|
49
|
+
"/usr/lib/aarch64-linux-gnu/libssl.so.1.1",
|
|
50
|
+
"/usr/lib64/libssl.so.3",
|
|
51
|
+
"/usr/lib64/libssl.so.1.1",
|
|
52
|
+
"/usr/lib/libssl.so.3",
|
|
53
|
+
"/usr/lib/libssl.so.1.1"
|
|
54
|
+
].freeze
|
|
55
|
+
|
|
56
|
+
LIBC_SEARCH_PATHS = [
|
|
57
|
+
"/lib/x86_64-linux-gnu/libc.so.6",
|
|
58
|
+
"/lib/aarch64-linux-gnu/libc.so.6",
|
|
59
|
+
"/usr/lib/x86_64-linux-gnu/libc.so.6",
|
|
60
|
+
"/usr/lib/aarch64-linux-gnu/libc.so.6",
|
|
61
|
+
"/lib64/libc.so.6",
|
|
62
|
+
"/usr/lib64/libc.so.6",
|
|
63
|
+
"/lib/libc.so.6",
|
|
64
|
+
].freeze
|
|
65
|
+
|
|
33
66
|
SPAN_ALLOWCLASSES = [
|
|
34
67
|
Socket,
|
|
35
68
|
BasicSocket,
|
|
@@ -43,6 +76,7 @@ module Vivarium
|
|
|
43
76
|
Process,
|
|
44
77
|
Process::UID,
|
|
45
78
|
Process::GID,
|
|
79
|
+
Net::HTTP,
|
|
46
80
|
]
|
|
47
81
|
SPAN_ALLOWLIST = [
|
|
48
82
|
"Kernel#system",
|
|
@@ -56,6 +90,7 @@ module Vivarium
|
|
|
56
90
|
EVENT_SEVERITY_HIGH = %w[
|
|
57
91
|
capable_check bprm_creds setid_change task_kill
|
|
58
92
|
ptrace_check sb_mount kernel_read_file
|
|
93
|
+
dlopen
|
|
59
94
|
].freeze
|
|
60
95
|
|
|
61
96
|
CAPABILITY_NAMES = {
|
|
@@ -342,6 +377,17 @@ module Vivarium
|
|
|
342
377
|
result
|
|
343
378
|
end
|
|
344
379
|
|
|
380
|
+
def self.decode_ssl_write_payload(raw_payload)
|
|
381
|
+
bytes = raw_payload.to_s.b
|
|
382
|
+
return { data_len: 0, cap_len: 0, data: "".b } if bytes.bytesize < SSL_WRITE_PAYLOAD_DATA_OFFSET
|
|
383
|
+
|
|
384
|
+
data_len = bytes[SSL_WRITE_PAYLOAD_DATA_LEN_OFFSET, 4].unpack1("L<")
|
|
385
|
+
cap_len = bytes[SSL_WRITE_PAYLOAD_CAP_LEN_OFFSET, 4].unpack1("L<")
|
|
386
|
+
cap_len = SSL_WRITE_PAYLOAD_DATA_MAX if cap_len > SSL_WRITE_PAYLOAD_DATA_MAX
|
|
387
|
+
data = bytes[SSL_WRITE_PAYLOAD_DATA_OFFSET, cap_len] || "".b
|
|
388
|
+
{ data_len: data_len, cap_len: cap_len, data: data }
|
|
389
|
+
end
|
|
390
|
+
|
|
345
391
|
def self.decode_span_raise_payload(raw_payload)
|
|
346
392
|
bytes = raw_payload.to_s.b
|
|
347
393
|
return "" if bytes.bytesize < 8
|
|
@@ -426,6 +472,11 @@ module Vivarium
|
|
|
426
472
|
when "file_getdents"
|
|
427
473
|
decoded = decode_file_getdents_payload(event.payload)
|
|
428
474
|
decoded.empty? ? event.payload.inspect : decoded
|
|
475
|
+
when "ssl_write"
|
|
476
|
+
decoded = decode_ssl_write_payload(event.payload)
|
|
477
|
+
"data_len=#{decoded[:data_len]} cap_len=#{decoded[:cap_len]}"
|
|
478
|
+
when "dlopen", "mmap_exec"
|
|
479
|
+
strip_to_first_null(event.payload).inspect
|
|
429
480
|
else
|
|
430
481
|
strip_to_first_null(event.payload).inspect
|
|
431
482
|
end
|
|
@@ -582,12 +633,14 @@ module Vivarium
|
|
|
582
633
|
u32 tid;
|
|
583
634
|
char event_name[16];
|
|
584
635
|
char payload[#{EVENT_PAYLOAD_SIZE}];
|
|
636
|
+
u64 dropped_since_last;
|
|
585
637
|
};
|
|
586
638
|
|
|
587
639
|
BPF_HASH(config_root_targets, u32, u8, 1024);
|
|
588
640
|
BPF_HASH(config_spawned_targets, u32, u8, 8192);
|
|
589
641
|
BPF_HASH(dns_connected_tids, u32, u8, 8192);
|
|
590
642
|
BPF_RINGBUF_OUTPUT(events, #{EVENTS_RINGBUF_PAGES});
|
|
643
|
+
BPF_ARRAY(drop_counter, u64, 1);
|
|
591
644
|
|
|
592
645
|
static __always_inline int target_enabled(u32 pid, u32 tid)
|
|
593
646
|
{
|
|
@@ -629,14 +682,27 @@ module Vivarium
|
|
|
629
682
|
|
|
630
683
|
static __always_inline void submit_event(struct event_t *src)
|
|
631
684
|
{
|
|
685
|
+
u32 key = 0;
|
|
686
|
+
u64 *cnt;
|
|
687
|
+
|
|
632
688
|
struct event_t *ev = events.ringbuf_reserve(sizeof(struct event_t));
|
|
633
689
|
if (!ev) {
|
|
690
|
+
cnt = drop_counter.lookup(&key);
|
|
691
|
+
if (cnt) {
|
|
692
|
+
__sync_fetch_and_add(cnt, 1);
|
|
693
|
+
}
|
|
634
694
|
return;
|
|
635
695
|
}
|
|
636
696
|
|
|
637
697
|
__builtin_memcpy(ev, src, sizeof(*ev));
|
|
638
698
|
ev->ktime_ns = bpf_ktime_get_ns();
|
|
639
699
|
ev->tid = (u32)bpf_get_current_pid_tgid();
|
|
700
|
+
ev->dropped_since_last = 0;
|
|
701
|
+
|
|
702
|
+
cnt = drop_counter.lookup(&key);
|
|
703
|
+
if (cnt && *cnt > 0) {
|
|
704
|
+
ev->dropped_since_last = __sync_lock_test_and_set(cnt, 0);
|
|
705
|
+
}
|
|
640
706
|
|
|
641
707
|
events.ringbuf_submit(ev, 0);
|
|
642
708
|
}
|
|
@@ -770,6 +836,39 @@ module Vivarium
|
|
|
770
836
|
return 0;
|
|
771
837
|
}
|
|
772
838
|
|
|
839
|
+
LSM_PROBE(mmap_file, struct file *file, unsigned long reqprot,
|
|
840
|
+
unsigned long prot, unsigned long flags)
|
|
841
|
+
{
|
|
842
|
+
if (!file) {
|
|
843
|
+
return 0;
|
|
844
|
+
}
|
|
845
|
+
if (!((prot | reqprot) & 0x04)) { /* PROT_EXEC */
|
|
846
|
+
return 0;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
850
|
+
u32 pid = pid_tgid >> 32;
|
|
851
|
+
u32 tid = (u32)pid_tgid;
|
|
852
|
+
if (!target_enabled(pid, tid)) {
|
|
853
|
+
return 0;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
struct event_t ev = {};
|
|
857
|
+
int path_ret;
|
|
858
|
+
ev.pid = pid;
|
|
859
|
+
__builtin_memcpy(ev.event_name, "mmap_exec", 10);
|
|
860
|
+
|
|
861
|
+
path_ret = bpf_d_path(&file->f_path, ev.payload, sizeof(ev.payload));
|
|
862
|
+
if (path_ret < 0) {
|
|
863
|
+
if (ev.payload[0] == 0) {
|
|
864
|
+
__builtin_memcpy(ev.payload, "<path_error>", 13);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
submit_event(&ev);
|
|
869
|
+
return 0;
|
|
870
|
+
}
|
|
871
|
+
|
|
773
872
|
LSM_PROBE(socket_create, int family, int type, int protocol, int kern)
|
|
774
873
|
{
|
|
775
874
|
u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
@@ -1339,6 +1438,68 @@ module Vivarium
|
|
|
1339
1438
|
return 0;
|
|
1340
1439
|
}
|
|
1341
1440
|
|
|
1441
|
+
int on_ssl_write(struct pt_regs *ctx)
|
|
1442
|
+
{
|
|
1443
|
+
u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
1444
|
+
u32 pid = pid_tgid >> 32;
|
|
1445
|
+
u32 tid = (u32)pid_tgid;
|
|
1446
|
+
|
|
1447
|
+
if (!target_enabled(pid, tid)) {
|
|
1448
|
+
return 0;
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
const char *buf = (const char *)PT_REGS_PARM2(ctx);
|
|
1452
|
+
int num = (int)PT_REGS_PARM3(ctx);
|
|
1453
|
+
if (!buf || num <= 0) {
|
|
1454
|
+
return 0;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
struct event_t ev = {};
|
|
1458
|
+
ev.pid = pid;
|
|
1459
|
+
__builtin_memcpy(ev.event_name, "ssl_write", 10);
|
|
1460
|
+
|
|
1461
|
+
u32 data_len = (u32)num;
|
|
1462
|
+
u32 cap = data_len;
|
|
1463
|
+
if (cap > #{SSL_WRITE_PAYLOAD_DATA_MAX}) {
|
|
1464
|
+
cap = #{SSL_WRITE_PAYLOAD_DATA_MAX};
|
|
1465
|
+
}
|
|
1466
|
+
__builtin_memcpy(&ev.payload[#{SSL_WRITE_PAYLOAD_DATA_LEN_OFFSET}], &data_len, sizeof(data_len));
|
|
1467
|
+
__builtin_memcpy(&ev.payload[#{SSL_WRITE_PAYLOAD_CAP_LEN_OFFSET}], &cap, sizeof(cap));
|
|
1468
|
+
if (bpf_probe_read_user(&ev.payload[#{SSL_WRITE_PAYLOAD_DATA_OFFSET}], cap, buf) < 0) {
|
|
1469
|
+
u32 zero = 0;
|
|
1470
|
+
__builtin_memcpy(&ev.payload[#{SSL_WRITE_PAYLOAD_CAP_LEN_OFFSET}], &zero, sizeof(zero));
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
submit_event(&ev);
|
|
1474
|
+
return 0;
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
int on_dlopen(struct pt_regs *ctx)
|
|
1478
|
+
{
|
|
1479
|
+
u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
1480
|
+
u32 pid = pid_tgid >> 32;
|
|
1481
|
+
u32 tid = (u32)pid_tgid;
|
|
1482
|
+
if (!target_enabled(pid, tid)) {
|
|
1483
|
+
return 0;
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
const char *filename = (const char *)PT_REGS_PARM1(ctx);
|
|
1487
|
+
if (!filename) {
|
|
1488
|
+
return 0;
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
struct event_t ev = {};
|
|
1492
|
+
ev.pid = pid;
|
|
1493
|
+
__builtin_memcpy(ev.event_name, "dlopen", 7);
|
|
1494
|
+
|
|
1495
|
+
if (bpf_probe_read_user_str(ev.payload, sizeof(ev.payload), filename) < 0) {
|
|
1496
|
+
__builtin_memcpy(ev.payload, "<path_error>", 13);
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
submit_event(&ev);
|
|
1500
|
+
return 0;
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1342
1503
|
int on_span_raise(struct pt_regs *ctx)
|
|
1343
1504
|
{
|
|
1344
1505
|
u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
@@ -1370,8 +1531,13 @@ module Vivarium
|
|
|
1370
1531
|
}
|
|
1371
1532
|
CLANG
|
|
1372
1533
|
|
|
1373
|
-
def initialize(pin_dir: Vivarium.bpf_pin_dir
|
|
1374
|
-
|
|
1534
|
+
def initialize(pin_dir: Vivarium.bpf_pin_dir, ssl_trace: true, libssl_path: nil,
|
|
1535
|
+
dlopen_trace: true, libc_path: nil)
|
|
1536
|
+
@pin_dir = pin_dir
|
|
1537
|
+
@ssl_trace = ssl_trace
|
|
1538
|
+
@libssl_path = libssl_path
|
|
1539
|
+
@dlopen_trace = dlopen_trace
|
|
1540
|
+
@libc_path = libc_path
|
|
1375
1541
|
end
|
|
1376
1542
|
|
|
1377
1543
|
def run
|
|
@@ -1384,6 +1550,7 @@ module Vivarium
|
|
|
1384
1550
|
.gsub("__VIVARIUM_F_PATH_OFFSET__", f_path_offset.to_s)
|
|
1385
1551
|
.gsub("__VIVARIUM_DENTRY_D_NAME_OFFSET__", d_name_offset.to_s)
|
|
1386
1552
|
|
|
1553
|
+
require "vivarium_usdt"
|
|
1387
1554
|
usdt_so_path = ENV.fetch("VIVARIUM_USDT_SO_PATH") { Vivarium.locate_vivarium_usdt_so }
|
|
1388
1555
|
usdt = RbBCC::USDT.new(path: usdt_so_path)
|
|
1389
1556
|
usdt.enable_probe(probe: "start_probe", fn_name: "on_span_start")
|
|
@@ -1392,6 +1559,9 @@ module Vivarium
|
|
|
1392
1559
|
|
|
1393
1560
|
bpf = RbBCC::BCC.new(text: program, usdt_contexts: [usdt])
|
|
1394
1561
|
|
|
1562
|
+
attach_ssl_write_uprobe(bpf) if @ssl_trace
|
|
1563
|
+
attach_dlopen_uprobe(bpf) if @dlopen_trace
|
|
1564
|
+
|
|
1395
1565
|
config_root_targets = bpf["config_root_targets"]
|
|
1396
1566
|
config_spawned_targets = bpf["config_spawned_targets"]
|
|
1397
1567
|
events_ringbuf = bpf["events"]
|
|
@@ -1416,6 +1586,72 @@ module Vivarium
|
|
|
1416
1586
|
|
|
1417
1587
|
private
|
|
1418
1588
|
|
|
1589
|
+
def attach_ssl_write_uprobe(bpf)
|
|
1590
|
+
path = resolve_libssl_path
|
|
1591
|
+
unless path
|
|
1592
|
+
warn "[vivariumd] libssl not found; SSL_write uprobe disabled " \
|
|
1593
|
+
"(set --libssl PATH or VIVARIUM_LIBSSL_PATH to override)"
|
|
1594
|
+
return
|
|
1595
|
+
end
|
|
1596
|
+
|
|
1597
|
+
bpf.attach_uprobe(name: path, sym: "SSL_write", fn_name: "on_ssl_write")
|
|
1598
|
+
puts "[vivariumd] SSL_write uprobe attached via #{path}"
|
|
1599
|
+
rescue StandardError => e
|
|
1600
|
+
warn "[vivariumd] SSL_write uprobe attach failed: #{e.class}: #{e.message}"
|
|
1601
|
+
end
|
|
1602
|
+
|
|
1603
|
+
def resolve_libssl_path
|
|
1604
|
+
if @libssl_path
|
|
1605
|
+
return @libssl_path if File.exist?(@libssl_path)
|
|
1606
|
+
|
|
1607
|
+
warn "[vivariumd] --libssl path does not exist: #{@libssl_path}"
|
|
1608
|
+
return nil
|
|
1609
|
+
end
|
|
1610
|
+
|
|
1611
|
+
env_path = ENV["VIVARIUM_LIBSSL_PATH"]
|
|
1612
|
+
if env_path && !env_path.empty?
|
|
1613
|
+
return env_path if File.exist?(env_path)
|
|
1614
|
+
|
|
1615
|
+
warn "[vivariumd] VIVARIUM_LIBSSL_PATH does not exist: #{env_path}"
|
|
1616
|
+
return nil
|
|
1617
|
+
end
|
|
1618
|
+
|
|
1619
|
+
LIBSSL_SEARCH_PATHS.find { |p| File.exist?(p) }
|
|
1620
|
+
end
|
|
1621
|
+
|
|
1622
|
+
def attach_dlopen_uprobe(bpf)
|
|
1623
|
+
path = resolve_libc_path
|
|
1624
|
+
unless path
|
|
1625
|
+
warn "[vivariumd] libc not found; dlopen uprobe disabled " \
|
|
1626
|
+
"(set --libc PATH or VIVARIUM_LIBC_PATH to override)"
|
|
1627
|
+
return
|
|
1628
|
+
end
|
|
1629
|
+
|
|
1630
|
+
bpf.attach_uprobe(name: path, sym: "dlopen", fn_name: "on_dlopen")
|
|
1631
|
+
puts "[vivariumd] dlopen uprobe attached via #{path}"
|
|
1632
|
+
rescue StandardError => e
|
|
1633
|
+
warn "[vivariumd] dlopen uprobe attach failed: #{e.class}: #{e.message}"
|
|
1634
|
+
end
|
|
1635
|
+
|
|
1636
|
+
def resolve_libc_path
|
|
1637
|
+
if @libc_path
|
|
1638
|
+
return @libc_path if File.exist?(@libc_path)
|
|
1639
|
+
|
|
1640
|
+
warn "[vivariumd] --libc path does not exist: #{@libc_path}"
|
|
1641
|
+
return nil
|
|
1642
|
+
end
|
|
1643
|
+
|
|
1644
|
+
env_path = ENV["VIVARIUM_LIBC_PATH"]
|
|
1645
|
+
if env_path && !env_path.empty?
|
|
1646
|
+
return env_path if File.exist?(env_path)
|
|
1647
|
+
|
|
1648
|
+
warn "[vivariumd] VIVARIUM_LIBC_PATH does not exist: #{env_path}"
|
|
1649
|
+
return nil
|
|
1650
|
+
end
|
|
1651
|
+
|
|
1652
|
+
LIBC_SEARCH_PATHS.find { |p| File.exist?(p) }
|
|
1653
|
+
end
|
|
1654
|
+
|
|
1419
1655
|
def ensure_root!
|
|
1420
1656
|
return if Process.uid.zero?
|
|
1421
1657
|
|
|
@@ -1557,13 +1793,13 @@ module Vivarium
|
|
|
1557
1793
|
end
|
|
1558
1794
|
end
|
|
1559
1795
|
|
|
1560
|
-
def self.observe(pin_dir: bpf_pin_dir, dest: $stdout, &block)
|
|
1561
|
-
return scoped_observe(pin_dir: pin_dir, dest: dest, &block) if block_given?
|
|
1796
|
+
def self.observe(pin_dir: bpf_pin_dir, dest: $stdout, filter: nil, &block)
|
|
1797
|
+
return scoped_observe(pin_dir: pin_dir, dest: dest, filter: filter, &block) if block_given?
|
|
1562
1798
|
|
|
1563
|
-
top_observe(pin_dir: pin_dir, dest: dest)
|
|
1799
|
+
top_observe(pin_dir: pin_dir, dest: dest, filter: filter)
|
|
1564
1800
|
end
|
|
1565
1801
|
|
|
1566
|
-
def self.top_observe(pin_dir: bpf_pin_dir, dest: $stdout)
|
|
1802
|
+
def self.top_observe(pin_dir: bpf_pin_dir, dest: $stdout, filter: nil)
|
|
1567
1803
|
require "vivarium_usdt"
|
|
1568
1804
|
|
|
1569
1805
|
store = MapStore.new(pin_dir: pin_dir)
|
|
@@ -1578,6 +1814,7 @@ module Vivarium
|
|
|
1578
1814
|
observer_pid: pid,
|
|
1579
1815
|
main_tid: main_tid,
|
|
1580
1816
|
method_id_queue: method_id_queue,
|
|
1817
|
+
filter: filter,
|
|
1581
1818
|
dest: dest
|
|
1582
1819
|
)
|
|
1583
1820
|
correlator.start
|
|
@@ -1592,7 +1829,7 @@ module Vivarium
|
|
|
1592
1829
|
session
|
|
1593
1830
|
end
|
|
1594
1831
|
|
|
1595
|
-
def self.scoped_observe(pin_dir:, dest:)
|
|
1832
|
+
def self.scoped_observe(pin_dir:, dest:, filter: nil)
|
|
1596
1833
|
require "vivarium_usdt"
|
|
1597
1834
|
|
|
1598
1835
|
store = MapStore.new(pin_dir: pin_dir)
|
|
@@ -1607,6 +1844,7 @@ module Vivarium
|
|
|
1607
1844
|
observer_pid: pid,
|
|
1608
1845
|
main_tid: main_tid,
|
|
1609
1846
|
method_id_queue: method_id_queue,
|
|
1847
|
+
filter: filter,
|
|
1610
1848
|
dest: dest
|
|
1611
1849
|
)
|
|
1612
1850
|
correlator.start
|
|
@@ -1626,6 +1864,11 @@ module Vivarium
|
|
|
1626
1864
|
allowlist = SPAN_ALLOWLIST
|
|
1627
1865
|
TracePoint.new(:call, :c_call, :return, :c_return, :raise) do |tp|
|
|
1628
1866
|
if tp.event == :raise
|
|
1867
|
+
# FIXME: handle threaded events in the future
|
|
1868
|
+
if tp.raised_exception.kind_of?(ThreadError)
|
|
1869
|
+
next
|
|
1870
|
+
end
|
|
1871
|
+
|
|
1629
1872
|
Vivarium::Usdt.raise(
|
|
1630
1873
|
tp.raised_exception.class.to_s,
|
|
1631
1874
|
tp.raised_exception.message.to_s,
|
|
@@ -1677,15 +1920,36 @@ module Vivarium
|
|
|
1677
1920
|
end
|
|
1678
1921
|
|
|
1679
1922
|
def self.run_daemon!(argv = ARGV)
|
|
1680
|
-
options = { pin_dir: bpf_pin_dir
|
|
1923
|
+
options = { pin_dir: bpf_pin_dir, ssl_trace: true, libssl_path: nil,
|
|
1924
|
+
dlopen_trace: true, libc_path: nil }
|
|
1681
1925
|
OptionParser.new do |opts|
|
|
1682
|
-
opts.banner = "Usage: vivariumd [--pin-dir PATH]"
|
|
1926
|
+
opts.banner = "Usage: vivariumd [--pin-dir PATH] [--no-ssl-trace] [--libssl PATH] " \
|
|
1927
|
+
"[--no-dlopen-trace] [--libc PATH]"
|
|
1683
1928
|
opts.on("--pin-dir PATH", "Pinned map directory") { |v| options[:pin_dir] = v }
|
|
1929
|
+
opts.on("--[no-]ssl-trace", "Attach OpenSSL SSL_write uprobe (default: enabled)") do |v|
|
|
1930
|
+
options[:ssl_trace] = v
|
|
1931
|
+
end
|
|
1932
|
+
opts.on("--libssl PATH", "Path to libssl.so to attach SSL_write to") do |v|
|
|
1933
|
+
options[:libssl_path] = v
|
|
1934
|
+
end
|
|
1935
|
+
opts.on("--[no-]dlopen-trace", "Attach libc dlopen uprobe (default: enabled)") do |v|
|
|
1936
|
+
options[:dlopen_trace] = v
|
|
1937
|
+
end
|
|
1938
|
+
opts.on("--libc PATH", "Path to libc.so for dlopen uprobe") do |v|
|
|
1939
|
+
options[:libc_path] = v
|
|
1940
|
+
end
|
|
1684
1941
|
end.parse!(argv)
|
|
1685
1942
|
|
|
1686
|
-
Daemon.new(
|
|
1943
|
+
Daemon.new(
|
|
1944
|
+
pin_dir: options[:pin_dir],
|
|
1945
|
+
ssl_trace: options[:ssl_trace],
|
|
1946
|
+
libssl_path: options[:libssl_path],
|
|
1947
|
+
dlopen_trace: options[:dlopen_trace],
|
|
1948
|
+
libc_path: options[:libc_path]
|
|
1949
|
+
).run
|
|
1687
1950
|
end
|
|
1688
1951
|
end
|
|
1689
1952
|
|
|
1690
1953
|
require_relative "vivarium/correlator"
|
|
1954
|
+
require_relative "vivarium/display_filter"
|
|
1691
1955
|
require_relative "vivarium/tree_renderer"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: vivarium
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Uchio Kondo
|
|
@@ -64,12 +64,15 @@ files:
|
|
|
64
64
|
- CONTEXT.md
|
|
65
65
|
- README.md
|
|
66
66
|
- Rakefile
|
|
67
|
+
- examples/dlopen_demo.rb
|
|
68
|
+
- examples/drop_demo.rb
|
|
67
69
|
- examples/execve_demo.rb
|
|
68
70
|
- examples/file_operation_demo.rb
|
|
69
71
|
- examples/network_client_demo.rb
|
|
70
72
|
- examples/privilege_event_demo.rb
|
|
71
73
|
- examples/raise_demo.rb
|
|
72
74
|
- examples/signal_kill_demo.rb
|
|
75
|
+
- examples/ssl_write_demo.rb
|
|
73
76
|
- examples/sudo_attempt_demo.rb
|
|
74
77
|
- exe/vivarium
|
|
75
78
|
- exe/vivariumd
|
|
@@ -77,6 +80,8 @@ files:
|
|
|
77
80
|
- lib/vivarium.rb
|
|
78
81
|
- lib/vivarium/cli.rb
|
|
79
82
|
- lib/vivarium/correlator.rb
|
|
83
|
+
- lib/vivarium/display_filter.rb
|
|
84
|
+
- lib/vivarium/http_decoder.rb
|
|
80
85
|
- lib/vivarium/tree_renderer.rb
|
|
81
86
|
- lib/vivarium/version.rb
|
|
82
87
|
- logo-simple.png
|