Pass the connection address from write to gzip through a common address between gzip and dial

This commit is contained in:
M. Mert Yildiran 2022-06-01 14:57:16 +03:00
parent 76bee7a9df
commit c7d40d1caf
No known key found for this signature in database
GPG Key ID: D42ADB236521BF7A
8 changed files with 132 additions and 72 deletions

View File

@ -57,6 +57,20 @@ static __always_inline int golang_crypto_tls_write_uprobe(struct pt_regs *ctx) {
b->is_request = true; b->is_request = true;
b->is_gzip_chunk = false; b->is_gzip_chunk = false;
struct socket x = {
.pid = s->pid,
.fd = ctx->rax,
.key_dial = s->key_dial,
.key_gzip = s->key_gzip,
.conn_addr = b->conn_addr,
};
__u64 key_gzip_full = (pid << 32) + s->key_gzip;
status = bpf_map_update_elem(&golang_write_to_gzip, &key_gzip_full, &x, BPF_ANY);
if (status != 0) {
bpf_printk("[golang_crypto_tls_write_uprobe] error updating gzip conn addr: %d", status);
}
status = bpf_probe_read_str(&b->data, sizeof(b->data), (void*)ctx->rbx); status = bpf_probe_read_str(&b->data, sizeof(b->data), (void*)ctx->rbx);
if (status < 0) { if (status < 0) {
bpf_printk("[golang_crypto_tls_write_uprobe] error reading data: %d", status); bpf_printk("[golang_crypto_tls_write_uprobe] error reading data: %d", status);
@ -114,23 +128,38 @@ static __always_inline int golang_crypto_tls_read_uprobe(struct pt_regs *ctx) {
SEC("uprobe/golang_net_http_gzipreader_read") SEC("uprobe/golang_net_http_gzipreader_read")
static __always_inline int golang_net_http_gzipreader_read_uprobe(struct pt_regs *ctx) { static __always_inline int golang_net_http_gzipreader_read_uprobe(struct pt_regs *ctx) {
void* stack_addr = (void*)ctx->rsp;
__u64 pid_tgid = bpf_get_current_pid_tgid();
__u64 pid = pid_tgid >> 32;
__u32 key_gzip;
// Address at ctx->rsp + 0x150 is common between golang_net_http_gzipreader_read_uprobe and golang_net_http_dialconn_uprobe
__u32 status = bpf_probe_read(&key_gzip, sizeof(key_gzip), stack_addr + 0x150);
if (status < 0) {
bpf_printk("[golang_net_http_gzipreader_read_uprobe] error reading key_gzip: %d", status);
return 0;
}
__u64 key_gzip_full = (pid << 32) + key_gzip;
struct socket *s = bpf_map_lookup_elem(&golang_write_to_gzip, &key_gzip_full);
if (s == NULL) {
bpf_printk("[golang_net_http_gzipreader_read_uprobe] error getting socket");
return 0;
}
struct golang_read_write *b = NULL; struct golang_read_write *b = NULL;
b = bpf_ringbuf_reserve(&golang_read_writes, sizeof(struct golang_read_write), 0); b = bpf_ringbuf_reserve(&golang_read_writes, sizeof(struct golang_read_write), 0);
if (!b) { if (!b) {
return 0; return 0;
} }
// __u64 pid_tgid = bpf_get_current_pid_tgid(); b->pid = pid;
// b->pid = pid_tgid >> 32; b->conn_addr = s->conn_addr;
// // ctx->rsi is common between golang_crypto_tls_write_uprobe and golang_crypto_tls_read_uprobe
// b->conn_addr = ctx->rsi; // go.itab.*net.TCPConn,net.Conn address
b->is_request = false; b->is_request = false;
b->is_gzip_chunk = true; b->is_gzip_chunk = true;
void* stack_addr = (void*)ctx->rsp;
__u64 data_p; __u64 data_p;
// Address at ctx->rsp + 0x8 holds the data // Address at ctx->rsp + 0x8 holds the data
__u32 status = bpf_probe_read(&data_p, sizeof(data_p), stack_addr + 0x8); status = bpf_probe_read(&data_p, sizeof(data_p), stack_addr + 0x8);
if (status < 0) { if (status < 0) {
bpf_printk("[golang_net_http_gzipreader_read_uprobe] error reading data pointer: %d", status); bpf_printk("[golang_net_http_gzipreader_read_uprobe] error reading data pointer: %d", status);
bpf_ringbuf_discard(b, BPF_RB_FORCE_WAKEUP); bpf_ringbuf_discard(b, BPF_RB_FORCE_WAKEUP);
@ -160,7 +189,13 @@ static __always_inline int golang_net_socket_uprobe(struct pt_regs *ctx) {
return 0; return 0;
} }
struct socket b = { .pid = s->pid, .fd = ctx->rax, .key_dial = s->key_dial }; struct socket b = {
.pid = s->pid,
.fd = ctx->rax,
.key_dial = s->key_dial,
.key_gzip = s->key_gzip,
.conn_addr = 0,
};
__u64 key_dial_full = (pid << 32) + s->key_dial; __u64 key_dial_full = (pid << 32) + s->key_dial;
__u32 status = bpf_map_update_elem(&golang_socket_to_write, &key_dial_full, &b, BPF_ANY); __u32 status = bpf_map_update_elem(&golang_socket_to_write, &key_dial_full, &b, BPF_ANY);
@ -182,8 +217,22 @@ static __always_inline int golang_net_http_dialconn_uprobe(struct pt_regs *ctx)
return 0; return 0;
} }
__u32 key_gzip;
// Address at ctx->rsp + 0x1d0 is common between golang_net_http_gzipreader_read_uprobe and golang_net_http_dialconn_uprobe
status = bpf_probe_read(&key_gzip, sizeof(key_gzip), stack_addr + 0x1d0);
if (status < 0) {
bpf_printk("[golang_net_http_dialconn_uprobe] error reading key_gzip: %d", status);
return 0;
}
__u64 pid_tgid = bpf_get_current_pid_tgid(); __u64 pid_tgid = bpf_get_current_pid_tgid();
struct socket b = { .pid = pid_tgid >> 32, .fd = 0, .key_dial = key_dial }; struct socket b = {
.pid = pid_tgid >> 32,
.fd = 0,
.key_dial = key_dial,
.key_gzip = key_gzip,
.conn_addr = 0,
};
__u64 pid = b.pid; __u64 pid = b.pid;
// ctx->r14 is common between golang_net_socket_uprobe and golang_net_http_dialconn_uprobe // ctx->r14 is common between golang_net_socket_uprobe and golang_net_http_dialconn_uprobe

View File

@ -57,6 +57,8 @@ struct socket {
__u32 pid; __u32 pid;
__u32 fd; __u32 fd;
__u64 key_dial; __u64 key_dial;
__u64 key_gzip;
__u64 conn_addr;
}; };
#define BPF_MAP(_name, _type, _key_type, _value_type, _max_entries) \ #define BPF_MAP(_name, _type, _key_type, _value_type, _max_entries) \
@ -91,6 +93,7 @@ BPF_PERF_OUTPUT(log_buffer);
BPF_LRU_HASH(golang_dial_to_socket, __u64, struct socket); BPF_LRU_HASH(golang_dial_to_socket, __u64, struct socket);
BPF_LRU_HASH(golang_socket_to_write, __u64, struct socket); BPF_LRU_HASH(golang_socket_to_write, __u64, struct socket);
BPF_LRU_HASH(golang_write_to_gzip, __u64, struct socket);
BPF_RINGBUF(golang_read_writes); BPF_RINGBUF(golang_read_writes);
#endif /* __MAPS__ */ #endif /* __MAPS__ */

View File

@ -4,10 +4,9 @@ type golangConnection struct {
Pid uint32 Pid uint32
ConnAddr uint32 ConnAddr uint32
AddressPair addressPair AddressPair addressPair
Request []byte Requests [][]byte
Response []byte Responses [][]byte
GotRequest bool Gzipped bool
GotResponse bool
} }
func NewGolangConnection(pid uint32, connAddr uint32) *golangConnection { func NewGolangConnection(pid uint32, connAddr uint32) *golangConnection {

View File

@ -22,7 +22,6 @@ import (
"github.com/up9inc/mizu/logger" "github.com/up9inc/mizu/logger"
"github.com/up9inc/mizu/tap/api" "github.com/up9inc/mizu/tap/api"
orderedmap "github.com/wk8/go-ordered-map" orderedmap "github.com/wk8/go-ordered-map"
"golang.org/x/sys/unix"
) )
const ( const (
@ -138,12 +137,6 @@ func (p *tlsPoller) pollGolangReadWrite(rd *ringbuf.Reader, emitter api.Emitter,
continue continue
} }
if b.IsGzipChunk {
chunk := unix.ByteSliceToString(b.Data[:])
fmt.Printf("chunk: %v\n", chunk)
continue
}
if p.golangReadWriteMap.Len()+1 > golangMapLimit { if p.golangReadWriteMap.Len()+1 > golangMapLimit {
pair := p.golangReadWriteMap.Oldest() pair := p.golangReadWriteMap.Oldest()
p.golangReadWriteMap.Delete(pair.Key) p.golangReadWriteMap.Delete(pair.Key)
@ -162,6 +155,10 @@ func (p *tlsPoller) pollGolangReadWrite(rd *ringbuf.Reader, emitter api.Emitter,
connection = _connection.(*golangConnection) connection = _connection.(*golangConnection)
} }
if b.IsGzipChunk {
connection.Gzipped = true
}
if b.IsRequest { if b.IsRequest {
err := connection.setAddressBySockfd(p.procfs, b.Pid, b.Fd) err := connection.setAddressBySockfd(p.procfs, b.Pid, b.Fd)
if err != nil { if err != nil {
@ -169,71 +166,77 @@ func (p *tlsPoller) pollGolangReadWrite(rd *ringbuf.Reader, emitter api.Emitter,
continue continue
} }
connection.Request = make([]byte, len(b.Data[:])) request := make([]byte, len(b.Data[:]))
copy(connection.Request, b.Data[:]) copy(request, b.Data[:])
connection.GotRequest = true connection.Requests = append(connection.Requests, request)
} else { } else {
connection.Response = make([]byte, len(b.Data[:])) response := make([]byte, len(b.Data[:]))
copy(connection.Response, b.Data[:]) copy(response, b.Data[:])
connection.GotResponse = true connection.Responses = append(connection.Responses, response)
}
if connection.GotRequest && connection.GotResponse { if !b.IsGzipChunk {
// TODO: Remove these comments // TODO: Remove these comments
// fmt.Printf("\n\nconnection.Pid: %v\n", connection.Pid) // fmt.Printf("\n\nidentifier: %v\n", identifier)
// fmt.Printf("connection.Pid: %v\n", connection.Pid)
// fmt.Printf("connection.ConnAddr: 0x%x\n", connection.ConnAddr) // fmt.Printf("connection.ConnAddr: 0x%x\n", connection.ConnAddr)
// fmt.Printf("connection.AddressPair.srcIp: %v\n", connection.AddressPair.srcIp) // fmt.Printf("connection.AddressPair.srcIp: %v\n", connection.AddressPair.srcIp)
// fmt.Printf("connection.AddressPair.srcPort: %v\n", connection.AddressPair.srcPort) // fmt.Printf("connection.AddressPair.srcPort: %v\n", connection.AddressPair.srcPort)
// fmt.Printf("connection.AddressPair.dstIp: %v\n", connection.AddressPair.dstIp) // fmt.Printf("connection.AddressPair.dstIp: %v\n", connection.AddressPair.dstIp)
// fmt.Printf("connection.AddressPair.dstPort: %v\n", connection.AddressPair.dstPort) // fmt.Printf("connection.AddressPair.dstPort: %v\n", connection.AddressPair.dstPort)
// fmt.Printf("connection.Request:\n%v\n", unix.ByteSliceToString(connection.Request)) // fmt.Printf("connection.Gzipped: %v\n", connection.Gzipped)
// fmt.Printf("connection.Response:\n%v\n", unix.ByteSliceToString(connection.Response)) // for i, x := range connection.Requests {
// fmt.Printf("connection.Request[%d]:\n%v\n", i, unix.ByteSliceToString(x))
// }
// for i, y := range connection.Responses {
// fmt.Printf("connection.Response[%d]:\n%v\n", i, unix.ByteSliceToString(y))
// }
tcpid := p.buildTcpId(&connection.AddressPair) // tcpid := p.buildTcpId(&connection.AddressPair)
tlsEmitter := &tlsEmitter{ // tlsEmitter := &tlsEmitter{
delegate: emitter, // delegate: emitter,
namespace: p.getNamespace(b.Pid), // namespace: p.getNamespace(b.Pid),
} // }
reader := &tlsReader{ // reader := &tlsReader{
chunks: make(chan *tlsChunk, 1), // chunks: make(chan *tlsChunk, 1),
progress: &api.ReadProgress{}, // progress: &api.ReadProgress{},
tcpID: &tcpid, // tcpID: &tcpid,
isClient: true, // isClient: true,
captureTime: time.Now(), // captureTime: time.Now(),
extension: p.extension, // extension: p.extension,
emitter: tlsEmitter, // emitter: tlsEmitter,
counterPair: &api.CounterPair{}, // counterPair: &api.CounterPair{},
reqResMatcher: p.extension.Dissector.NewResponseRequestMatcher(), // reqResMatcher: p.extension.Dissector.NewResponseRequestMatcher(),
} // }
stream := &tlsStream{ // stream := &tlsStream{
reader: reader, // reader: reader,
} // }
streamsMap.Store(streamsMap.NextId(), stream) // streamsMap.Store(streamsMap.NextId(), stream)
reader.parent = stream // reader.parent = stream
err := p.extension.Dissector.Dissect(bufio.NewReader(bytes.NewReader(connection.Request)), reader, options) // err := p.extension.Dissector.Dissect(bufio.NewReader(bytes.NewReader(connection.Requests[0])), reader, options)
if err != nil { // if err != nil {
logger.Log.Warningf("Error dissecting TLS %v - %v", reader.GetTcpID(), err) // logger.Log.Warningf("Error dissecting TLS %v - %v", reader.GetTcpID(), err)
} // }
reader.isClient = false // reader.isClient = false
reader.tcpID = &api.TcpID{ // reader.tcpID = &api.TcpID{
SrcIP: reader.tcpID.DstIP, // SrcIP: reader.tcpID.DstIP,
DstIP: reader.tcpID.SrcIP, // DstIP: reader.tcpID.SrcIP,
SrcPort: reader.tcpID.DstPort, // SrcPort: reader.tcpID.DstPort,
DstPort: reader.tcpID.SrcPort, // DstPort: reader.tcpID.SrcPort,
} // }
reader.progress = &api.ReadProgress{} // reader.progress = &api.ReadProgress{}
err = p.extension.Dissector.Dissect(bufio.NewReader(bytes.NewReader(connection.Response)), reader, options) // err = p.extension.Dissector.Dissect(bufio.NewReader(bytes.NewReader(connection.Responses[0])), reader, options)
if err != nil { // if err != nil {
logger.Log.Warningf("Error dissecting TLS %v - %v", reader.GetTcpID(), err) // logger.Log.Warningf("Error dissecting TLS %v - %v", reader.GetTcpID(), err)
// }
} }
} }
} }

View File

@ -108,6 +108,7 @@ type tlsTapperMapSpecs struct {
GolangDialToSocket *ebpf.MapSpec `ebpf:"golang_dial_to_socket"` GolangDialToSocket *ebpf.MapSpec `ebpf:"golang_dial_to_socket"`
GolangReadWrites *ebpf.MapSpec `ebpf:"golang_read_writes"` GolangReadWrites *ebpf.MapSpec `ebpf:"golang_read_writes"`
GolangSocketToWrite *ebpf.MapSpec `ebpf:"golang_socket_to_write"` GolangSocketToWrite *ebpf.MapSpec `ebpf:"golang_socket_to_write"`
GolangWriteToGzip *ebpf.MapSpec `ebpf:"golang_write_to_gzip"`
Heap *ebpf.MapSpec `ebpf:"heap"` Heap *ebpf.MapSpec `ebpf:"heap"`
LogBuffer *ebpf.MapSpec `ebpf:"log_buffer"` LogBuffer *ebpf.MapSpec `ebpf:"log_buffer"`
PidsMap *ebpf.MapSpec `ebpf:"pids_map"` PidsMap *ebpf.MapSpec `ebpf:"pids_map"`
@ -141,6 +142,7 @@ type tlsTapperMaps struct {
GolangDialToSocket *ebpf.Map `ebpf:"golang_dial_to_socket"` GolangDialToSocket *ebpf.Map `ebpf:"golang_dial_to_socket"`
GolangReadWrites *ebpf.Map `ebpf:"golang_read_writes"` GolangReadWrites *ebpf.Map `ebpf:"golang_read_writes"`
GolangSocketToWrite *ebpf.Map `ebpf:"golang_socket_to_write"` GolangSocketToWrite *ebpf.Map `ebpf:"golang_socket_to_write"`
GolangWriteToGzip *ebpf.Map `ebpf:"golang_write_to_gzip"`
Heap *ebpf.Map `ebpf:"heap"` Heap *ebpf.Map `ebpf:"heap"`
LogBuffer *ebpf.Map `ebpf:"log_buffer"` LogBuffer *ebpf.Map `ebpf:"log_buffer"`
PidsMap *ebpf.Map `ebpf:"pids_map"` PidsMap *ebpf.Map `ebpf:"pids_map"`
@ -157,6 +159,7 @@ func (m *tlsTapperMaps) Close() error {
m.GolangDialToSocket, m.GolangDialToSocket,
m.GolangReadWrites, m.GolangReadWrites,
m.GolangSocketToWrite, m.GolangSocketToWrite,
m.GolangWriteToGzip,
m.Heap, m.Heap,
m.LogBuffer, m.LogBuffer,
m.PidsMap, m.PidsMap,

Binary file not shown.

View File

@ -108,6 +108,7 @@ type tlsTapperMapSpecs struct {
GolangDialToSocket *ebpf.MapSpec `ebpf:"golang_dial_to_socket"` GolangDialToSocket *ebpf.MapSpec `ebpf:"golang_dial_to_socket"`
GolangReadWrites *ebpf.MapSpec `ebpf:"golang_read_writes"` GolangReadWrites *ebpf.MapSpec `ebpf:"golang_read_writes"`
GolangSocketToWrite *ebpf.MapSpec `ebpf:"golang_socket_to_write"` GolangSocketToWrite *ebpf.MapSpec `ebpf:"golang_socket_to_write"`
GolangWriteToGzip *ebpf.MapSpec `ebpf:"golang_write_to_gzip"`
Heap *ebpf.MapSpec `ebpf:"heap"` Heap *ebpf.MapSpec `ebpf:"heap"`
LogBuffer *ebpf.MapSpec `ebpf:"log_buffer"` LogBuffer *ebpf.MapSpec `ebpf:"log_buffer"`
PidsMap *ebpf.MapSpec `ebpf:"pids_map"` PidsMap *ebpf.MapSpec `ebpf:"pids_map"`
@ -141,6 +142,7 @@ type tlsTapperMaps struct {
GolangDialToSocket *ebpf.Map `ebpf:"golang_dial_to_socket"` GolangDialToSocket *ebpf.Map `ebpf:"golang_dial_to_socket"`
GolangReadWrites *ebpf.Map `ebpf:"golang_read_writes"` GolangReadWrites *ebpf.Map `ebpf:"golang_read_writes"`
GolangSocketToWrite *ebpf.Map `ebpf:"golang_socket_to_write"` GolangSocketToWrite *ebpf.Map `ebpf:"golang_socket_to_write"`
GolangWriteToGzip *ebpf.Map `ebpf:"golang_write_to_gzip"`
Heap *ebpf.Map `ebpf:"heap"` Heap *ebpf.Map `ebpf:"heap"`
LogBuffer *ebpf.Map `ebpf:"log_buffer"` LogBuffer *ebpf.Map `ebpf:"log_buffer"`
PidsMap *ebpf.Map `ebpf:"pids_map"` PidsMap *ebpf.Map `ebpf:"pids_map"`
@ -157,6 +159,7 @@ func (m *tlsTapperMaps) Close() error {
m.GolangDialToSocket, m.GolangDialToSocket,
m.GolangReadWrites, m.GolangReadWrites,
m.GolangSocketToWrite, m.GolangSocketToWrite,
m.GolangWriteToGzip,
m.Heap, m.Heap,
m.LogBuffer, m.LogBuffer,
m.PidsMap, m.PidsMap,

Binary file not shown.