google / sandboxed-api

Generate sandboxes for C/C++ libraries automatically
https://developers.google.com/sandboxed-api/
Apache License 2.0
1.66k stars 191 forks source link

`gethostbyname()` fails #168

Open gbryant-arm opened 1 year ago

gbryant-arm commented 1 year ago

Hi!

I'm trying to run this simple socket example in sandbox2:

#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <arpa/inet.h>
#include <netdb.h> /* getprotobyname */
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>

extern int h_errno;

int main(int argc, char **argv) {
    char *server_hostname = "localhost";
    unsigned short server_port = 443;
    char buffer[BUFSIZ];
    char *user_input = "";
    in_addr_t in_addr;
    in_addr_t server_addr;
    int sockfd;
    ssize_t nbytes_read, i, user_input_len = 1;
    struct hostent *hostent;
    /* This is the struct used by INet addresses. */
    struct sockaddr_in sockaddr_in;

    if (argc > 1) {
        server_hostname = argv[1];
        if (argc > 2) {
            server_port = strtol(argv[2], NULL, 10);
        }
    }

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    /* Prepare sockaddr_in. */
    hostent = gethostbyname(server_hostname);                           // <-------------- fails here
    if (hostent == NULL) {
        fprintf(stderr, "error: gethostbyname(\"%s\")\n", server_hostname);
        printf("h_errno: %d\n", h_errno);
        exit(EXIT_FAILURE);
    }
    in_addr = inet_addr(inet_ntoa(*(struct in_addr*)*(hostent->h_addr_list)));
    if (in_addr == (in_addr_t)-1) {
        fprintf(stderr, "error: inet_addr(\"%s\")\n", *(hostent->h_addr_list));
        exit(EXIT_FAILURE);
    }

    sockaddr_in.sin_addr.s_addr = in_addr;
    sockaddr_in.sin_family = AF_INET;
    sockaddr_in.sin_port = htons(server_port);

    /* Do the actual connection. */
    if (connect(sockfd, (struct sockaddr*)&sockaddr_in, sizeof(sockaddr_in)) == -1) {
        perror("connect");
        return EXIT_FAILURE;
    }
    if (write(sockfd, user_input, user_input_len) == -1) {
        perror("write");
        exit(EXIT_FAILURE);
    }
    while ((nbytes_read = read(sockfd, buffer, BUFSIZ)) > 0) {
        write(STDOUT_FILENO, buffer, nbytes_read);
    }

    exit(EXIT_SUCCESS);
}

Command: sandbox2tool --sandbox2tool_keep_env --sandbox2tool_mount_tmp --sandbox2tool_resolve_and_add_libraries --sandbox2tool_need_networking a.out Additionally the sandbox is configured to allow all syscalls (DangerDefaultAllowAll()).

I was expecting gethostbyname() to succeed and return a hostent struct containing one or several IP addresses. Instead gethostbyname() fails with h_errno=3 (NO_RECOVERY). Interestingly passing an IP address directly to gethostbyname() instead of localhost doesn't fail.

What am I missing? Cheers