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

Incorrect handling of binding a socket to an already bound address (ql_syscall_bind) #1476

Closed
carter-yagemann opened this issue Jun 20, 2024 · 1 comment · Fixed by #1448
Closed

Comments

@carter-yagemann
Copy link

Describe the bug

In Linux, when a target program binds a socket that is already bound, the OS should return an error code indicating that the address is already in use and the target program should proceed, but in Qiling an uncaught except is raised and execution is stopped, which is unexpected and undesired behavior.

Sample Code

Target Program Source Code: (adapted from man bind)

/* test.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#define MY_SOCK_PATH "/tmp/testsocket"
#define LISTEN_BACKLOG 50

#define handle_error(msg) \
  do { perror(msg); exit(EXIT_FAILURE); } while (0)

int
main(void)
{
    int                 sfd, cfd;
    socklen_t           peer_addr_size;
    struct sockaddr_un  my_addr, peer_addr;

    sfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sfd == -1)
        handle_error("socket");

    memset(&my_addr, 0, sizeof(my_addr));
    my_addr.sun_family = AF_UNIX;
    strncpy(my_addr.sun_path, MY_SOCK_PATH,
        sizeof(my_addr.sun_path) - 1);

    printf("Bind 1\n");
    if (bind(sfd, (struct sockaddr *) &my_addr,
            sizeof(my_addr)) == -1)
        handle_error("bind");

    printf("Bind 2\n");
    if (bind(sfd, (struct sockaddr *) &my_addr,
            sizeof(my_addr)) == -1)
        handle_error("bind");

    return 0;
}

Real Execution:

gcc -o test -static test.c
./test
# output:
# Bind 1
# Bind 2
# bind: Address already in use

Qiling Emulation:

import qiling
ql = qiling.Qiling(["./root_fs/test"], "./root_fs")
ql.run()

[x] Syscall ERROR: ql_syscall_bind DEBUG: [Errno 98] Address already in use
Traceback (most recent call last):
File "/env/lib/python3.11/site-packages/qiling/os/posix/posix.py", line 374, in load_syscall
retval = syscall_hook(self.ql, *params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/env/lib/python3.11/site-packages/qiling/os/posix/syscall/socket.py", line 433, in ql_syscall_bind
sock.bind(dest)
File "/env/lib/python3.11/site-packages/qiling/os/posix/filestruct.py", line 83, in bind
return self.__socket.bind(address)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: [Errno 98] Address already in use

Expected behavior
Qiling should correctly handle the case where the host OS returns an "Address already in use" error and return the proper return value to the target program. Many programs use the behavior like in test.c to check for already running instances of the program.

Screenshots
N/A

Additional context
N/A

@elicn elicn linked a pull request Jun 28, 2024 that will close this issue
@elicn
Copy link
Member

elicn commented Jul 2, 2024

Hi @carter-yagemann,
A fix has been committed to dev branch. I am tentatively closing the issue now.
Feel free to check out the updated code and re-open this issue if the problem persists.

@elicn elicn closed this as completed Jul 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants