Search code examples
clinux-kernelbpfebpfbcc-bpf

eBPF: How can the sockaddr struct be read when hooking into security_socket_connect


As proposed in the presentation Security Monitoring with eBPF I'm trying to hook into security_socket_connect.

While my gobpf/bcc based code partly works, I seem not be able to read the IP address in the sockaddr struct.

The relevant part looks like this:

int security_socket_connect_entry(struct pt_regs *ctx, struct socket *sock, struct sockaddr *address, int addrlen)
{    
    u32 address_family = address->sa_family;
    if (address_family == AF_INET) {
        struct ipv4_data_t data4 = {.pid = pid};

        struct sockaddr_in *addr2 = (struct sockaddr_in *)address;

After that I try to read the IP address in addr2. The first try was:

data4.daddr = addr2->sin_addr.s_addr;

The second try was with bpf_probe_read:

bpf_probe_read(&data4.daddr, sizeof(data4.daddr), (void *)((long)addr2->sin_addr.s_addr));

Both options present the same error:

R9 invalid mem access 'inv'

HINT: The invalid mem access 'inv' error can happen if you try to dereference memory without first using bpf_probe_read() to copy it to the BPF stack. Sometimes the bpf_probe_read is automatic by the bcc rewriter, other times you'll need to be explicit. 

A repo with a buildable sample can be found here: socket-connect-bpf


Solution

  • I figured it out thanks to an answer to issue #1858 in the bcc repo.

    We have to operate on the pointer, so the IP address can be read like this:

    bpf_probe_read(&data4.daddr, sizeof(data4.daddr), &addr2->sin_addr.s_addr);