Skip to content

Commit

Permalink
Test for overflow reading proc IPv4 buffer.
Browse files Browse the repository at this point in the history
  • Loading branch information
shane-lawrence committed Feb 5, 2025
1 parent ecaa17f commit dd4443c
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 2 deletions.
20 changes: 18 additions & 2 deletions test/libscap/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,26 @@ set(LIBSCAP_TESTS_LIBRARIES "${GTEST_LIB}" "${GTEST_MAIN_LIB}" "${CMAKE_THREAD_L
set(LIBSCAP_TESTS_DEPENDENCIES gtest scap)

# Test suite asserting against pure userspace components
file(GLOB_RECURSE USERSPACE_TEST_SUITE "${CMAKE_CURRENT_SOURCE_DIR}/test_suites/userspace/*.cpp")
file(GLOB_RECURSE USERSPACE_TEST_SUITE
"${CMAKE_CURRENT_SOURCE_DIR}/test_suites/userspace/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/test_suites/userspace/*.c"
)
set(LIBSCAP_TESTS_SOURCES ${USERSPACE_TEST_SUITE})

# Add _GNU_SOURCE definition for makedev and set C flags
add_definitions(-D_GNU_SOURCE)
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/test_suites/userspace/linux/scap_fds_impl.c
PROPERTIES
COMPILE_FLAGS "-D_GNU_SOURCE -include sys/sysmacros.h"
COMPILE_DEFINITIONS "HAVE_SYS_SYSMACROS_H"
)

# Add scap_engine_util for Linux tests
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
list(APPEND LIBSCAP_TESTS_LIBRARIES scap_engine_util)
endif()

# Helpers are not engine-specific so we always include them
file(GLOB_RECURSE LIBSCAP_TESTS_UTILS_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/helpers/*cpp")
list(APPEND LIBSCAP_TESTS_SOURCES ${LIBSCAP_TESTS_UTILS_SOURCES})
Expand All @@ -57,7 +74,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux")
"${CMAKE_CURRENT_SOURCE_DIR}/test_suites/userspace/linux/*.cpp"
)
list(APPEND LIBSCAP_TEST_SOURCES ${LINUX_TEST_SUITE})
list(APPEND LIBSCAP_TESTS_LIBRARIES scap_engine_util)
endif()

# Engine-specific tests
Expand Down
13 changes: 13 additions & 0 deletions test/libscap/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
add_executable(
unit-test-libscap-linux
test_fds.c
)

target_link_libraries(unit-test-libscap-linux
"${GTEST_LIB}"
"${GTEST_MAIN_LIB}"
scap
)

add_test(NAME unit-test-libscap-linux
COMMAND unit-test-libscap-linux)
11 changes: 11 additions & 0 deletions test/libscap/test_suites/userspace/linux/scap_fds.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include <gtest/gtest.h>
#include <libscap/scap.h>

extern "C" {
int32_t test_time_wait_socket_at_buffer_end(void);
}

TEST(scap_fds, buffer_overflow_test) {
int32_t res = test_time_wait_socket_at_buffer_end();
ASSERT_EQ(res, SCAP_SUCCESS) << "Expected SCAP_SUCCESS when parsing TIME_WAIT socket at buffer end";
}
48 changes: 48 additions & 0 deletions test/libscap/test_suites/userspace/linux/scap_fds_impl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/param.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <netinet/tcp.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>

#include <libscap/scap.h>
#include <libscap/scap-int.h>
#include <libscap/linux/scap_linux_int.h>
#include <libscap/linux/scap_fds.c>

// This file decouples the C++ test framework from the C code we're testing.

// Mock a buffer that has a TIME_WAIT socket at the very end and test it.
int32_t test_time_wait_socket_at_buffer_end(void) {
static char error[SCAP_LASTERR_SIZE];
// TODO: Make this the same size as the real buffer.
char buffer[4096];
memset(buffer, 0, sizeof(buffer));

int pos = 0;
for(int i = 0; i < 100; i++) {
// Resembles typical socket entries.
pos += snprintf(buffer + pos, sizeof(buffer) - pos,
" sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode\n"
" 0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 123456\n");
}

// Imitates TIME_WAIT sockets with inode=0.
snprintf(buffer + pos, sizeof(buffer) - pos,
" 0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 0");

scap_fdinfo* sockets = NULL;
return scap_fd_read_ipv4_sockets_from_proc_fs(buffer, SCAP_L4_TCP, &sockets, error);
}

0 comments on commit dd4443c

Please sign in to comment.