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

test(drivers): add some tests for ia32 syscalls #1872

Merged
merged 1 commit into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions test/drivers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ set(DRIVERS_TEST_DEPENDECIES
## IA32 tests are only available on x86_64
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64" AND ENABLE_IA32_TESTS)
add_executable(ia32 ./helpers/ia32.c)
target_include_directories(ia32 PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
set_target_properties(ia32 PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
set(DRIVERS_TEST_DEPENDECIES
${DRIVERS_TEST_DEPENDECIES}
Expand All @@ -66,5 +67,3 @@ add_executable(drivers_test ${DRIVERS_TEST_SOURCES})
target_include_directories(drivers_test ${DRIVERS_TEST_INCLUDE})
target_link_libraries(drivers_test ${DRIVERS_TEST_LINK_LIBRARIES})
add_dependencies(drivers_test ${DRIVERS_TEST_DEPENDECIES})


158 changes: 147 additions & 11 deletions test/drivers/helpers/ia32.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#include <sys/socket.h>
#include <sys/mman.h>
#include <linux/net.h> /* Definition of SYS_* constants */
#include <arpa/inet.h>
#include <errno.h>
#include <event_class/network_utils.h>

#ifdef __NR_openat2
#include <linux/openat2.h> /* Definition of RESOLVE_* constants */
Expand Down Expand Up @@ -63,32 +66,165 @@ int main(int argc, char** argv)
syscall(__NR_socketcall, -1, args);
return 0;
}

if(argc != 2)
else if(argc == 2)
{
fprintf(stderr, "we need exactly one single arg\n");
return -1;
}

#ifdef __NR_write
TRY_SYSCALL(__NR_write, 17, NULL, 1013)
TRY_SYSCALL(__NR_write, 17, NULL, 1013)
#endif

#ifdef __NR_clock_gettime
TRY_SYSCALL(__NR_clock_gettime, 0, NULL)
TRY_SYSCALL(__NR_clock_gettime, 0, NULL)
#endif

#ifdef __NR_getcpu
TRY_SYSCALL(__NR_getcpu, NULL, NULL, NULL)
TRY_SYSCALL(__NR_getcpu, NULL, NULL, NULL)
#endif

#ifdef __NR_gettimeofday
TRY_SYSCALL(__NR_gettimeofday, NULL, NULL)
TRY_SYSCALL(__NR_gettimeofday, NULL, NULL)
#endif

#ifdef __NR_time
TRY_SYSCALL(__NR_time, NULL)
TRY_SYSCALL(__NR_time, NULL)
#endif
}
else if(argc == 3)
{
/* This if case is used to manage socketcall, we look at argv[2] in this case */

// Create sockets
int32_t server_socket_fd = syscall(__NR_socket, AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
if(server_socket_fd == -1)
{
fprintf(stderr, "socket server failed\n");
return -1;
}
int32_t client_socket_fd = syscall(__NR_socket, AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
if(client_socket_fd == -1)
{
fprintf(stderr, "socket client failed\n");
return -1;
}

// Reuse address and port
int option_value = 1;
if(syscall(__NR_setsockopt, server_socket_fd, SOL_SOCKET, SO_REUSEADDR, &option_value,
sizeof(option_value)) == -1)
{
fprintf(stderr, "setsockopt (server addr) failed\n");
return -1;
}
if(syscall(__NR_setsockopt, server_socket_fd, SOL_SOCKET, SO_REUSEPORT, &option_value,
sizeof(option_value)) == -1)
{
fprintf(stderr, "setsockopt (server port) failed\n");
return -1;
}
if(syscall(__NR_setsockopt, client_socket_fd, SOL_SOCKET, SO_REUSEADDR, &option_value,
sizeof(option_value)) == -1)
{
fprintf(stderr, "setsockopt (client addr) failed\n");
return -1;
}
if(syscall(__NR_setsockopt, client_socket_fd, SOL_SOCKET, SO_REUSEPORT, &option_value,
sizeof(option_value)) == -1)
{
fprintf(stderr, "setsockopt (client port) failed\n");
return -1;
}

// populate info
struct sockaddr_in client_addr = {0};
struct sockaddr_in server_addr = {0};

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(IPV4_PORT_SERVER);
if(inet_pton(AF_INET, IPV4_SERVER, &(server_addr.sin_addr)) == -1)
{
fprintf(stderr, "inet_pton server failed\n");
return -1;
}

client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(IPV4_PORT_CLIENT);
if(inet_pton(AF_INET, IPV4_CLIENT, &(client_addr.sin_addr)) == -1)
{
fprintf(stderr, "inet_pton client failed\n");
return -1;
}

// Now we bind the server socket with the server address.
if(syscall(__NR_bind, server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1)
{
fprintf(stderr, "bind (server) failed\n");
return -1;
}

if(syscall(__NR_listen, server_socket_fd, QUEUE_LENGTH) == -1)
{
fprintf(stderr, "listen failed\n");
return -1;
}

// We need to bind the client socket with an address otherwise we cannot assert against it.
if(syscall(__NR_bind, client_socket_fd, (struct sockaddr*)&client_addr, sizeof(client_addr)) == -1)
{
fprintf(stderr, "bind (client) failed\n");
return -1;
}

// The connection will be inprogress so we don't check the errno.
syscall(__NR_connect, client_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));

#ifdef __NR_socketcall
if(strncmp("__NR_accept", argv[2], sizeof("__NR_accept")) == 0)
{
uint32_t args[3] = {0};
args[0] = server_socket_fd;
args[1] = 0;
args[2] = 0;

int connected_socket_fd = syscall(__NR_socketcall, SYS_ACCEPT, (uint32_t*)args);
if(connected_socket_fd == -1)
{
fprintf(stderr, "accept (server) failed\n");
return -1;
}
syscall(__NR_shutdown, connected_socket_fd, 2);
syscall(__NR_close, connected_socket_fd);
}

if(strncmp("__NR_sendto", argv[2], sizeof("__NR_sendto")) == 0)
{
char sent_data[NO_SNAPLEN_MESSAGE_LEN] = NO_SNAPLEN_MESSAGE;
uint32_t sendto_flags = 0;

unsigned long args[6] = {0};
args[0] = client_socket_fd;
args[1] = (unsigned long)sent_data;
args[2] = sizeof(sent_data);
args[3] = sendto_flags;
args[4] = (unsigned long)&server_addr;
args[5] = sizeof(server_addr);
int64_t sent_bytes = syscall(__NR_socketcall, SYS_SENDTO, args);
if(sent_bytes == -1)
{
fprintf(stderr, "sendto failed\n");
return -1;
}
}
#endif
syscall(__NR_shutdown, server_socket_fd, 2);
syscall(__NR_shutdown, client_socket_fd, 2);
syscall(__NR_close, server_socket_fd);
syscall(__NR_close, client_socket_fd);
return 0;
}
else
{
fprintf(stderr, "wrong number of args\n");
return -1;
}

fprintf(stderr, "not managed syscall: '%s'\n", argv[1]);
return -1;
Expand Down
123 changes: 123 additions & 0 deletions test/drivers/test_suites/actions_suite/ia32.cpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -652,4 +652,127 @@ TEST(Actions, ia32_time)
}
#endif

#ifdef __NR_accept
TEST(Actions, ia32_socketcall_accept)
{
auto evt_test = get_syscall_event_test(__NR_accept, EXIT_EVENT);

evt_test->enable_capture();

/*=============================== TRIGGER SYSCALL ===========================*/
pid_t ret_pid = syscall(__NR_fork);
if(ret_pid == 0)
{
const char* argv[] = {"ia32", "__NR_socketcall","__NR_accept", NULL};
const char* envp[] = {NULL};
syscall(__NR_execve, "${CMAKE_CURRENT_BINARY_DIR}/ia32", argv, envp);
exit(EXIT_FAILURE);
}
assert_syscall_state(SYSCALL_SUCCESS, "fork", ret_pid, NOT_EQUAL, -1);
int status = 0;
int options = 0;
assert_syscall_state(SYSCALL_SUCCESS, "wait4", syscall(__NR_wait4, ret_pid, &status, options, NULL), NOT_EQUAL,
-1);

if(__WEXITSTATUS(status) == EXIT_FAILURE || __WIFSIGNALED(status) != 0)
{
FAIL() << "Fork failed..." << std::endl;
}

/* Disable the capture: no more events from now. */
evt_test->disable_capture();

/* Retrieve events in order. */
evt_test->assert_event_presence(ret_pid, PPME_SOCKET_ACCEPT_5_X);

if(HasFatalFailure())
{
return;
}

evt_test->parse_event();
evt_test->assert_header();

/*=============================== ASSERT PARAMETERS ===========================*/


/* Parameter 1: fd (type: PT_FD) */
evt_test->assert_numeric_param(1, (int64_t)0, GREATER_EQUAL);

/* Parameter 2: tuple (type: PT_SOCKTUPLE) */
/* The server performs an `accept` so the `client` is the src. */
evt_test->assert_tuple_inet_param(2, PPM_AF_INET, IPV4_CLIENT, IPV4_SERVER, IPV4_PORT_CLIENT_STRING, IPV4_PORT_SERVER_STRING);

/* Parameter 3: queuepct (type: PT_UINT8) */
/* we expect 0 elements in the queue so 0%. */
evt_test->assert_numeric_param(3, (uint8_t)0);

/* Parameter 4: queuelen (type: PT_UINT32) */
/* we expect 0 elements. */
evt_test->assert_numeric_param(4, (uint32_t)0);

/* Parameter 5: queuemax (type: PT_UINT32) */
evt_test->assert_numeric_param(5, (uint32_t)QUEUE_LENGTH);

/*=============================== ASSERT PARAMETERS ===========================*/

evt_test->assert_num_params_pushed(5);
}
#endif

#ifdef __NR_sendto
TEST(Actions, ia32_socketcall_sendto)
{
auto evt_test = get_syscall_event_test(__NR_sendto, EXIT_EVENT);

evt_test->enable_capture();

/*=============================== TRIGGER SYSCALL ===========================*/
pid_t ret_pid = syscall(__NR_fork);
if(ret_pid == 0)
{
const char* argv[] = {"ia32", "__NR_socketcall","__NR_sendto", NULL};
const char* envp[] = {NULL};
syscall(__NR_execve, "${CMAKE_CURRENT_BINARY_DIR}/ia32", argv, envp);
exit(EXIT_FAILURE);
}
assert_syscall_state(SYSCALL_SUCCESS, "fork", ret_pid, NOT_EQUAL, -1);
int status = 0;
int options = 0;
assert_syscall_state(SYSCALL_SUCCESS, "wait4", syscall(__NR_wait4, ret_pid, &status, options, NULL), NOT_EQUAL,
-1);

if(__WEXITSTATUS(status) == EXIT_FAILURE || __WIFSIGNALED(status) != 0)
{
FAIL() << "Fork failed..." << std::endl;
}

/* Disable the capture: no more events from now. */
evt_test->disable_capture();

/* Retrieve events in order. */
evt_test->assert_event_presence(ret_pid, PPME_SOCKET_SENDTO_X);

if(HasFatalFailure())
{
return;
}

evt_test->parse_event();
evt_test->assert_header();

/*=============================== ASSERT PARAMETERS ===========================*/

/* Parameter 1: res (type: PT_ERRNO) */
evt_test->assert_numeric_param(1, (int64_t)NO_SNAPLEN_MESSAGE_LEN);

/* Parameter 2: data (type: PT_BYTEBUF) */
evt_test->assert_bytebuf_param(2, NO_SNAPLEN_MESSAGE, NO_SNAPLEN_MESSAGE_LEN);

/*=============================== ASSERT PARAMETERS ===========================*/

evt_test->assert_num_params_pushed(2);
}
#endif

#endif
Loading