Skip to content

Commit

Permalink
fixed ebpf
Browse files Browse the repository at this point in the history
Signed-off-by: Afek Berger <[email protected]>
  • Loading branch information
afek854 committed Mar 4, 2025
1 parent 200343a commit 1031fbb
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 35 deletions.
46 changes: 31 additions & 15 deletions pkg/ebpf/gadgets/http/tracer/bpf/http-sniffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ struct {
__type(value, char[PACKET_CHUNK_SIZE]);
} empty_char SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, __u32);
__type(value, u8[MAX_DATAEVENT_BUFFER]);
} empty_buffer SEC(".maps");


// Declared to avoid compiler deletion
const struct httpevent *unusedevent __attribute__((unused));

Expand All @@ -80,6 +88,22 @@ static __always_inline int should_discard()
return 0;
}

static __always_inline struct httpevent *get_dataevent()
{
__u32 zero = 0;
struct httpevent *dataevent = bpf_map_lookup_elem(&event_data, &zero);
if (!dataevent)
return NULL;

u8 *empty = bpf_map_lookup_elem(&empty_buffer, &zero);
if (empty) {
bpf_probe_read(dataevent->buf, sizeof(dataevent->buf), empty);
bpf_probe_read(dataevent->syscall, sizeof(dataevent->syscall), empty);
}

return dataevent;
}

static __always_inline __u64 min_size(__u64 a, __u64 b) {
return a < b ? a : b;
}
Expand Down Expand Up @@ -251,23 +275,17 @@ static __always_inline int get_http_type(struct trace_event_raw_sys_exit *ctx, v
static __always_inline int process_packet(struct trace_event_raw_sys_exit *ctx, char *syscall)
{
__u64 id = bpf_get_current_pid_tgid();
char buf[PACKET_CHUNK_SIZE] = {0};
__u32 total_size = (__u32)ctx->ret;

struct packet_buffer *packet = bpf_map_lookup_elem(&buffer_packets, &id);
if (!packet)
return 0;

if (ctx->ret <= 0)
return 0;

__u32 total_size = (__u32)ctx->ret;
__u32 key = 0;

if (total_size < 1)
{
return 0;
}

char *buf = bpf_map_lookup_elem(&empty_char, &key);
if (!buf)
return 0;

if (packet->len < 1)
Expand All @@ -281,8 +299,7 @@ static __always_inline int process_packet(struct trace_event_raw_sys_exit *ctx,
if (!type)
return 0;

__u32 zero = 0;
struct httpevent *dataevent = bpf_map_lookup_elem(&event_data, &zero);
struct httpevent *dataevent = get_dataevent();
if (!dataevent)
return 0;

Expand Down Expand Up @@ -366,10 +383,9 @@ static __always_inline int process_msg(struct trace_event_raw_sys_exit *ctx, cha
if (type)
{
seg_len = iov.iov_len;
__u32 zero = 0;
struct httpevent *dataevent = bpf_map_lookup_elem(&event_data, &zero);
struct httpevent *dataevent = get_dataevent();
if (!dataevent)
continue;
return 0;

populate_httpevent(dataevent);
enrich_ip_port(ctx, msg->fd, dataevent);
Expand All @@ -380,7 +396,7 @@ static __always_inline int process_msg(struct trace_event_raw_sys_exit *ctx, cha
if (copy_len > MAX_DATAEVENT_BUFFER)
copy_len = MAX_DATAEVENT_BUFFER;

bpf_probe_read(dataevent->buf, copy_len, buffer);
bpf_probe_read(&dataevent->buf, copy_len, iov.iov_base);
bpf_probe_read_str(&dataevent->syscall, sizeof(dataevent->syscall), syscall);
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, dataevent, sizeof(*dataevent));
break;
Expand Down
3 changes: 3 additions & 0 deletions pkg/ebpf/gadgets/http/tracer/http_sniffer_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified pkg/ebpf/gadgets/http/tracer/http_sniffer_bpfel.o
Binary file not shown.
70 changes: 52 additions & 18 deletions pkg/ebpf/gadgets/http/tracer/httpparse.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func CreateEventFromRequest(bpfEvent *http_snifferHttpevent) (*tracerhttptype.Ev
ip := make(net.IP, 4)
binary.LittleEndian.PutUint32(ip, bpfEvent.OtherIp)

request, err := ParseHTTPRequest(FromCString(bpfEvent.Buf[:]))
request, err := ParseHttpRequest(FromCString(bpfEvent.Buf[:]))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -50,12 +50,12 @@ func CreateEventFromRequest(bpfEvent *http_snifferHttpevent) (*tracerhttptype.Ev
return &event, nil
}

func ParseHTTPRequest(data []byte) (*http.Request, error) {
func ParseHttpRequest(data []byte) (*http.Request, error) {
bufReader := bufio.NewReader(bytes.NewReader(data))

req, err := http.ReadRequest(bufReader)
if err != nil {
return nil, err
return fallbackReadRequest(data)
}

body, err := io.ReadAll(req.Body)
Expand All @@ -70,22 +70,10 @@ func ParseHTTPRequest(data []byte) (*http.Request, error) {
return req, nil
}

func ParseHTTPResponse(data []byte, req *http.Request) (*http.Response, error) {
bufReader := bufio.NewReader(bytes.NewReader(PatchHTTPPacket(data)))

resp, err := http.ReadResponse(bufReader, req)
func ParseHttpResponse(data []byte, req *http.Request) (*http.Response, error) {
resp, err := readResponse(data, req)
if err != nil {
lastNewline := bytes.LastIndex(data, []byte("\n"))
if lastNewline != -1 {
cleanedData := data[:lastNewline+1]
bufReader = bufio.NewReader(bytes.NewReader(PatchHTTPPacket(cleanedData)))
resp, err = http.ReadResponse(bufReader, req)
if err != nil {
return nil, fmt.Errorf("failed to read response even after removing last line: %w", err)
}
return resp, nil
}
return nil, fmt.Errorf("failed to read response: %w", err)
return fallbackReadResponse(data, req)
}

return resp, nil
Expand Down Expand Up @@ -144,3 +132,49 @@ func PatchHTTPPacket(data []byte) []byte {

return append(data, []byte("\r\n\r\n")...)
}

func fallbackReadRequest(data []byte) (*http.Request, error) {
cleanedData, err := cleanCorrupted(data)
if err != nil {
return nil, fmt.Errorf("failed to clean request data: %w", err)
}

bufReader := bufio.NewReader(bytes.NewReader(PatchHTTPPacket(cleanedData)))
req, err := http.ReadRequest(bufReader)
if err != nil {
return nil, fmt.Errorf("failed to read request even after removing last line: %w", err)
}

return req, nil
}

func fallbackReadResponse(data []byte, req *http.Request) (*http.Response, error) {
cleanedData, err := cleanCorrupted(data)
if err != nil {
return nil, fmt.Errorf("failed to clean response data: %w", err)
}

resp, err := readResponse(cleanedData, req)
if err != nil {
return nil, fmt.Errorf("failed to read response even after removing last line: %w", err)
}

return resp, nil
}

func readResponse(data []byte, req *http.Request) (*http.Response, error) {
bufReader := bufio.NewReader(bytes.NewReader(PatchHTTPPacket(data)))
resp, err := http.ReadResponse(bufReader, req)
return resp, err
}

func cleanCorrupted(data []byte) ([]byte, error) {
lastNewline := bytes.LastIndex(data, []byte("\n"))
if lastNewline == -1 {
return nil, fmt.Errorf("failed to find newline in request data")
}

cleanedData := data[:lastNewline+1]

return cleanedData, nil
}
12 changes: 10 additions & 2 deletions pkg/ebpf/gadgets/http/tracer/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/kubescape/go-logger/helpers"
"github.com/kubescape/node-agent/pkg/ebpf/gadgets/http/types"
tracepointlib "github.com/kubescape/node-agent/pkg/ebpf/lib"
"github.com/kubescape/storage/pkg/apis/softwarecomposition/consts"
)

//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -strip /usr/bin/llvm-strip-18 -cc /usr/bin/clang -no-global-types -target bpfel -cc clang -cflags "-g -O2 -Wall" -type active_connection_info -type packet_buffer -type httpevent http_sniffer bpf/http-sniffer.c -- -I./bpf/
Expand Down Expand Up @@ -164,8 +165,15 @@ func (t *Tracer) Run(gadgetCtx gadgets.GadgetContext) error {

func (t *Tracer) GroupEvents(bpfEvent *http_snifferHttpevent) *types.Event {
eventType := types.HTTPDataType(bpfEvent.Type)
syscall := gadgets.FromCString(bpfEvent.Syscall[:])
direction, err := types.GetPacketDirection(syscall)
if err != nil {
logger.L().Debug("http Tracer.GroupEvents - error getting packet direction", helpers.Error(err),
helpers.String("syscall", syscall))
return nil
}

if eventType == types.Request {
if eventType == types.Request && direction == consts.Inbound {
event, err := CreateEventFromRequest(bpfEvent)
if err != nil {
msg := fmt.Sprintf("Error parsing request: %s", err)
Expand All @@ -176,7 +184,7 @@ func (t *Tracer) GroupEvents(bpfEvent *http_snifferHttpevent) *types.Event {
} else if eventType == types.Response {
if exists, ok := t.eventsMap.Get(GetUniqueIdentifier(bpfEvent)); ok {
grouped := exists
response, err := ParseHTTPResponse(FromCString(bpfEvent.Buf[:]), grouped.Request)
response, err := ParseHttpResponse(FromCString(bpfEvent.Buf[:]), grouped.Request)
if err != nil {
msg := fmt.Sprintf("Error parsing response: %s", err)
t.eventCallback(types.Base(eventtypes.Warn(msg)))
Expand Down

0 comments on commit 1031fbb

Please sign in to comment.