Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle 32-bit socketcall syscall #3707

Closed
wants to merge 4 commits into from

Conversation

geyslan
Copy link
Member

@geyslan geyslan commented Nov 22, 2023

Close: #3676

1. Explain what the PR does

26475aa feat(events): parse call arg for socketcall
59158d5 chore: libbpfgo/helpers bump
ebdd285 fix(ebpf): handle x86 32-bit socketcall syscall
7d3d385 fix(ebpf): 32-bit syscall numbers

59158d5 chore: libbpfgo/helpers bump

Brings in the latest libbpfgo/helpers addition: ParseSocketcallCall().

ebdd285 fix(ebpf): handle x86 32-bit socketcall syscall

The Linux kernel version determines x86 32-bit compatibility: older
versions use 'socketcall' syscall for socket functions (like socket,
bind, connect), while newer versions use individual syscalls directly.

These changes were also tested on an arm64 running an armhf binary.

Context: #3676

2. Explain how to test it

Use this event emitter

Build it for 64 and 32 bits:

gcc conntest.c -o conntest64
gcc -m32 conntest.c -o conntest32

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>

int main() {
    int ret;
    int dummy_fd1, dummy_fd2;
    int sockfd;
    int listen_sock, client_sock;
    struct sockaddr_in server_addr;
    socklen_t addr_len;

    // Open dummy file descriptors to consume 3 and 4
    dummy_fd1 = open("/dev/null", O_RDONLY);
    if (dummy_fd1 < 0) {
        perror("Failed to open dummy file descriptor 1");
        exit(EXIT_FAILURE);
    }

    dummy_fd2 = open("/dev/null", O_RDONLY);
    if (dummy_fd2 < 0) {
        perror("Failed to open dummy file descriptor 2");
        exit(EXIT_FAILURE);
    }

    // Initialize server_addr
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    // Create socket
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    int optval = 1;
    ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
    if (ret < 0) {
        perror("Setsockopt failed");
        exit(EXIT_FAILURE);
    }

    // Bind socket
    ret = bind(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr));
    if (ret < 0) {
        perror("Bind failed");
        exit(EXIT_FAILURE);
    }

    // Connect socket
    ret = connect(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr));
    if (ret < 0) {
        perror("Connect failed");
        exit(EXIT_FAILURE);
    }

    // Create listening socket
    listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_sock < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    // Bind listening socket
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(9090);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    ret = bind(listen_sock, (struct sockaddr *) &server_addr, sizeof(server_addr));
    if (ret < 0) {
        perror("Bind failed");
        close(listen_sock);
        exit(EXIT_FAILURE);
    }

    // Listen on listening socket
    ret = listen(listen_sock, 5);
    if (ret < 0) {
        perror("Listen failed");
        close(listen_sock);
        exit(EXIT_FAILURE);
    }

    // Accept a connection
    addr_len = sizeof(server_addr);
    client_sock = accept(listen_sock, (struct sockaddr *) &server_addr, &addr_len);
    if (client_sock < 0) {
        perror("Accept failed");
        close(listen_sock);
        exit(EXIT_FAILURE);
    }

    close(client_sock);
    close(listen_sock);
    close(sockfd);

    close(dummy_fd1);
    close(dummy_fd2);

    return 0;
}

Run tracee

sudo ./dist/tracee-ebpf -s comm=conntest32,conntest64 -e 'socketcall,socket,setsockopt,bind,connect,listen,accept,security_socket_*' --capabilities bypass=true

Run conntest*

  • Output for 64 bits
TIME             UID    COMM             PID     TID     RET              EVENT                     ARGS
13:24:42:256495  1000   conntest64       226645  226645  0                security_socket_create    family: AF_INET, type: SOCK_STREAM, protocol: 0, kern: 0
13:24:42:256486  1000   conntest64       226645  226645  5                socket                    domain: AF_INET, type: SOCK_STREAM, protocol: 0
13:24:42:256740  1000   conntest64       226645  226645  0                security_socket_setsoc... sockfd: 5, level: SOL_SOCKET, optname: SO_REUSEADDR, local_addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:0]
13:24:42:256734  1000   conntest64       226645  226645  0                setsockopt                sockfd: 5, level: SOL_SOCKET, optname: SO_REUSEADDR, optval: 0x7ffc880b8264, optlen: 4
13:24:42:256863  1000   conntest64       226645  226645  0                security_socket_bind      sockfd: 5, local_addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:8080]
13:24:42:256857  1000   conntest64       226645  226645  0                bind                      sockfd: 5, addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:8080], addrlen: 16
13:24:42:256932  1000   conntest64       226645  226645  0                security_socket_connect   sockfd: 5, remote_addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:8080]
13:24:42:256926  1000   conntest64       226645  226645  0                connect                   sockfd: 5, addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:8080], addrlen: 16
13:24:42:257121  1000   conntest64       226645  226645  0                security_socket_create    family: AF_INET, type: SOCK_STREAM, protocol: 0, kern: 0
13:24:42:257117  1000   conntest64       226645  226645  6                socket                    domain: AF_INET, type: SOCK_STREAM, protocol: 0
13:24:42:257183  1000   conntest64       226645  226645  0                security_socket_bind      sockfd: 6, local_addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:9090]
13:24:42:257179  1000   conntest64       226645  226645  0                bind                      sockfd: 6, addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:9090], addrlen: 16
13:24:42:257240  1000   conntest64       226645  226645  0                security_socket_listen    sockfd: 6, local_addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:9090], backlog: 5
13:24:42:257235  1000   conntest64       226645  226645  0                listen                    sockfd: 6, backlog: 5
13:24:42:257352  1000   conntest64       226645  226645  0                security_socket_accept    sockfd: 6, local_addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:9090]
13:24:42:257331  1000   conntest64       226645  226645  7                accept                    sockfd: 6, addr: map[sa_family:AF_INET sin_addr:127.0.0.1 sin_port:58454], addrlen: 0x7ffc880b8260
  • Output for 32 bits (on kernels which make use of socketcall)
TIME             UID    COMM             PID     TID     RET              EVENT                     ARGS
13:27:36:200148  1000   conntest32       230968  230968  0                security_socket_create    family: AF_INET, type: SOCK_STREAM, protocol: 0, kern: 0
13:27:36:200145  1000   conntest32       230968  230968  5                socketcall                call: SYS_SOCKET, args: 0xffb38fd0
13:27:36:200170  1000   conntest32       230968  230968  0                security_socket_setsoc... sockfd: 5, level: SOL_SOCKET, optname: SO_REUSEADDR, local_addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:0]
13:27:36:200168  1000   conntest32       230968  230968  0                socketcall                call: SYS_SETSOCKOPT, args: 0xffb38fa8
13:27:36:200180  1000   conntest32       230968  230968  0                security_socket_bind      sockfd: 5, local_addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:8080]
13:27:36:200179  1000   conntest32       230968  230968  0                socketcall                call: SYS_BIND, args: 0xffb38fc4
13:27:36:200192  1000   conntest32       230968  230968  0                security_socket_connect   sockfd: 5, remote_addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:8080]
13:27:36:200190  1000   conntest32       230968  230968  0                socketcall                call: SYS_CONNECT, args: 0xffb38fd0
13:27:36:200245  1000   conntest32       230968  230968  0                security_socket_create    family: AF_INET, type: SOCK_STREAM, protocol: 0, kern: 0
13:27:36:200244  1000   conntest32       230968  230968  6                socketcall                call: SYS_SOCKET, args: 0xffb38fd0
13:27:36:200256  1000   conntest32       230968  230968  0                security_socket_bind      sockfd: 6, local_addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:9090]
13:27:36:200254  1000   conntest32       230968  230968  0                socketcall                call: SYS_BIND, args: 0xffb38fc4
13:27:36:200265  1000   conntest32       230968  230968  0                security_socket_listen    sockfd: 6, local_addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:9090], backlog: 5
13:27:36:200263  1000   conntest32       230968  230968  0                socketcall                call: SYS_LISTEN, args: 0xffb38fd4
13:27:36:200275  1000   conntest32       230968  230968  0                security_socket_accept    sockfd: 6, local_addr: map[sa_family:AF_INET sin_addr:0.0.0.0 sin_port:9090]
13:27:36:200273  1000   conntest32       230968  230968  7                socketcall                call: SYS_ACCEPT, args: 0xffb38fd0

3. Other comments

@geyslan geyslan self-assigned this Nov 22, 2023
@geyslan geyslan changed the title fix(ebpf): 32bit syscall numbers fix 32bit syscall numbers translation Nov 22, 2023
@geyslan geyslan changed the title fix 32bit syscall numbers translation handle 32-bit socketcall syscall Nov 23, 2023
@geyslan geyslan marked this pull request as ready for review November 23, 2023 16:08
The Linux kernel version determines x86 32-bit compatibility: older
versions use 'socketcall' syscall for socket functions (like socket,
bind, connect), while newer versions use individual syscalls directly.

These changes were also tested on an arm64 running an armhf binary.

Context: aquasecurity#3676
Brings in the latest libbpfgo/helpers addition: ParseSocketcallCall().
@rafaeldtinoco
Copy link
Contributor

Good job. Thanks and Im merging this at #3709 because of a minor chore fix on the syscall header declaration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants