From a3c5d3b2567fd53597470453e812f0f95dfcb215 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 12 Aug 2025 11:30:54 +0200 Subject: [PATCH] tests: Rewrite all fuzzers to LLVMFuzzerInitialize and nalloc Signed-off-by: Jakub Jelen Reviewed-by: Andreas Schneider --- tests/fuzz/CMakeLists.txt | 3 + tests/fuzz/nallocinc.c | 2 +- tests/fuzz/ssh_bind_config_fuzzer.c | 29 ++++++++- tests/fuzz/ssh_client_config_fuzzer.c | 29 ++++++++- tests/fuzz/ssh_client_fuzzer.c | 70 +++++++++++++++------- tests/fuzz/ssh_known_hosts_fuzzer.c | 23 +++++++- tests/fuzz/ssh_privkey_fuzzer.c | 32 ++++++++-- tests/fuzz/ssh_pubkey_fuzzer.c | 35 ++++++++--- tests/fuzz/ssh_server_fuzzer.c | 84 +++++++++++++++++++-------- tests/fuzz/ssh_sshsig_fuzzer.c | 14 ++++- 10 files changed, 252 insertions(+), 69 deletions(-) diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt index 30c9407a..8f2f97e6 100644 --- a/tests/fuzz/CMakeLists.txt +++ b/tests/fuzz/CMakeLists.txt @@ -10,6 +10,9 @@ macro(fuzzer name) LINK_FLAGS "-fsanitize=fuzzer") # Run the fuzzer to make sure it works add_test(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name} -runs=1) + # Run the fuzzer with nalloc to make sure it works + add_test(${name}_nalloc ${CMAKE_CURRENT_BINARY_DIR}/${name} -runs=1) + set_property(TEST ${name}_nalloc PROPERTY ENVIRONMENT NALLOC_FREQ 32) else() target_sources(${name} PRIVATE fuzzer.c) # Run the fuzzer to make sure it works diff --git a/tests/fuzz/nallocinc.c b/tests/fuzz/nallocinc.c index bf8b4573..6ce3c442 100644 --- a/tests/fuzz/nallocinc.c +++ b/tests/fuzz/nallocinc.c @@ -157,7 +157,7 @@ static int nalloc_start(const uint8_t *data, size_t size) } } else if (nalloc_bitmask == 0) { // nalloc disabled - return 0; + return 2; } nalloc_random_state = 0; for (size_t i = 0; i < size; i++) { diff --git a/tests/fuzz/ssh_bind_config_fuzzer.c b/tests/fuzz/ssh_bind_config_fuzzer.c index 3d0d8be8..fb5e03ee 100644 --- a/tests/fuzz/ssh_bind_config_fuzzer.c +++ b/tests/fuzz/ssh_bind_config_fuzzer.c @@ -24,6 +24,26 @@ #include "libssh/server.h" #include "libssh/bind_config.h" +#include "nallocinc.c" + +static void _fuzz_finalize(void) +{ + ssh_finalize(); +} + +int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + (void)argc; + + nalloc_init(*argv[0]); + + ssh_init(); + + atexit(_fuzz_finalize); + + return 0; +} + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ssh_bind bind = NULL; @@ -36,17 +56,20 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) strncpy(input, (const char *)data, size); input[size] = '\0'; - ssh_init(); + assert(nalloc_start(data, size) > 0); bind = ssh_bind_new(); - assert(bind != NULL); + if (bind == NULL) { + goto out; + } ssh_bind_config_parse_string(bind, input); ssh_bind_free(bind); - ssh_finalize(); +out: free(input); + nalloc_end(); return 0; } diff --git a/tests/fuzz/ssh_client_config_fuzzer.c b/tests/fuzz/ssh_client_config_fuzzer.c index 62eae93c..a994f807 100644 --- a/tests/fuzz/ssh_client_config_fuzzer.c +++ b/tests/fuzz/ssh_client_config_fuzzer.c @@ -23,6 +23,26 @@ #include "libssh/libssh.h" #include "libssh/options.h" +#include "nallocinc.c" + +static void _fuzz_finalize(void) +{ + ssh_finalize(); +} + +int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + (void)argc; + + nalloc_init(*argv[0]); + + ssh_init(); + + atexit(_fuzz_finalize); + + return 0; +} + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ssh_session session = NULL; @@ -35,10 +55,12 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) strncpy(input, (const char *)data, size); input[size] = '\0'; - ssh_init(); + assert(nalloc_start(data, size) > 0); session = ssh_new(); - assert(session != NULL); + if (session == NULL) { + goto out; + } /* Make sure we have default options set */ ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL); @@ -47,9 +69,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) ssh_config_parse_string(session, input); ssh_free(session); - ssh_finalize(); +out: free(input); + nalloc_end(); return 0; } diff --git a/tests/fuzz/ssh_client_fuzzer.c b/tests/fuzz/ssh_client_fuzzer.c index 78e3ae56..4f70282c 100644 --- a/tests/fuzz/ssh_client_fuzzer.c +++ b/tests/fuzz/ssh_client_fuzzer.c @@ -26,6 +26,24 @@ #include "nallocinc.c" +static void _fuzz_finalize(void) +{ + ssh_finalize(); +} + +int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + (void)argc; + + nalloc_init(*argv[0]); + + ssh_init(); + + atexit(_fuzz_finalize); + + return 0; +} + static int auth_callback(const char *prompt, char *buf, size_t len, @@ -86,13 +104,6 @@ static void select_loop(ssh_session session, ssh_channel channel) ssh_event_free(event); } -int LLVMFuzzerInitialize(int *argc, char ***argv) -{ - (void)argc; - nalloc_init(*argv[0]); - return 0; -} - int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ssh_session session = NULL; @@ -122,35 +133,54 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) rc = shutdown(socket_fds[1], SHUT_WR); assert(rc == 0); - ssh_init(); + assert(nalloc_start(data, size) > 0); session = ssh_new(); - assert(session != NULL); + if (session == NULL) { + goto out; + } env = getenv("LIBSSH_VERBOSITY"); if (env != NULL && strlen(env) > 0) { ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY_STR, env); } rc = ssh_options_set(session, SSH_OPTIONS_FD, &socket_fds[0]); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } rc = ssh_options_set(session, SSH_OPTIONS_HOST, "127.0.0.1"); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } rc = ssh_options_set(session, SSH_OPTIONS_USER, "alice"); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, "none"); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, "none"); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } rc = ssh_options_set(session, SSH_OPTIONS_HMAC_C_S, "none"); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } rc = ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, "none"); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } rc = ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &no); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } rc = ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &timeout); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } - nalloc_start(data, size); ssh_callbacks_init(&cb); ssh_set_callbacks(session, &cb); @@ -186,8 +216,6 @@ out: ssh_disconnect(session); ssh_free(session); - ssh_finalize(); - close(socket_fds[0]); close(socket_fds[1]); diff --git a/tests/fuzz/ssh_known_hosts_fuzzer.c b/tests/fuzz/ssh_known_hosts_fuzzer.c index fabdc28f..839ae537 100644 --- a/tests/fuzz/ssh_known_hosts_fuzzer.c +++ b/tests/fuzz/ssh_known_hosts_fuzzer.c @@ -23,6 +23,26 @@ #include "libssh/libssh.h" #include "knownhosts.c" +#include "nallocinc.c" + +static void _fuzz_finalize(void) +{ + ssh_finalize(); +} + +int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + (void)argc; + + nalloc_init(*argv[0]); + + ssh_init(); + + atexit(_fuzz_finalize); + + return 0; +} + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char *hostname = NULL; @@ -59,7 +79,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) fwrite(data + hostname_len, size - hostname_len, 1, fp); fclose(fp); - ssh_init(); + assert(nalloc_start(data, size) > 0); ssh_known_hosts_read_entries(hostname, filename, &entries); for (it = ssh_list_get_iterator(entries); @@ -78,5 +98,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) free(hostname); unlink(filename); + nalloc_end(); return 0; } diff --git a/tests/fuzz/ssh_privkey_fuzzer.c b/tests/fuzz/ssh_privkey_fuzzer.c index b65d680d..ff79103d 100644 --- a/tests/fuzz/ssh_privkey_fuzzer.c +++ b/tests/fuzz/ssh_privkey_fuzzer.c @@ -25,28 +25,48 @@ #include "libssh/libssh.h" #include "libssh/priv.h" +#include "nallocinc.c" + +static void _fuzz_finalize(void) +{ + ssh_finalize(); +} + +int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + (void)argc; + + nalloc_init(*argv[0]); + + ssh_init(); + + atexit(_fuzz_finalize); + + return 0; +} + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ssh_key pkey = NULL; uint8_t *input = NULL; int rc; + assert(nalloc_start(data, size) > 0); + input = bin_to_base64(data, size); if (input == NULL) { - return 1; + goto out; } - ssh_init(); - rc = ssh_pki_import_privkey_base64((char *)input, NULL, NULL, NULL, &pkey); free(input); if (rc != SSH_OK) { - return 1; + goto out; } ssh_key_free(pkey); - ssh_finalize(); - +out: + nalloc_end(); return 0; } diff --git a/tests/fuzz/ssh_pubkey_fuzzer.c b/tests/fuzz/ssh_pubkey_fuzzer.c index 70c94948..bb96dcc3 100644 --- a/tests/fuzz/ssh_pubkey_fuzzer.c +++ b/tests/fuzz/ssh_pubkey_fuzzer.c @@ -15,6 +15,7 @@ */ #include "config.h" +#include #include #include #include @@ -23,6 +24,26 @@ #include "libssh/libssh.h" #include "libssh/misc.h" +#include "nallocinc.c" + +static void _fuzz_finalize(void) +{ + ssh_finalize(); +} + +int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + (void)argc; + + nalloc_init(*argv[0]); + + ssh_init(); + + atexit(_fuzz_finalize); + + return 0; +} + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ssh_key pkey = NULL; @@ -31,8 +52,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) int rc; ssize_t sz; - ssh_init(); - filename = strdup("/tmp/libssh_pubkey_XXXXXX"); if (filename == NULL) { return -1; @@ -51,18 +70,18 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) return -1; } + assert(nalloc_start(data, size) > 0); + rc = ssh_pki_import_pubkey_file(filename, &pkey); if (rc != SSH_OK) { - unlink(filename); - free(filename); - return 1; + goto out; } ssh_key_free(pkey); + +out: unlink(filename); free(filename); - - ssh_finalize(); - + nalloc_end(); return 0; } diff --git a/tests/fuzz/ssh_server_fuzzer.c b/tests/fuzz/ssh_server_fuzzer.c index 7dd6fea4..e5504c72 100644 --- a/tests/fuzz/ssh_server_fuzzer.c +++ b/tests/fuzz/ssh_server_fuzzer.c @@ -70,6 +70,24 @@ struct session_data_struct { bool authenticated; }; +static void _fuzz_finalize(void) +{ + ssh_finalize(); +} + +int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + (void)argc; + + nalloc_init(*argv[0]); + + ssh_init(); + + atexit(_fuzz_finalize); + + return 0; +} + static int auth_none(ssh_session session, const char *user, void *userdata) { struct session_data_struct *sdata = @@ -120,13 +138,6 @@ static int write_rsa_hostkey(const char *rsakey_path) return 0; } -int LLVMFuzzerInitialize(int *argc, char ***argv) -{ - (void)argc; - nalloc_init(*argv[0]); - return 0; -} - int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { int socket_fds[2] = {-1, -1}; @@ -134,6 +145,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) bool no = false; const char *env = NULL; int rc; + ssh_bind sshbind = NULL; + ssh_session session = NULL; + ssh_event event = NULL; /* Our struct holding information about the session. */ struct session_data_struct sdata = { @@ -170,35 +184,54 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) rc = shutdown(socket_fds[1], SHUT_WR); assert(rc == 0); + assert(nalloc_start(data, size) > 0); + /* Set up the libssh server */ - ssh_bind sshbind = ssh_bind_new(); - assert(sshbind != NULL); - - ssh_session session = ssh_new(); - assert(session != NULL); + sshbind = ssh_bind_new(); + if (sshbind == NULL) { + goto out; + } + session = ssh_new(); + if (session == NULL) { + goto out; + } env = getenv("LIBSSH_VERBOSITY"); if (env != NULL && strlen(env) > 0) { rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, env); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } } rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, "/tmp/libssh_fuzzer_private_key"); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_CIPHERS_C_S, "none"); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_CIPHERS_S_C, "none"); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HMAC_C_S, "none"); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HMAC_S_C, "none"); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_PROCESS_CONFIG, &no); - assert(rc == 0); + if (rc != SSH_OK) { + goto out; + } ssh_set_auth_methods(session, SSH_AUTH_METHOD_NONE); @@ -206,12 +239,15 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) ssh_set_server_callbacks(session, &server_cb); rc = ssh_bind_accept_fd(sshbind, session, socket_fds[0]); - assert(rc == SSH_OK); + if (rc != SSH_OK) { + goto out; + } - ssh_event event = ssh_event_new(); - assert(event != NULL); + event = ssh_event_new(); + if (event == NULL) { + goto out; + } - nalloc_start(data, size); if (ssh_handle_key_exchange(session) == SSH_OK) { ssh_event_add_session(event, session); @@ -228,6 +264,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) n++; } } + +out: nalloc_end(); ssh_event_free(event); diff --git a/tests/fuzz/ssh_sshsig_fuzzer.c b/tests/fuzz/ssh_sshsig_fuzzer.c index 523e67af..8493f2b5 100644 --- a/tests/fuzz/ssh_sshsig_fuzzer.c +++ b/tests/fuzz/ssh_sshsig_fuzzer.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include #include @@ -21,6 +22,8 @@ #define LIBSSH_STATIC 1 #include "libssh/libssh.h" +#include "nallocinc.c" + static void _fuzz_finalize(void) { ssh_finalize(); @@ -29,7 +32,8 @@ static void _fuzz_finalize(void) int LLVMFuzzerInitialize(int *argc, char ***argv) { (void)argc; - (void)argv; + + nalloc_init(*argv[0]); ssh_init(); @@ -46,9 +50,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) char *signature = NULL; int rc; + assert(nalloc_start(data, size) > 0); + signature = (char *)malloc(size + 1); if (signature == NULL) { - return 1; + goto out; } strncpy(signature, (const char *)data, size); signature[size] = '\0'; @@ -56,9 +62,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) rc = sshsig_verify(input, sizeof(input), signature, namespace, &pkey); free(signature); if (rc != SSH_OK) { - return 1; + goto out; } ssh_key_free(pkey); +out: + nalloc_end(); return 0; }