From 74b4ce08693db23d952e5a9ddb941a2adb971312 Mon Sep 17 00:00:00 2001 From: Vladimir Stoilov Date: Fri, 23 Jun 2023 16:41:21 +0300 Subject: [PATCH] Make default pid to be -1 and remove unsafe code --- .../interception/ebpf/bandwidth/interface.go | 27 ++++++++----- .../ebpf/connection_listener/worker.go | 40 ++++++++++++++----- process/find.go | 1 + 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/firewall/interception/ebpf/bandwidth/interface.go b/firewall/interception/ebpf/bandwidth/interface.go index 3930a45e..cd85572d 100644 --- a/firewall/interception/ebpf/bandwidth/interface.go +++ b/firewall/interception/ebpf/bandwidth/interface.go @@ -1,17 +1,17 @@ package ebpf import ( + "encoding/binary" "fmt" "net" "path/filepath" "syscall" - "time" - "unsafe" "github.com/cilium/ebpf" "github.com/cilium/ebpf/link" "github.com/cilium/ebpf/rlimit" "github.com/safing/portbase/log" + "github.com/safing/portmaster/network/packet" "golang.org/x/sys/unix" ) @@ -28,6 +28,7 @@ var ebpfInterface = struct { objs: bpfObjects{}, } +// SetupBandwidthInterface initializes the ebpf interface and starts gattering bandwidth information for all connections. func SetupBandwidthInterface() error { // Allow the current process to lock memory for eBPF resources. @@ -141,6 +142,7 @@ func ShutdownBandwithInterface() { ebpfInterface.objs.Close() } +// findCgroupPath returns the default unified path of the cgroup func findCgroupPath() (string, error) { cgroupPath := "/sys/fs/cgroup" @@ -156,24 +158,31 @@ func findCgroupPath() (string, error) { return cgroupPath, nil } +// printBandwidthData prints the contencs of the shared map in the ebpf program. func printBandwidthData() { iter := ebpfInterface.objs.bpfMaps.PmBandwidthMap.Iterate() var skKey bpfSkKey var skInfo bpfSkInfo for iter.Next(&skKey, &skInfo) { log.Debugf("Connection: %d %s:%d %s:%d %d %d", skKey.Protocol, - arrayToIP(skKey.SrcIp, skKey.Ipv6).String(), skKey.SrcPort, - arrayToIP(skKey.DstIp, skKey.Ipv6).String(), skKey.DstPort, + convertArrayToIPv4(skKey.SrcIp, packet.IPVersion(skKey.Ipv6)).String(), skKey.SrcPort, + convertArrayToIPv4(skKey.DstIp, packet.IPVersion(skKey.Ipv6)).String(), skKey.DstPort, skInfo.Rx, skInfo.Tx, ) } } -// arrayToIP converts IP number array to net.IP -func arrayToIP(ipNum [4]uint32, ipv6 uint8) net.IP { - if ipv6 == 0 { - return unsafe.Slice((*byte)(unsafe.Pointer(&ipNum)), 4) +// convertArrayToIPv4 converts an array of uint32 values to an IPv4 net.IP address. +func convertArrayToIPv4(input [4]uint32, ipVersion packet.IPVersion) net.IP { + if ipVersion == packet.IPv4 { + addressBuf := make([]byte, 4) + binary.LittleEndian.PutUint32(addressBuf, input[0]) + return net.IP(addressBuf) } else { - return unsafe.Slice((*byte)(unsafe.Pointer(&ipNum)), 16) + addressBuf := make([]byte, 16) + for i := 0; i < 4; i++ { + binary.LittleEndian.PutUint32(addressBuf[i*4:i*4+4], input[i]) + } + return net.IP(addressBuf) } } diff --git a/firewall/interception/ebpf/connection_listener/worker.go b/firewall/interception/ebpf/connection_listener/worker.go index ba3d9022..c02d948f 100644 --- a/firewall/interception/ebpf/connection_listener/worker.go +++ b/firewall/interception/ebpf/connection_listener/worker.go @@ -5,7 +5,6 @@ import ( "encoding/binary" "errors" "net" - "unsafe" "github.com/cilium/ebpf/link" "github.com/cilium/ebpf/ringbuf" @@ -15,8 +14,10 @@ import ( ) //go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -cflags "-O2 -g -Wall -Werror" -type Event bpf ../programs/monitor.c + var stopper chan struct{} +// StartEBPFWorker starts the ebpf worker. func StartEBPFWorker(ch chan packet.Packet) { stopper = make(chan struct{}) go func() { @@ -32,7 +33,7 @@ func StartEBPFWorker(ch chan packet.Packet) { log.Errorf("ebpf: failed to load ebpf object: %s", err) return } - defer objs.Close() + defer objs.Close() //nolint:errcheck // Create a link to the tcp_connect program. linkTCPConnect, err := link.AttachTracing(link.TracingOptions{ @@ -42,7 +43,7 @@ func StartEBPFWorker(ch chan packet.Packet) { log.Errorf("ebpf: failed to attach to tcp_v4_connect: %s ", err) return } - defer linkTCPConnect.Close() + defer linkTCPConnect.Close() //nolint:errcheck // Create a link to the udp_v4_connect program. linkUDPV4, err := link.AttachTracing(link.TracingOptions{ @@ -52,7 +53,7 @@ func StartEBPFWorker(ch chan packet.Packet) { log.Errorf("ebpf: failed to attach to udp_v4_connect: %s ", err) return } - defer linkUDPV4.Close() + defer linkUDPV4.Close() //nolint:errcheck // Create a link to the udp_v6_connect program. linkUDPV6, err := link.AttachTracing(link.TracingOptions{ @@ -62,7 +63,7 @@ func StartEBPFWorker(ch chan packet.Packet) { log.Errorf("ebpf: failed to attach to udp_v6_connect: %s ", err) return } - defer linkUDPV6.Close() + defer linkUDPV6.Close() //nolint:errcheck rd, err := ringbuf.NewReader(objs.bpfMaps.PmConnectionEvents) if err != nil { @@ -105,8 +106,8 @@ func StartEBPFWorker(ch chan packet.Packet) { Protocol: packet.IPProtocol(event.Protocol), SrcPort: event.Sport, DstPort: event.Dport, - Src: arrayToIP(event.Saddr, packet.IPVersion(event.IpVersion)), - Dst: arrayToIP(event.Daddr, packet.IPVersion(event.IpVersion)), + Src: convertArrayToIPv4(event.Saddr, packet.IPVersion(event.IpVersion)), + Dst: convertArrayToIPv4(event.Daddr, packet.IPVersion(event.IpVersion)), PID: int(event.Pid), } if isEventValid(event) { @@ -123,19 +124,30 @@ func StartEBPFWorker(ch chan packet.Packet) { }() } +// StopEBPFWorker stops the ebpf worker. func StopEBPFWorker() { close(stopper) } +// isEventValid checks whether the given bpfEvent is valid or not. +// It returns true if the event is valid, otherwise false. func isEventValid(event bpfEvent) bool { + // Check if the destination port is 0 if event.Dport == 0 { return false } + // Check if the source port is 0 if event.Sport == 0 { return false } + // Check if the process ID is 0 + if event.Pid == 0 { + return false + } + + // If the IP version is IPv4 if event.IpVersion == 4 { if event.Saddr[0] == 0 { return false @@ -148,11 +160,17 @@ func isEventValid(event bpfEvent) bool { return true } -// arrayToIP converts IP number array to net.IP -func arrayToIP(ipNum [4]uint32, ipVersion packet.IPVersion) net.IP { +// convertArrayToIPv4 converts an array of uint32 values to an IPv4 net.IP address. +func convertArrayToIPv4(input [4]uint32, ipVersion packet.IPVersion) net.IP { if ipVersion == packet.IPv4 { - return unsafe.Slice((*byte)(unsafe.Pointer(&ipNum)), 4) + addressBuf := make([]byte, 4) + binary.LittleEndian.PutUint32(addressBuf, input[0]) + return net.IP(addressBuf) } else { - return unsafe.Slice((*byte)(unsafe.Pointer(&ipNum)), 16) + addressBuf := make([]byte, 16) + for i := 0; i < 4; i++ { + binary.LittleEndian.PutUint32(addressBuf[i*4:i*4+4], input[i]) + } + return net.IP(addressBuf) } } diff --git a/process/find.go b/process/find.go index 41d1459a..881ecc69 100644 --- a/process/find.go +++ b/process/find.go @@ -126,6 +126,7 @@ func GetProcessByRequestOrigin(ar *api.Request) (*Process, error) { Protocol: packet.TCP, Src: remoteIP, // source as in the process we are looking for SrcPort: remotePort, // source as in the process we are looking for + PID: -1, } pid, _, err := GetPidOfConnection(ar.Context(), pkt)