From 7459d8235b845bbf14f92fd356da04b83dca460d Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 18:10:22 +0100 Subject: [PATCH 01/26] Rename memory.c -> syscalls.c Signed-off-by: DL6ER --- src/CMakeLists.txt | 4 ++-- src/FTL.h | 3 ++- src/api/socket.c | 7 +++---- src/args.c | 1 - src/capabilities.c | 1 - src/config.c | 1 - src/daemon.c | 1 - src/database/aliasclients.c | 2 -- src/database/common.c | 1 - src/database/gravity-db.c | 3 +++ src/database/gravity-db.h | 9 +++------ src/database/network-table.c | 2 -- src/database/query-table.c | 2 -- src/datastructure.c | 1 - src/dnsmasq_interface.c | 1 - src/files.c | 1 - src/gc.c | 2 -- src/log.c | 1 - src/overTime.c | 2 -- src/regex.c | 1 - src/resolve.c | 1 - src/setupVars.c | 1 - src/shmem.c | 1 - src/signals.c | 2 -- src/{memory.c => syscalls.c} | 2 +- src/{memory.h => syscalls.h} | 8 ++++---- src/timers.c | 1 - 27 files changed, 18 insertions(+), 44 deletions(-) rename src/{memory.c => syscalls.c} (99%) rename src/{memory.h => syscalls.h} (90%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b83dc8a7..b89b8fa9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -131,8 +131,8 @@ set(sources log.h main.c main.h - memory.c - memory.h + syscalls.c + syscalls.h overTime.c overTime.h regex.c diff --git a/src/FTL.h b/src/FTL.h index cf645050..d1811cd1 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -114,7 +114,7 @@ // Important: This number has to be smaller than 256 for this mechanism to work #define NUM_RECHECKS 3 -// Use out own memory handling functions that will detect possible errors +// Use out own syscalls handling functions that will detect possible errors // and report accordingly in the log. This will make debugging FTL crashs // caused by insufficient memory or by code bugs (not properly dealing // with NULL pointers) much easier. @@ -124,6 +124,7 @@ #define strdup(str_in) FTLstrdup(str_in, __FILE__, __FUNCTION__, __LINE__) #define calloc(numer_of_elements, element_size) FTLcalloc(numer_of_elements, element_size, __FILE__, __FUNCTION__, __LINE__) #define realloc(ptr, new_size) FTLrealloc(ptr, new_size, __FILE__, __FUNCTION__, __LINE__) +#include "syscalls.h" // Preprocessor help functions #define str(x) # x diff --git a/src/api/socket.c b/src/api/socket.c index a5fb901d..3eb8e0d0 100644 --- a/src/api/socket.c +++ b/src/api/socket.c @@ -10,13 +10,12 @@ #include "FTL.h" #include "api.h" -#include "log.h" +#include "../log.h" #include "socket.h" #include "request.h" -#include "config.h" -#include "memory.h" +#include "../config.h" // global variable killed -#include "signals.h" +#include "../signals.h" // The backlog argument defines the maximum length // to which the queue of pending connections for diff --git a/src/args.c b/src/args.c index b196a83f..0878f43f 100644 --- a/src/args.c +++ b/src/args.c @@ -16,7 +16,6 @@ #include "FTL.h" #include "args.h" #include "version.h" -#include "memory.h" #include "main.h" #include "log.h" // global variable killed diff --git a/src/capabilities.c b/src/capabilities.c index 6478526c..013bba64 100644 --- a/src/capabilities.c +++ b/src/capabilities.c @@ -14,7 +14,6 @@ #undef __USE_XOPEN #include "FTL.h" #include "capabilities.h" -#include "memory.h" #include "config.h" #include "log.h" diff --git a/src/config.c b/src/config.c index 7d840524..64fdffa8 100644 --- a/src/config.c +++ b/src/config.c @@ -10,7 +10,6 @@ #include "FTL.h" #include "config.h" -#include "memory.h" #include "setupVars.h" #include "log.h" // nice() diff --git a/src/daemon.c b/src/daemon.c index e9a29d93..2d72d20b 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -10,7 +10,6 @@ #include "FTL.h" #include "daemon.h" -#include "memory.h" #include "config.h" #include "log.h" // sleepms() diff --git a/src/database/aliasclients.c b/src/database/aliasclients.c index 2097d0c7..023c402a 100644 --- a/src/database/aliasclients.c +++ b/src/database/aliasclients.c @@ -17,8 +17,6 @@ #include "../config.h" // logg() #include "../log.h" -// calloc() -#include "../memory.h" // getAliasclientIDfromIP() #include "network-table.h" diff --git a/src/database/common.c b/src/database/common.c index 2f50b1e6..2839255c 100644 --- a/src/database/common.c +++ b/src/database/common.c @@ -13,7 +13,6 @@ #include "network-table.h" #include "message-table.h" #include "../shmem.h" -#include "../memory.h" // struct config #include "../config.h" // logg() diff --git a/src/database/gravity-db.c b/src/database/gravity-db.c index de8da8b6..13187cea 100644 --- a/src/database/gravity-db.c +++ b/src/database/gravity-db.c @@ -30,6 +30,9 @@ // reset_aliasclient() #include "aliasclients.h" +// Definition of struct regex_data +#include "../regex_r.h" + // Prefix of interface names in the client table #define INTERFACE_SEP ":" diff --git a/src/database/gravity-db.h b/src/database/gravity-db.h index e4ce7bf0..c92f671b 100644 --- a/src/database/gravity-db.h +++ b/src/database/gravity-db.h @@ -10,12 +10,9 @@ #ifndef GRAVITY_H #define GRAVITY_H -// global variable counters -#include "memory.h" -// clients data structure -#include "datastructure.h" - -// Definition of struct regex_data +// clientsData +#include "../datastructure.h" +// regex_data #include "../regex_r.h" // Table indices diff --git a/src/database/network-table.c b/src/database/network-table.c index ef12136d..40c9f9ab 100644 --- a/src/database/network-table.c +++ b/src/database/network-table.c @@ -12,8 +12,6 @@ #include "network-table.h" #include "common.h" #include "../shmem.h" -// strdup() -#include "../memory.h" #include "../log.h" // timer_elapsed_msec() #include "../timers.h" diff --git a/src/database/query-table.c b/src/database/query-table.c index 3bd3ca93..6b04f9ed 100644 --- a/src/database/query-table.c +++ b/src/database/query-table.c @@ -25,8 +25,6 @@ #include "../config.h" // getstr() #include "../shmem.h" -// free() -#include "../memory.h" static bool saving_failed_before = false; diff --git a/src/datastructure.c b/src/datastructure.c index dfa0bd24..ff8c7510 100644 --- a/src/datastructure.c +++ b/src/datastructure.c @@ -10,7 +10,6 @@ #include "FTL.h" #include "datastructure.h" -#include "memory.h" #include "shmem.h" #include "log.h" // enum REGEX diff --git a/src/dnsmasq_interface.c b/src/dnsmasq_interface.c index c97b68d2..0a0e96f1 100644 --- a/src/dnsmasq_interface.c +++ b/src/dnsmasq_interface.c @@ -16,7 +16,6 @@ #include "dnsmasq_interface.h" #include "shmem.h" #include "overTime.h" -#include "memory.h" #include "database/common.h" #include "database/database-thread.h" #include "datastructure.h" diff --git a/src/files.c b/src/files.c index 7f1d3d94..cdcbeb80 100644 --- a/src/files.c +++ b/src/files.c @@ -10,7 +10,6 @@ #include "FTL.h" #include "files.h" -#include "memory.h" #include "config.h" #include "setupVars.h" #include "log.h" diff --git a/src/gc.c b/src/gc.c index 618fa2e1..efe0c9e7 100644 --- a/src/gc.c +++ b/src/gc.c @@ -16,8 +16,6 @@ #include "overTime.h" #include "database/common.h" #include "log.h" -// global variable counters -#include "memory.h" // global variable killed #include "signals.h" // data getter functions diff --git a/src/log.c b/src/log.c index 9cde7d37..28885f41 100644 --- a/src/log.c +++ b/src/log.c @@ -10,7 +10,6 @@ #include "FTL.h" #include "version.h" -#include "memory.h" // is_fork() #include "daemon.h" #include "config.h" diff --git a/src/overTime.c b/src/overTime.c index b0315a29..53e23765 100644 --- a/src/overTime.c +++ b/src/overTime.c @@ -13,8 +13,6 @@ #include "shmem.h" #include "config.h" #include "log.h" -// global variable counters -#include "memory.h" // data getter functions #include "datastructure.h" diff --git a/src/regex.c b/src/regex.c index 818981f2..5a0807a3 100644 --- a/src/regex.c +++ b/src/regex.c @@ -11,7 +11,6 @@ #include "FTL.h" #include "regex_r.h" #include "timers.h" -#include "memory.h" #include "log.h" #include "config.h" // data getter functions diff --git a/src/resolve.c b/src/resolve.c index cd71996e..4719f94c 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -11,7 +11,6 @@ #include "FTL.h" #include "resolve.h" #include "shmem.h" -#include "memory.h" // struct config #include "config.h" // sleepms() diff --git a/src/setupVars.c b/src/setupVars.c index d018a797..34c00f32 100644 --- a/src/setupVars.c +++ b/src/setupVars.c @@ -10,7 +10,6 @@ #include "FTL.h" #include "log.h" -#include "memory.h" #include "config.h" #include "setupVars.h" diff --git a/src/shmem.c b/src/shmem.c index bacd53fe..bd922480 100644 --- a/src/shmem.c +++ b/src/shmem.c @@ -12,7 +12,6 @@ #include "shmem.h" #include "overTime.h" #include "log.h" -#include "memory.h" #include "config.h" // data getter functions #include "datastructure.h" diff --git a/src/signals.c b/src/signals.c index b5ec061d..f39dd6cb 100644 --- a/src/signals.c +++ b/src/signals.c @@ -15,8 +15,6 @@ #include "signals.h" // logg() #include "log.h" -// free() -#include "memory.h" // ls_dir() #include "files.h" // gettid() diff --git a/src/memory.c b/src/syscalls.c similarity index 99% rename from src/memory.c rename to src/syscalls.c index 81dae6be..d3618874 100644 --- a/src/memory.c +++ b/src/syscalls.c @@ -10,7 +10,7 @@ #include "FTL.h" #include "shmem.h" -#include "memory.h" +#include "syscalls.h" #include "log.h" // The special memory handling routines have to be the last ones in this source file diff --git a/src/memory.h b/src/syscalls.h similarity index 90% rename from src/memory.h rename to src/syscalls.h index 72ea92b0..e3fdd4ed 100644 --- a/src/memory.h +++ b/src/syscalls.h @@ -3,12 +3,12 @@ * Network-wide ad blocking via your own hardware. * * FTL Engine -* Memory prototypes +* Syscall prototypes * * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ -#ifndef MEMORY_H -#define MEMORY_H +#ifndef SYSCALLS_H +#define SYSCALLS_H #include "enums.h" @@ -17,4 +17,4 @@ void *FTLcalloc(size_t n, size_t size, const char *file, const char *function, c void *FTLrealloc(void *ptr_in, size_t size, const char *file, const char *function, const int line) __attribute__((alloc_size(2))); void FTLfree(void *ptr, const char* file, const char *function, const int line); -#endif //MEMORY_H +#endif //SYSCALLS_H diff --git a/src/timers.c b/src/timers.c index 56cfc125..691e16ba 100644 --- a/src/timers.c +++ b/src/timers.c @@ -10,7 +10,6 @@ #include "FTL.h" #include "timers.h" -#include "memory.h" #include "log.h" struct timespec t0[NUMTIMERS]; From d4deb01d9fb7e6f8acb2390b07d1e27e92841203 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 18:12:44 +0100 Subject: [PATCH 02/26] Factor out syscalls for calloc, free, realloc and strdup into dedicated syscalls/{}.c files Signed-off-by: DL6ER --- src/CMakeLists.txt | 4 +- src/FTL.h | 2 +- src/syscalls.c | 95 ----------------------------------- src/syscalls/CMakeLists.txt | 20 ++++++++ src/syscalls/calloc.c | 29 +++++++++++ src/syscalls/free.c | 27 ++++++++++ src/syscalls/realloc.c | 34 +++++++++++++ src/syscalls/strdup.c | 38 ++++++++++++++ src/{ => syscalls}/syscalls.h | 2 - 9 files changed, 151 insertions(+), 100 deletions(-) delete mode 100644 src/syscalls.c create mode 100644 src/syscalls/CMakeLists.txt create mode 100644 src/syscalls/calloc.c create mode 100644 src/syscalls/free.c create mode 100644 src/syscalls/realloc.c create mode 100644 src/syscalls/strdup.c rename src/{ => syscalls}/syscalls.h (97%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b89b8fa9..f4f6fb9c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -131,8 +131,6 @@ set(sources log.h main.c main.h - syscalls.c - syscalls.h overTime.c overTime.h regex.c @@ -174,6 +172,7 @@ add_executable(pihole-FTL $ $ $ + $ ) if(STATIC STREQUAL "true") set_target_properties(pihole-FTL PROPERTIES LINK_SEARCH_START_STATIC ON) @@ -228,3 +227,4 @@ add_subdirectory(database) add_subdirectory(dnsmasq) add_subdirectory(lua) add_subdirectory(tre-regex) +add_subdirectory(syscalls) diff --git a/src/FTL.h b/src/FTL.h index d1811cd1..1a724e1a 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -124,7 +124,7 @@ #define strdup(str_in) FTLstrdup(str_in, __FILE__, __FUNCTION__, __LINE__) #define calloc(numer_of_elements, element_size) FTLcalloc(numer_of_elements, element_size, __FILE__, __FUNCTION__, __LINE__) #define realloc(ptr, new_size) FTLrealloc(ptr, new_size, __FILE__, __FUNCTION__, __LINE__) -#include "syscalls.h" +#include "syscalls/syscalls.h" // Preprocessor help functions #define str(x) # x diff --git a/src/syscalls.c b/src/syscalls.c deleted file mode 100644 index d3618874..00000000 --- a/src/syscalls.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Pi-hole: A black hole for Internet advertisements -* (c) 2017 Pi-hole, LLC (https://pi-hole.net) -* Network-wide ad blocking via your own hardware. -* -* FTL Engine -* Global variable definitions and memory reallocation handling -* -* This file is copyright under the latest version of the EUPL. -* Please see LICENSE file for your rights under this license. */ - -#include "FTL.h" -#include "shmem.h" -#include "syscalls.h" -#include "log.h" - -// The special memory handling routines have to be the last ones in this source file -// as we restore the original definition of the strdup, free, calloc, and realloc -// functions in here, i.e. if anything extra would come below these lines, it would -// not be protected by our (error logging) functions! - -#undef strdup -char* __attribute__((malloc)) FTLstrdup(const char *src, const char * file, const char * function, const int line) -{ - // The FTLstrdup() function returns a pointer to a new string which is a - // duplicate of the string s. Memory for the new string is obtained with - // calloc(3), and can be freed with free(3). - if(src == NULL) - { - logg("WARN: Trying to copy a NULL string in %s() (%s:%i)", function, file, line); - return NULL; - } - const size_t len = strlen(src); - char *dest = calloc(len+1, sizeof(char)); - if(dest == NULL) - { - logg("FATAL: Memory allocation failed in %s() (%s:%i)", function, file, line); - return NULL; - } - // Use memcpy as memory areas cannot overlap - memcpy(dest, src, len); - dest[len] = '\0'; - - return dest; -} - -#undef calloc -void* __attribute__((malloc)) __attribute__((alloc_size(1,2))) FTLcalloc(const size_t nmemb, const size_t size, const char * file, const char * function, const int line) -{ - // The FTLcalloc() function allocates memory for an array of nmemb elements - // of size bytes each and returns a pointer to the allocated memory. The - // memory is set to zero. If nmemb or size is 0, then calloc() returns - // either NULL, or a unique pointer value that can later be successfully - // passed to free(). - void *ptr = calloc(nmemb, size); - if(ptr == NULL) - logg("FATAL: Memory allocation (%zu x %zu) failed in %s() (%s:%i)", - nmemb, size, function, file, line); - - return ptr; -} - -#undef realloc -void __attribute__((alloc_size(2))) *FTLrealloc(void *ptr_in, const size_t size, const char * file, const char * function, const int line) -{ - // The FTLrealloc() function changes the size of the memory block pointed to - // by ptr to size bytes. The contents will be unchanged in the range from - // the start of the region up to the minimum of the old and new sizes. If - // the new size is larger than the old size, the added memory will not be - // initialized. If ptr is NULL, then the call is equivalent to malloc(size), - // for all values of size; if size is equal to zero, and ptr is - // not NULL, then the call is equivalent to free(ptr). Unless ptr is - // NULL, it must have been returned by an earlier call to malloc(), cal‐ - // loc() or realloc(). If the area pointed to was moved, a free(ptr) is - // done. - void *ptr_out = realloc(ptr_in, size); - if(ptr_out == NULL) - logg("FATAL: Memory reallocation (%p -> %zu) failed in %s() (%s:%i)", - ptr_in, size, function, file, line); - - return ptr_out; -} - -#undef free -void FTLfree(void *ptr, const char * file, const char * function, const int line) -{ - // The free() function frees the memory space pointed to by ptr, which - // must have been returned by a previous call to malloc(), calloc(), or - // realloc(). Otherwise, or if free(ptr) has already been called before, - // undefined behavior occurs. If ptr is NULL, no operation is performed. - if(ptr == NULL) - logg("FATAL: Trying to free NULL pointer in %s() (%s:%i)", function, file, line); - - // We intentionally run free() nevertheless to see the crash in the debugger - free(ptr); -} diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt new file mode 100644 index 00000000..cde8b6de --- /dev/null +++ b/src/syscalls/CMakeLists.txt @@ -0,0 +1,20 @@ +# Pi-hole: A black hole for Internet advertisements +# (c) 2020 Pi-hole, LLC (https://pi-hole.net) +# Network-wide ad blocking via your own hardware. +# +# FTL Engine +# /src/syscalls/CMakeList.txt +# +# This file is copyright under the latest version of the EUPL. +# Please see LICENSE file for your rights under this license. + +set(sources + calloc.c + free.c + realloc.c + strdup.c + syscalls.h + ) + +add_library(syscalls OBJECT ${sources}) +target_compile_options(syscalls PRIVATE ${EXTRAWARN}) diff --git a/src/syscalls/calloc.c b/src/syscalls/calloc.c new file mode 100644 index 00000000..facaf13c --- /dev/null +++ b/src/syscalls/calloc.c @@ -0,0 +1,29 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for calloc +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +#undef calloc +void* __attribute__((malloc)) __attribute__((alloc_size(1,2))) FTLcalloc(const size_t nmemb, const size_t size, const char * file, const char * function, const int line) +{ + // The FTLcalloc() function allocates memory for an array of nmemb elements + // of size bytes each and returns a pointer to the allocated memory. The + // memory is set to zero. If nmemb or size is 0, then calloc() returns + // either NULL, or a unique pointer value that can later be successfully + // passed to free(). + void *ptr = calloc(nmemb, size); + if(ptr == NULL) + logg("FATAL: Memory allocation (%zu x %zu) failed in %s() (%s:%i)", + nmemb, size, function, file, line); + + return ptr; +} diff --git a/src/syscalls/free.c b/src/syscalls/free.c new file mode 100644 index 00000000..1c3fb66d --- /dev/null +++ b/src/syscalls/free.c @@ -0,0 +1,27 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for free +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +#undef free +void FTLfree(void *ptr, const char * file, const char * function, const int line) +{ + // The free() function frees the memory space pointed to by ptr, which + // must have been returned by a previous call to malloc(), calloc(), or + // realloc(). Otherwise, or if free(ptr) has already been called before, + // undefined behavior occurs. If ptr is NULL, no operation is performed. + if(ptr == NULL) + logg("FATAL: Trying to free NULL pointer in %s() (%s:%i)", function, file, line); + + // We intentionally run free() nevertheless to see the crash in the debugger + free(ptr); +} diff --git a/src/syscalls/realloc.c b/src/syscalls/realloc.c new file mode 100644 index 00000000..2c5786cc --- /dev/null +++ b/src/syscalls/realloc.c @@ -0,0 +1,34 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for realloc +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +#undef realloc +void __attribute__((alloc_size(2))) *FTLrealloc(void *ptr_in, const size_t size, const char * file, const char * function, const int line) +{ + // The FTLrealloc() function changes the size of the memory block pointed to + // by ptr to size bytes. The contents will be unchanged in the range from + // the start of the region up to the minimum of the old and new sizes. If + // the new size is larger than the old size, the added memory will not be + // initialized. If ptr is NULL, then the call is equivalent to malloc(size), + // for all values of size; if size is equal to zero, and ptr is + // not NULL, then the call is equivalent to free(ptr). Unless ptr is + // NULL, it must have been returned by an earlier call to malloc(), cal‐ + // loc() or realloc(). If the area pointed to was moved, a free(ptr) is + // done. + void *ptr_out = realloc(ptr_in, size); + if(ptr_out == NULL) + logg("FATAL: Memory reallocation (%p -> %zu) failed in %s() (%s:%i)", + ptr_in, size, function, file, line); + + return ptr_out; +} \ No newline at end of file diff --git a/src/syscalls/strdup.c b/src/syscalls/strdup.c new file mode 100644 index 00000000..8730af0f --- /dev/null +++ b/src/syscalls/strdup.c @@ -0,0 +1,38 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for strdup +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +#undef strdup +char* __attribute__((malloc)) FTLstrdup(const char *src, const char * file, const char * function, const int line) +{ + // The FTLstrdup() function returns a pointer to a new string which is a + // duplicate of the string s. Memory for the new string is obtained with + // calloc(3), and can be freed with free(3). + if(src == NULL) + { + logg("WARN: Trying to copy a NULL string in %s() (%s:%i)", function, file, line); + return NULL; + } + const size_t len = strlen(src); + char *dest = calloc(len+1, sizeof(char)); + if(dest == NULL) + { + logg("FATAL: Memory allocation failed in %s() (%s:%i)", function, file, line); + return NULL; + } + // Use memcpy as memory areas cannot overlap + memcpy(dest, src, len); + dest[len] = '\0'; + + return dest; +} \ No newline at end of file diff --git a/src/syscalls.h b/src/syscalls/syscalls.h similarity index 97% rename from src/syscalls.h rename to src/syscalls/syscalls.h index e3fdd4ed..887b1fa7 100644 --- a/src/syscalls.h +++ b/src/syscalls/syscalls.h @@ -10,8 +10,6 @@ #ifndef SYSCALLS_H #define SYSCALLS_H -#include "enums.h" - char *FTLstrdup(const char *src, const char *file, const char *function, const int line) __attribute__((malloc)); void *FTLcalloc(size_t n, size_t size, const char *file, const char *function, const int line) __attribute__((malloc)) __attribute__((alloc_size(1,2))); void *FTLrealloc(void *ptr_in, size_t size, const char *file, const char *function, const int line) __attribute__((alloc_size(2))); From 9537d7de3da04e78c2a4ad28dd74c45c123dff0c Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 18:28:02 +0100 Subject: [PATCH 03/26] Add interrupt-safe fprintf() and printf() routines Signed-off-by: DL6ER --- src/FTL.h | 2 + src/syscalls/CMakeLists.txt | 2 + src/syscalls/fprintf.c | 80 +++++++++++++++++++++++++++++++++++++ src/syscalls/syscalls.h | 3 +- 4 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/syscalls/fprintf.c diff --git a/src/FTL.h b/src/FTL.h index 1a724e1a..7985b228 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -124,6 +124,8 @@ #define strdup(str_in) FTLstrdup(str_in, __FILE__, __FUNCTION__, __LINE__) #define calloc(numer_of_elements, element_size) FTLcalloc(numer_of_elements, element_size, __FILE__, __FUNCTION__, __LINE__) #define realloc(ptr, new_size) FTLrealloc(ptr, new_size, __FILE__, __FUNCTION__, __LINE__) +#define printf(format, ...) FTLfprintf(stdout, format, ##__VA_ARGS__) +#define fprintf(stream, format, ...) FTLfprintf(stream, format, ##__VA_ARGS__) #include "syscalls/syscalls.h" // Preprocessor help functions diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index cde8b6de..4dde8b66 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -10,7 +10,9 @@ set(sources calloc.c + fprintf.c free.c + printf.c realloc.c strdup.c syscalls.h diff --git a/src/syscalls/fprintf.c b/src/syscalls/fprintf.c new file mode 100644 index 00000000..82bf8e7e --- /dev/null +++ b/src/syscalls/fprintf.c @@ -0,0 +1,80 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for fprintf +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +int FTLfprintf(FILE *stream, const char *format, ...) +{ + // Print into dynamically allocated memory + va_list arg; + char *buffer = NULL; + int length = 0; + do + { + va_start(arg, format); + // Reset errno before trying to get the string + errno = 0; + length = vasprintf(&buffer, format, arg); + va_end(arg); + } + // Try again to allocate memory if this failed due to an interruption by + // an incoming signal + while(length < 0 && errno == EINTR); + + // Error handling + if(length < 0 || buffer == NULL) + { + fputs("WARN: fprintf() failed to allocate memory: ", stream); + fputs(strerror(errno), stream); + fputs("\n", stream); + fputs("Not processing string: ", stream); + fputs(format, stream); + fputs("\n", stream); + + // Return early, there isn't anything we can do here + return length; + } + + // Actually write into file now + char *_buffer = buffer; + int bytes_written = 0; + do + { + // Reset errno before trying to write + errno = 0; + // Print buffer into stream + bytes_written = fputs(_buffer, stream); + // Add number of written bytes + _buffer += bytes_written; + } + // Try to write the remaining content into the stream if this failed due + // to an interruption by an incoming signal + while(_buffer < buffer && errno == EINTR); + + // Final error checking (may have faild for some other reason then an + // EINTR = interrupted system call) + if(_buffer < buffer) + { + fputs("WARN: fprintf() did not print all characters: ", stream); + fputs(strerror(errno), stream); + fputs("\n", stream); + fputs("Not processing string: ", stream); + fputs(format, stream); + fputs("\n", stream); + } + + // Free allocated memory + free(buffer); + + // Return number of written bytes + return length; +} diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index 887b1fa7..2b458273 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -1,5 +1,5 @@ /* Pi-hole: A black hole for Internet advertisements -* (c) 2019 Pi-hole, LLC (https://pi-hole.net) +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) * Network-wide ad blocking via your own hardware. * * FTL Engine @@ -14,5 +14,6 @@ char *FTLstrdup(const char *src, const char *file, const char *function, const i void *FTLcalloc(size_t n, size_t size, const char *file, const char *function, const int line) __attribute__((malloc)) __attribute__((alloc_size(1,2))); void *FTLrealloc(void *ptr_in, size_t size, const char *file, const char *function, const int line) __attribute__((alloc_size(2))); void FTLfree(void *ptr, const char* file, const char *function, const int line); +int FTLfprintf(FILE *stream, const char *format, ...) __attribute__ ((format (gnu_printf, 2, 3))); #endif //SYSCALLS_H From 217f957af359f72e1775c25eaf251e649d8dbef3 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 18:39:32 +0100 Subject: [PATCH 04/26] Add interrupt-safe vfprintf() and vprintf() routines Signed-off-by: DL6ER --- src/FTL.h | 2 + src/syscalls/CMakeLists.txt | 2 +- src/syscalls/fprintf.c | 65 ++------------------------ src/syscalls/syscalls.h | 1 + src/syscalls/vfprintf.c | 92 +++++++++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 62 deletions(-) create mode 100644 src/syscalls/vfprintf.c diff --git a/src/FTL.h b/src/FTL.h index 7985b228..d508523d 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -126,6 +126,8 @@ #define realloc(ptr, new_size) FTLrealloc(ptr, new_size, __FILE__, __FUNCTION__, __LINE__) #define printf(format, ...) FTLfprintf(stdout, format, ##__VA_ARGS__) #define fprintf(stream, format, ...) FTLfprintf(stream, format, ##__VA_ARGS__) +#define vprintf(format, args) FTLvfprintf(stdout, format, args) +#define vfprintf(stream, format, args) FTLvfprintf(stream, format, args) #include "syscalls/syscalls.h" // Preprocessor help functions diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index 4dde8b66..c38f86cb 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -12,10 +12,10 @@ set(sources calloc.c fprintf.c free.c - printf.c realloc.c strdup.c syscalls.h + vfprintf.c ) add_library(syscalls OBJECT ${sources}) diff --git a/src/syscalls/fprintf.c b/src/syscalls/fprintf.c index 82bf8e7e..e8016c88 100644 --- a/src/syscalls/fprintf.c +++ b/src/syscalls/fprintf.c @@ -14,67 +14,10 @@ int FTLfprintf(FILE *stream, const char *format, ...) { - // Print into dynamically allocated memory - va_list arg; - char *buffer = NULL; - int length = 0; - do - { - va_start(arg, format); - // Reset errno before trying to get the string - errno = 0; - length = vasprintf(&buffer, format, arg); - va_end(arg); - } - // Try again to allocate memory if this failed due to an interruption by - // an incoming signal - while(length < 0 && errno == EINTR); + va_list args; + va_start(args, format); + const int length = FTLvfprintf(stream, format, args); + va_end(args); - // Error handling - if(length < 0 || buffer == NULL) - { - fputs("WARN: fprintf() failed to allocate memory: ", stream); - fputs(strerror(errno), stream); - fputs("\n", stream); - fputs("Not processing string: ", stream); - fputs(format, stream); - fputs("\n", stream); - - // Return early, there isn't anything we can do here - return length; - } - - // Actually write into file now - char *_buffer = buffer; - int bytes_written = 0; - do - { - // Reset errno before trying to write - errno = 0; - // Print buffer into stream - bytes_written = fputs(_buffer, stream); - // Add number of written bytes - _buffer += bytes_written; - } - // Try to write the remaining content into the stream if this failed due - // to an interruption by an incoming signal - while(_buffer < buffer && errno == EINTR); - - // Final error checking (may have faild for some other reason then an - // EINTR = interrupted system call) - if(_buffer < buffer) - { - fputs("WARN: fprintf() did not print all characters: ", stream); - fputs(strerror(errno), stream); - fputs("\n", stream); - fputs("Not processing string: ", stream); - fputs(format, stream); - fputs("\n", stream); - } - - // Free allocated memory - free(buffer); - - // Return number of written bytes return length; } diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index 2b458273..a94ca940 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -15,5 +15,6 @@ void *FTLcalloc(size_t n, size_t size, const char *file, const char *function, c void *FTLrealloc(void *ptr_in, size_t size, const char *file, const char *function, const int line) __attribute__((alloc_size(2))); void FTLfree(void *ptr, const char* file, const char *function, const int line); int FTLfprintf(FILE *stream, const char *format, ...) __attribute__ ((format (gnu_printf, 2, 3))); +int FTLvfprintf(FILE *stream, const char *format, va_list args) __attribute__ ((format (gnu_printf, 2, 0))); #endif //SYSCALLS_H diff --git a/src/syscalls/vfprintf.c b/src/syscalls/vfprintf.c new file mode 100644 index 00000000..96de1cf2 --- /dev/null +++ b/src/syscalls/vfprintf.c @@ -0,0 +1,92 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for vfprintf +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +int FTLvfprintf(FILE *stream, const char *format, va_list args) +{ + // Print into dynamically allocated memory + char *buffer = NULL; + int _errno, length = 0; + do + { + // The va_copy() macro copies the (previously initialized) variable + // argument list args to the local _args. The behavior is as if + // va_start() were applied to _args with the same last argument, + // followed by the same number of va_arg() invocations that was used to + // reach the current state of args. We do this to be able to reuse the + // arguments in args when we need to redo the string preparation + // procedure + va_list _args; + va_copy(_args, args); + // Reset errno before trying to get the string + errno = 0; + // Do the actual string transformation + length = vasprintf(&buffer, format, _args); + // Copy errno into buffer before calling va_end() + _errno = errno; + va_end(_args); + } + // Try again to allocate memory if this failed due to an interruption by + // an incoming signal + while(length < 0 && _errno == EINTR); + + // Handle other errors than EINTR + if(length < 0 || buffer == NULL) + { + fputs("WARN: fprintf() failed to allocate memory: ", stream); + fputs(strerror(errno), stream); + fputs("\n", stream); + fputs("Not processing string: ", stream); + fputs(format, stream); + fputs("\n", stream); + + // Free the buffer in case anything got allocated + if(buffer != NULL) + free(buffer); + + // Return early, there isn't anything we can do here + return length; + } + + // Actually write into the requested stream now + char *_buffer = buffer; + do + { + // Reset errno before trying to write + errno = 0; + // Print buffer into stream and advance working pointer by number of + // written bytes + _buffer += fputs(_buffer, stream); + } + // Try to write the remaining content into the stream if this failed due + // to an interruption by an incoming signal + while(_buffer < buffer && errno == EINTR); + + // Final error checking (may have faild for some other reason then an + // EINTR = interrupted system call) + if(_buffer < buffer) + { + fputs("WARN: fprintf() did not print all characters: ", stream); + fputs(strerror(errno), stream); + fputs("\n", stream); + fputs("Not processing string: ", stream); + fputs(format, stream); + fputs("\n", stream); + } + + // Free allocated memory + free(buffer); + + // Return number of written bytes + return length; +} From 44f88e8870562751f9d91fb1880f395d5fd5cfb9 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 18:43:38 +0100 Subject: [PATCH 05/26] Make calloc(), realloc() and strdup() interrupt-safe Signed-off-by: DL6ER --- src/syscalls/calloc.c | 12 +++++++++++- src/syscalls/free.c | 1 - src/syscalls/realloc.c | 12 +++++++++++- src/syscalls/strdup.c | 10 +++++----- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/syscalls/calloc.c b/src/syscalls/calloc.c index facaf13c..4eab1b3c 100644 --- a/src/syscalls/calloc.c +++ b/src/syscalls/calloc.c @@ -20,7 +20,17 @@ void* __attribute__((malloc)) __attribute__((alloc_size(1,2))) FTLcalloc(const s // memory is set to zero. If nmemb or size is 0, then calloc() returns // either NULL, or a unique pointer value that can later be successfully // passed to free(). - void *ptr = calloc(nmemb, size); + void *ptr = NULL; + do + { + errno = 0; + ptr = calloc(nmemb, size); + } + // Try again to allocate memory if this failed due to an interruption by + // an incoming signal + while(ptr == NULL && errno == EINTR); + + // Handle other errors than EINTR if(ptr == NULL) logg("FATAL: Memory allocation (%zu x %zu) failed in %s() (%s:%i)", nmemb, size, function, file, line); diff --git a/src/syscalls/free.c b/src/syscalls/free.c index 1c3fb66d..56ccc4ae 100644 --- a/src/syscalls/free.c +++ b/src/syscalls/free.c @@ -22,6 +22,5 @@ void FTLfree(void *ptr, const char * file, const char * function, const int line if(ptr == NULL) logg("FATAL: Trying to free NULL pointer in %s() (%s:%i)", function, file, line); - // We intentionally run free() nevertheless to see the crash in the debugger free(ptr); } diff --git a/src/syscalls/realloc.c b/src/syscalls/realloc.c index 2c5786cc..ff73da45 100644 --- a/src/syscalls/realloc.c +++ b/src/syscalls/realloc.c @@ -25,7 +25,17 @@ void __attribute__((alloc_size(2))) *FTLrealloc(void *ptr_in, const size_t size, // NULL, it must have been returned by an earlier call to malloc(), cal‐ // loc() or realloc(). If the area pointed to was moved, a free(ptr) is // done. - void *ptr_out = realloc(ptr_in, size); + void *ptr_out = NULL; + do + { + errno = 0; + ptr_out = realloc(ptr_in, size); + } + // Try again to allocate memory if this failed due to an interruption by + // an incoming signal + while(ptr_out == NULL && errno == EINTR); + + // Handle other errors than EINTR if(ptr_out == NULL) logg("FATAL: Memory reallocation (%p -> %zu) failed in %s() (%s:%i)", ptr_in, size, function, file, line); diff --git a/src/syscalls/strdup.c b/src/syscalls/strdup.c index 8730af0f..e71d4a7a 100644 --- a/src/syscalls/strdup.c +++ b/src/syscalls/strdup.c @@ -12,7 +12,6 @@ //#include "syscalls.h" is implicitly done in FTL.h #include "../log.h" -#undef strdup char* __attribute__((malloc)) FTLstrdup(const char *src, const char * file, const char * function, const int line) { // The FTLstrdup() function returns a pointer to a new string which is a @@ -24,12 +23,13 @@ char* __attribute__((malloc)) FTLstrdup(const char *src, const char * file, cons return NULL; } const size_t len = strlen(src); - char *dest = calloc(len+1, sizeof(char)); + char *dest = FTLcalloc(len+1, sizeof(char), file, function, line); + + // Return early in case of an unrecoverable error, error reporting has + // already been done in FTLcalloc() if(dest == NULL) - { - logg("FATAL: Memory allocation failed in %s() (%s:%i)", function, file, line); return NULL; - } + // Use memcpy as memory areas cannot overlap memcpy(dest, src, len); dest[len] = '\0'; From 1a0df27d28af6d38f3f3ccef981a3860216b8636 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 18:52:40 +0100 Subject: [PATCH 06/26] Add interrupt-safe write() routine Signed-off-by: DL6ER --- src/FTL.h | 1 + src/syscalls/CMakeLists.txt | 1 + src/syscalls/syscalls.h | 1 + src/syscalls/write.c | 45 +++++++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 src/syscalls/write.c diff --git a/src/FTL.h b/src/FTL.h index d508523d..a8672382 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -128,6 +128,7 @@ #define fprintf(stream, format, ...) FTLfprintf(stream, format, ##__VA_ARGS__) #define vprintf(format, args) FTLvfprintf(stdout, format, args) #define vfprintf(stream, format, args) FTLvfprintf(stream, format, args) +#define write(fd, buf, n) FTLwrite(fd, buf, n, __FILE__, __FUNCTION__, __LINE__) #include "syscalls/syscalls.h" // Preprocessor help functions diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index c38f86cb..aaa2b9e4 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -16,6 +16,7 @@ set(sources strdup.c syscalls.h vfprintf.c + write.c ) add_library(syscalls OBJECT ${sources}) diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index a94ca940..591a0b4f 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -16,5 +16,6 @@ void *FTLrealloc(void *ptr_in, size_t size, const char *file, const char *functi void FTLfree(void *ptr, const char* file, const char *function, const int line); int FTLfprintf(FILE *stream, const char *format, ...) __attribute__ ((format (gnu_printf, 2, 3))); int FTLvfprintf(FILE *stream, const char *format, va_list args) __attribute__ ((format (gnu_printf, 2, 0))); +ssize_t FTLwrite(int fd, const void *buf, size_t total, const char * file, const char * function, const int line); #endif //SYSCALLS_H diff --git a/src/syscalls/write.c b/src/syscalls/write.c new file mode 100644 index 00000000..76b606b9 --- /dev/null +++ b/src/syscalls/write.c @@ -0,0 +1,45 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for write +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +ssize_t FTLwrite(int fd, const void *buf, size_t total, const char * file, const char * function, const int line) +{ + if(buf == NULL) + { + logg("ERROR: Trying to write a NULL string in %s() (%s:%i)", function, file, line); + return 0; + } + + ssize_t ret = 0; + size_t written = 0; + do + { + // Reset errno before trying to write + errno = 0; + ret = write(fd, buf, total); + if(ret > 0) + written += ret; + } + // Try to write the remaining content into the stream if + // (a) we haven't written all the data, however, there was no other error + // (b) the last write() call failed due to an interruption by an incoming signal + while((written < total && errno == 0) || (ret < 0 && errno == EINTR)); + + // Final error checking (may have faild for some other reason then an + // EINTR = interrupted system call) + if(written < total) + logg("WARN: Could not write() everything in %s() (%s:%i): %s", + function, file, line, strerror(errno)); + + return written; +} \ No newline at end of file From e23eb128ec592528184d5a9e116ceb0b26e150c8 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 18:57:16 +0100 Subject: [PATCH 07/26] Add interrupt-safe accept() routine Signed-off-by: DL6ER --- src/FTL.h | 1 + src/syscalls/CMakeLists.txt | 1 + src/syscalls/accept.c | 35 +++++++++++++++++++++++++++++++++++ src/syscalls/syscalls.h | 1 + 4 files changed, 38 insertions(+) create mode 100644 src/syscalls/accept.c diff --git a/src/FTL.h b/src/FTL.h index a8672382..709f1bf1 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -129,6 +129,7 @@ #define vprintf(format, args) FTLvfprintf(stdout, format, args) #define vfprintf(stream, format, args) FTLvfprintf(stream, format, args) #define write(fd, buf, n) FTLwrite(fd, buf, n, __FILE__, __FUNCTION__, __LINE__) +#define accept(sockfd, addr, addrlen) FTLaccept(sockfd, addr, addrlen, __FILE__, __FUNCTION__, __LINE__) #include "syscalls/syscalls.h" // Preprocessor help functions diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index aaa2b9e4..67b49dc9 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -9,6 +9,7 @@ # Please see LICENSE file for your rights under this license. set(sources + accept.c calloc.c fprintf.c free.c diff --git a/src/syscalls/accept.c b/src/syscalls/accept.c new file mode 100644 index 00000000..0fc7e0a0 --- /dev/null +++ b/src/syscalls/accept.c @@ -0,0 +1,35 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for accept +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char * file, const char * function, const int line) +{ + int ret = 0; + do + { + // Reset errno before trying to write + errno = 0; + ret = accept(sockfd, addr, addrlen); + } + // Try again if the last accept() call failed due to an interruption by an + // incoming signal + while(ret < 0 && errno == EINTR); + + // Final error checking (may have faild for some other reason then an + // EINTR = interrupted system call) + if(ret < 0) + logg("WARN: Could not accept() in %s() (%s:%i): %s", + function, file, line, strerror(errno)); + + return ret; +} \ No newline at end of file diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index 591a0b4f..fa16a58e 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -17,5 +17,6 @@ void FTLfree(void *ptr, const char* file, const char *function, const int line); int FTLfprintf(FILE *stream, const char *format, ...) __attribute__ ((format (gnu_printf, 2, 3))); int FTLvfprintf(FILE *stream, const char *format, va_list args) __attribute__ ((format (gnu_printf, 2, 0))); ssize_t FTLwrite(int fd, const void *buf, size_t total, const char * file, const char * function, const int line); +int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char * file, const char * function, const int line); #endif //SYSCALLS_H From 06396bab5c1f885069dcd965074826794bb46981 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 19:01:18 +0100 Subject: [PATCH 08/26] Avoid redundant error reporting Signed-off-by: DL6ER --- src/FTL.h | 2 -- src/api/msgpack.c | 22 +++++++++++----------- src/api/socket.c | 12 +++--------- src/api/socket.h | 1 - 4 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/FTL.h b/src/FTL.h index 709f1bf1..e3323876 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -119,8 +119,6 @@ // caused by insufficient memory or by code bugs (not properly dealing // with NULL pointers) much easier. #define free(ptr) FTLfree(ptr, __FILE__, __FUNCTION__, __LINE__) -#define lib_strdup() strdup() -#undef strdup #define strdup(str_in) FTLstrdup(str_in, __FILE__, __FUNCTION__, __LINE__) #define calloc(numer_of_elements, element_size) FTLcalloc(numer_of_elements, element_size, __FILE__, __FUNCTION__, __LINE__) #define realloc(ptr, new_size) FTLrealloc(ptr, new_size, __FILE__, __FUNCTION__, __LINE__) diff --git a/src/api/msgpack.c b/src/api/msgpack.c index eae1ff53..ede6065f 100644 --- a/src/api/msgpack.c +++ b/src/api/msgpack.c @@ -16,12 +16,12 @@ void pack_eom(const int sock) { // This byte is explicitly never used in the MessagePack spec, so it is perfect to use as an EOM for this API. uint8_t eom = 0xc1; - swrite(sock, &eom, sizeof(eom)); + write(sock, &eom, sizeof(eom)); } static void pack_basic(const int sock, const uint8_t format, const void *value, const size_t size) { - swrite(sock, &format, sizeof(format)); - swrite(sock, value, size); + write(sock, &format, sizeof(format)); + write(sock, value, size); } static uint64_t __attribute__((const)) leToBe64(const uint64_t value) { @@ -42,7 +42,7 @@ static uint64_t __attribute__((const)) leToBe64(const uint64_t value) { void pack_bool(const int sock, const bool value) { uint8_t packed = (uint8_t) (value ? 0xc3 : 0xc2); - swrite(sock, &packed, sizeof(packed)); + write(sock, &packed, sizeof(packed)); } void pack_uint8(const int sock, const uint8_t value) { @@ -87,8 +87,8 @@ bool pack_fixstr(const int sock, const char *string) { } const uint8_t format = (uint8_t) (0xA0 | length); - swrite(sock, &format, sizeof(format)); - swrite(sock, string, length); + write(sock, &format, sizeof(format)); + write(sock, string, length); return true; } @@ -104,17 +104,17 @@ bool pack_str32(const int sock, const char *string) { } const uint8_t format = 0xdb; - swrite(sock, &format, sizeof(format)); + write(sock, &format, sizeof(format)); const uint32_t bigELength = htonl((uint32_t) length); - swrite(sock, &bigELength, sizeof(bigELength)); - swrite(sock, string, length); + write(sock, &bigELength, sizeof(bigELength)); + write(sock, string, length); return true; } void pack_map16_start(const int sock, const uint16_t length) { const uint8_t format = 0xde; - swrite(sock, &format, sizeof(format)); + write(sock, &format, sizeof(format)); const uint16_t bigELength = htons(length); - swrite(sock, &bigELength, sizeof(bigELength)); + write(sock, &bigELength, sizeof(bigELength)); } diff --git a/src/api/socket.c b/src/api/socket.c index 3eb8e0d0..2201dbbf 100644 --- a/src/api/socket.c +++ b/src/api/socket.c @@ -222,21 +222,15 @@ void __attribute__ ((format (gnu_printf, 2, 3))) ssend(const int sock, const cha char *buffer; va_list args; va_start(args, format); - int ret = vasprintf(&buffer, format, args); + int bytes = vasprintf(&buffer, format, args); va_end(args); - if(ret > 0) + if(bytes > 0 && buffer != NULL) { - if(!write(sock, buffer, strlen(buffer))) - logg("WARNING: Socket write returned error %s (%i)", strerror(errno), errno); + write(sock, buffer, bytes); free(buffer); } } -void swrite(const int sock, const void *value, size_t size) { - if(write(sock, value, size) == -1) - logg("WARNING: Socket write returned error code %i", errno); -} - static inline int checkClientLimit(const int socket) { if(socket < MAXCONNS) { diff --git a/src/api/socket.h b/src/api/socket.h index 630ba960..bfb7150f 100644 --- a/src/api/socket.h +++ b/src/api/socket.h @@ -15,7 +15,6 @@ void close_telnet_socket(void); void close_unix_socket(bool unlink_file); void seom(const int sock); void ssend(const int sock, const char *format, ...) __attribute__ ((format (gnu_printf, 2, 3))); -void swrite(const int sock, const void* value, const size_t size); void *telnet_listening_thread_IPv4(void *args); void *telnet_listening_thread_IPv6(void *args); void *socket_listening_thread(void *args); From b00548edb9db309759dd3cc4d14ae2ca08337e65 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 19:21:46 +0100 Subject: [PATCH 09/26] Improve printf(), fprintf(), vprintf(), and vfprintf() error reporting Signed-off-by: DL6ER --- src/FTL.h | 8 ++-- src/syscalls/accept.c | 4 +- src/syscalls/calloc.c | 6 +-- src/syscalls/fprintf.c | 4 +- src/syscalls/free.c | 4 +- src/syscalls/realloc.c | 13 +++--- src/syscalls/strdup.c | 6 +-- src/syscalls/syscalls.h | 21 +++++---- src/syscalls/vfprintf.c | 101 ++++++++++++++++++++++++++++++++++------ src/syscalls/write.c | 8 ++-- 10 files changed, 127 insertions(+), 48 deletions(-) diff --git a/src/FTL.h b/src/FTL.h index e3323876..aec2c3ce 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -122,10 +122,10 @@ #define strdup(str_in) FTLstrdup(str_in, __FILE__, __FUNCTION__, __LINE__) #define calloc(numer_of_elements, element_size) FTLcalloc(numer_of_elements, element_size, __FILE__, __FUNCTION__, __LINE__) #define realloc(ptr, new_size) FTLrealloc(ptr, new_size, __FILE__, __FUNCTION__, __LINE__) -#define printf(format, ...) FTLfprintf(stdout, format, ##__VA_ARGS__) -#define fprintf(stream, format, ...) FTLfprintf(stream, format, ##__VA_ARGS__) -#define vprintf(format, args) FTLvfprintf(stdout, format, args) -#define vfprintf(stream, format, args) FTLvfprintf(stream, format, args) +#define printf(format, ...) FTLfprintf(stdout, __FILE__, __FUNCTION__, __LINE__, format, ##__VA_ARGS__) +#define fprintf(stream, format, ...) FTLfprintf(stream, __FILE__, __FUNCTION__, __LINE__, format, ##__VA_ARGS__) +#define vprintf(format, args) FTLvfprintf(stdout, __FILE__, __FUNCTION__, __LINE__, format, args) +#define vfprintf(stream, format, args) FTLvfprintf(stream, __FILE__, __FUNCTION__, __LINE__, format, args) #define write(fd, buf, n) FTLwrite(fd, buf, n, __FILE__, __FUNCTION__, __LINE__) #define accept(sockfd, addr, addrlen) FTLaccept(sockfd, addr, addrlen, __FILE__, __FUNCTION__, __LINE__) #include "syscalls/syscalls.h" diff --git a/src/syscalls/accept.c b/src/syscalls/accept.c index 0fc7e0a0..8dc12d21 100644 --- a/src/syscalls/accept.c +++ b/src/syscalls/accept.c @@ -12,7 +12,7 @@ //#include "syscalls.h" is implicitly done in FTL.h #include "../log.h" -int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char * file, const char * function, const int line) +int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char *file, const char *func, const int line) { int ret = 0; do @@ -29,7 +29,7 @@ int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char // EINTR = interrupted system call) if(ret < 0) logg("WARN: Could not accept() in %s() (%s:%i): %s", - function, file, line, strerror(errno)); + func, file, line, strerror(errno)); return ret; } \ No newline at end of file diff --git a/src/syscalls/calloc.c b/src/syscalls/calloc.c index 4eab1b3c..b79ad5fd 100644 --- a/src/syscalls/calloc.c +++ b/src/syscalls/calloc.c @@ -13,9 +13,9 @@ #include "../log.h" #undef calloc -void* __attribute__((malloc)) __attribute__((alloc_size(1,2))) FTLcalloc(const size_t nmemb, const size_t size, const char * file, const char * function, const int line) +void* __attribute__((malloc)) __attribute__((alloc_size(1,2))) FTLcalloc(const size_t nmemb, const size_t size, const char *file, const char *func, const int line) { - // The FTLcalloc() function allocates memory for an array of nmemb elements + // The FTLcalloc() func allocates memory for an array of nmemb elements // of size bytes each and returns a pointer to the allocated memory. The // memory is set to zero. If nmemb or size is 0, then calloc() returns // either NULL, or a unique pointer value that can later be successfully @@ -33,7 +33,7 @@ void* __attribute__((malloc)) __attribute__((alloc_size(1,2))) FTLcalloc(const s // Handle other errors than EINTR if(ptr == NULL) logg("FATAL: Memory allocation (%zu x %zu) failed in %s() (%s:%i)", - nmemb, size, function, file, line); + nmemb, size, func, file, line); return ptr; } diff --git a/src/syscalls/fprintf.c b/src/syscalls/fprintf.c index e8016c88..90b88652 100644 --- a/src/syscalls/fprintf.c +++ b/src/syscalls/fprintf.c @@ -12,11 +12,11 @@ //#include "syscalls.h" is implicitly done in FTL.h #include "../log.h" -int FTLfprintf(FILE *stream, const char *format, ...) +int FTLfprintf(FILE *stream, const char* file, const char *func, const int line, const char *format, ...) { va_list args; va_start(args, format); - const int length = FTLvfprintf(stream, format, args); + const int length = FTLvfprintf(stream, file, func, line, format, args); va_end(args); return length; diff --git a/src/syscalls/free.c b/src/syscalls/free.c index 56ccc4ae..da08daf1 100644 --- a/src/syscalls/free.c +++ b/src/syscalls/free.c @@ -13,14 +13,14 @@ #include "../log.h" #undef free -void FTLfree(void *ptr, const char * file, const char * function, const int line) +void FTLfree(void *ptr, const char *file, const char *func, const int line) { // The free() function frees the memory space pointed to by ptr, which // must have been returned by a previous call to malloc(), calloc(), or // realloc(). Otherwise, or if free(ptr) has already been called before, // undefined behavior occurs. If ptr is NULL, no operation is performed. if(ptr == NULL) - logg("FATAL: Trying to free NULL pointer in %s() (%s:%i)", function, file, line); + logg("FATAL: Trying to free NULL pointer in %s() (%s:%i)", func, file, line); free(ptr); } diff --git a/src/syscalls/realloc.c b/src/syscalls/realloc.c index ff73da45..53df93b1 100644 --- a/src/syscalls/realloc.c +++ b/src/syscalls/realloc.c @@ -13,18 +13,17 @@ #include "../log.h" #undef realloc -void __attribute__((alloc_size(2))) *FTLrealloc(void *ptr_in, const size_t size, const char * file, const char * function, const int line) +void __attribute__((alloc_size(2))) *FTLrealloc(void *ptr_in, const size_t size, const char * file, const char * func, const int line) { // The FTLrealloc() function changes the size of the memory block pointed to // by ptr to size bytes. The contents will be unchanged in the range from // the start of the region up to the minimum of the old and new sizes. If // the new size is larger than the old size, the added memory will not be // initialized. If ptr is NULL, then the call is equivalent to malloc(size), - // for all values of size; if size is equal to zero, and ptr is - // not NULL, then the call is equivalent to free(ptr). Unless ptr is - // NULL, it must have been returned by an earlier call to malloc(), cal‐ - // loc() or realloc(). If the area pointed to was moved, a free(ptr) is - // done. + // for all values of size; if size is equal to zero, and ptr is not NULL, + // then the call is equivalent to free(ptr). Unless ptr is NULL, it must + // have been returned by an earlier call to malloc(), calloc() or realloc(). + // If the area pointed to was moved, a free(ptr) is done implicitly. void *ptr_out = NULL; do { @@ -38,7 +37,7 @@ void __attribute__((alloc_size(2))) *FTLrealloc(void *ptr_in, const size_t size, // Handle other errors than EINTR if(ptr_out == NULL) logg("FATAL: Memory reallocation (%p -> %zu) failed in %s() (%s:%i)", - ptr_in, size, function, file, line); + ptr_in, size, func, file, line); return ptr_out; } \ No newline at end of file diff --git a/src/syscalls/strdup.c b/src/syscalls/strdup.c index e71d4a7a..cb3543de 100644 --- a/src/syscalls/strdup.c +++ b/src/syscalls/strdup.c @@ -12,18 +12,18 @@ //#include "syscalls.h" is implicitly done in FTL.h #include "../log.h" -char* __attribute__((malloc)) FTLstrdup(const char *src, const char * file, const char * function, const int line) +char* __attribute__((malloc)) FTLstrdup(const char *src, const char *file, const char *func, const int line) { // The FTLstrdup() function returns a pointer to a new string which is a // duplicate of the string s. Memory for the new string is obtained with // calloc(3), and can be freed with free(3). if(src == NULL) { - logg("WARN: Trying to copy a NULL string in %s() (%s:%i)", function, file, line); + logg("WARN: Trying to copy a NULL string in %s() (%s:%i)", func, file, line); return NULL; } const size_t len = strlen(src); - char *dest = FTLcalloc(len+1, sizeof(char), file, function, line); + char *dest = FTLcalloc(len+1, sizeof(char), file, func, line); // Return early in case of an unrecoverable error, error reporting has // already been done in FTLcalloc() diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index fa16a58e..7351c348 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -10,13 +10,18 @@ #ifndef SYSCALLS_H #define SYSCALLS_H -char *FTLstrdup(const char *src, const char *file, const char *function, const int line) __attribute__((malloc)); -void *FTLcalloc(size_t n, size_t size, const char *file, const char *function, const int line) __attribute__((malloc)) __attribute__((alloc_size(1,2))); -void *FTLrealloc(void *ptr_in, size_t size, const char *file, const char *function, const int line) __attribute__((alloc_size(2))); -void FTLfree(void *ptr, const char* file, const char *function, const int line); -int FTLfprintf(FILE *stream, const char *format, ...) __attribute__ ((format (gnu_printf, 2, 3))); -int FTLvfprintf(FILE *stream, const char *format, va_list args) __attribute__ ((format (gnu_printf, 2, 0))); -ssize_t FTLwrite(int fd, const void *buf, size_t total, const char * file, const char * function, const int line); -int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char * file, const char * function, const int line); +// Interrupt-safe memory routines +char *FTLstrdup(const char *src, const char *file, const char *func, const int line) __attribute__((malloc)); +void *FTLcalloc(size_t n, size_t size, const char *file, const char *func, const int line) __attribute__((malloc)) __attribute__((alloc_size(1,2))); +void *FTLrealloc(void *ptr_in, size_t size, const char *file, const char *func, const int line) __attribute__((alloc_size(2))); +void FTLfree(void *ptr, const char*file, const char *func, const int line); + +// Interrupt-safe printing routines +int FTLfprintf(FILE *stream, const char*file, const char *func, const int line, const char *format, ...) __attribute__ ((format (gnu_printf, 5, 6))); +int FTLvfprintf(FILE *stream, const char*file, const char *func, const int line, const char *format, va_list args) __attribute__ ((format (gnu_printf, 5, 0))); + +// Interrupt-safe socket routines +ssize_t FTLwrite(int fd, const void *buf, size_t total, const char *file, const char *func, const int line); +int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char *file, const char *func, const int line); #endif //SYSCALLS_H diff --git a/src/syscalls/vfprintf.c b/src/syscalls/vfprintf.c index 96de1cf2..501791ed 100644 --- a/src/syscalls/vfprintf.c +++ b/src/syscalls/vfprintf.c @@ -12,7 +12,90 @@ //#include "syscalls.h" is implicitly done in FTL.h #include "../log.h" -int FTLvfprintf(FILE *stream, const char *format, va_list args) +// itoa implementation using only static memory +// taken from Kernighan and Ritchie's "The C Programming Language" +// see https://clc-wiki.net/wiki/K&R2_solutions:Chapter_3:Exercise_4 +// This implementation has its drawbacks, however, we only use it for +// automated conversion of code line numbers to strings so we're not +// interested in its performance outside the range of [1, 10'000] +static void itoa(int n, char s[]) +{ + int i = 0, sign = n; + + // Make n positive if negative + if (sign < 0) + n = -n; + + // Generate digits in reverse order + do + { + s[i++] = n % 10 + '0'; /* get next digit */ + } while ((n /= 10) > 0); /* delete it */ + + // Add sign (if needed) + if (sign < 0) + s[i++] = '-'; + + // Rero-terminate string + s[i] = '\0'; + + // Reverse string s in place + int j; + char c; + int len = strlen(s); + for (i = 0, j = len-1; i Date: Wed, 9 Dec 2020 19:30:28 +0100 Subject: [PATCH 10/26] Add interrupt-safe recv() routine Signed-off-by: DL6ER --- src/FTL.h | 1 + src/syscalls/CMakeLists.txt | 1 + src/syscalls/recv.c | 37 +++++++++++++++++++++++++++++++++++++ src/syscalls/syscalls.h | 1 + 4 files changed, 40 insertions(+) create mode 100644 src/syscalls/recv.c diff --git a/src/FTL.h b/src/FTL.h index aec2c3ce..41685e76 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -128,6 +128,7 @@ #define vfprintf(stream, format, args) FTLvfprintf(stream, __FILE__, __FUNCTION__, __LINE__, format, args) #define write(fd, buf, n) FTLwrite(fd, buf, n, __FILE__, __FUNCTION__, __LINE__) #define accept(sockfd, addr, addrlen) FTLaccept(sockfd, addr, addrlen, __FILE__, __FUNCTION__, __LINE__) +#define recv(sockfd, buf, len, flags) FTLrecv(sockfd, buf, len, flags, __FILE__, __FUNCTION__, __LINE__) #include "syscalls/syscalls.h" // Preprocessor help functions diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index 67b49dc9..ba7f763c 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -14,6 +14,7 @@ set(sources fprintf.c free.c realloc.c + recv.c strdup.c syscalls.h vfprintf.c diff --git a/src/syscalls/recv.c b/src/syscalls/recv.c new file mode 100644 index 00000000..7c274a06 --- /dev/null +++ b/src/syscalls/recv.c @@ -0,0 +1,37 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for recv +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +#include + +int FTLrecv(int sockfd, void *buf, size_t len, int flags, const char *file, const char *func, const int line) +{ + int ret = 0; + do + { + // Reset errno before trying to write + errno = 0; + ret = recv(sockfd, buf, len, flags); + } + // Try again if the last accept() call failed due to an interruption by an + // incoming signal + while(ret < 0 && errno == EINTR); + + // Final error checking (may have faild for some other reason then an + // EINTR = interrupted system call) + if(ret < 0) + logg("WARN: Could not recv() in %s() (%s:%i): %s", + func, file, line, strerror(errno)); + + return ret; +} \ No newline at end of file diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index 7351c348..15a1f844 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -23,5 +23,6 @@ int FTLvfprintf(FILE *stream, const char*file, const char *func, const int line, // Interrupt-safe socket routines ssize_t FTLwrite(int fd, const void *buf, size_t total, const char *file, const char *func, const int line); int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char *file, const char *func, const int line); +int FTLrecv(int sockfd, void *buf, size_t len, int flags, const char *file, const char *func, const int line); #endif //SYSCALLS_H From 3dfc0698dda9b4d97d5951dac12119b32a100434 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 19:35:33 +0100 Subject: [PATCH 11/26] Add interrupt-safe recvfrom() routine Signed-off-by: DL6ER --- src/FTL.h | 1 + src/syscalls/CMakeLists.txt | 1 + src/syscalls/recv.c | 4 ++-- src/syscalls/recvfrom.c | 38 +++++++++++++++++++++++++++++++++++++ src/syscalls/syscalls.h | 3 ++- 5 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 src/syscalls/recvfrom.c diff --git a/src/FTL.h b/src/FTL.h index 41685e76..9b936930 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -129,6 +129,7 @@ #define write(fd, buf, n) FTLwrite(fd, buf, n, __FILE__, __FUNCTION__, __LINE__) #define accept(sockfd, addr, addrlen) FTLaccept(sockfd, addr, addrlen, __FILE__, __FUNCTION__, __LINE__) #define recv(sockfd, buf, len, flags) FTLrecv(sockfd, buf, len, flags, __FILE__, __FUNCTION__, __LINE__) +#define recvfrom(sockfd, buf, len, flags, src_addr, addrlen) FTLrecvfrom(sockfd, buf, len, flags, src_addr, addrlen, __FILE__, __FUNCTION__, __LINE__) #include "syscalls/syscalls.h" // Preprocessor help functions diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index ba7f763c..178c7467 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -15,6 +15,7 @@ set(sources free.c realloc.c recv.c + recvfrom.c strdup.c syscalls.h vfprintf.c diff --git a/src/syscalls/recv.c b/src/syscalls/recv.c index 7c274a06..404da899 100644 --- a/src/syscalls/recv.c +++ b/src/syscalls/recv.c @@ -14,9 +14,9 @@ #include -int FTLrecv(int sockfd, void *buf, size_t len, int flags, const char *file, const char *func, const int line) +ssize_t FTLrecv(int sockfd, void *buf, size_t len, int flags, const char *file, const char *func, const int line) { - int ret = 0; + ssize_t ret = 0; do { // Reset errno before trying to write diff --git a/src/syscalls/recvfrom.c b/src/syscalls/recvfrom.c new file mode 100644 index 00000000..347194a8 --- /dev/null +++ b/src/syscalls/recvfrom.c @@ -0,0 +1,38 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for recvfrom +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +#include +#include + +ssize_t FTLrecvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen, const char *file, const char *func, const int line) +{ + ssize_t ret = 0; + do + { + // Reset errno before trying to write + errno = 0; + ret = recvfrom(sockfd, buf, len, flags, src_addr, addrlen); + } + // Try again if the last accept() call failed due to an interruption by an + // incoming signal + while(ret < 0 && errno == EINTR); + + // Final error checking (may have faild for some other reason then an + // EINTR = interrupted system call) + if(ret < 0) + logg("WARN: Could not recvfrom() in %s() (%s:%i): %s", + func, file, line, strerror(errno)); + + return ret; +} \ No newline at end of file diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index 15a1f844..caa116e1 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -23,6 +23,7 @@ int FTLvfprintf(FILE *stream, const char*file, const char *func, const int line, // Interrupt-safe socket routines ssize_t FTLwrite(int fd, const void *buf, size_t total, const char *file, const char *func, const int line); int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char *file, const char *func, const int line); -int FTLrecv(int sockfd, void *buf, size_t len, int flags, const char *file, const char *func, const int line); +ssize_t FTLrecv(int sockfd, void *buf, size_t len, int flags, const char *file, const char *func, const int line); +ssize_t FTLrecvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen, const char *file, const char *func, const int line); #endif //SYSCALLS_H From 2c35038d578a7185a5faca27193397f4ac1c343f Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 19:44:18 +0100 Subject: [PATCH 12/26] Add interrupt-safe pthread_mutex_lock() routine Signed-off-by: DL6ER --- src/FTL.h | 1 + src/syscalls/CMakeLists.txt | 1 + src/syscalls/pthread_mutex_lock.c | 37 +++++++++++++++++++++++++++++++ src/syscalls/syscalls.h | 3 +++ 4 files changed, 42 insertions(+) create mode 100644 src/syscalls/pthread_mutex_lock.c diff --git a/src/FTL.h b/src/FTL.h index 9b936930..8c9c67f0 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -130,6 +130,7 @@ #define accept(sockfd, addr, addrlen) FTLaccept(sockfd, addr, addrlen, __FILE__, __FUNCTION__, __LINE__) #define recv(sockfd, buf, len, flags) FTLrecv(sockfd, buf, len, flags, __FILE__, __FUNCTION__, __LINE__) #define recvfrom(sockfd, buf, len, flags, src_addr, addrlen) FTLrecvfrom(sockfd, buf, len, flags, src_addr, addrlen, __FILE__, __FUNCTION__, __LINE__) +#define pthread_mutex_lock(mutex) FTLpthread_mutex_lock(mutex, __FILE__, __FUNCTION__, __LINE__) #include "syscalls/syscalls.h" // Preprocessor help functions diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index 178c7467..2039c251 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -13,6 +13,7 @@ set(sources calloc.c fprintf.c free.c + pthread_mutex_lock.c realloc.c recv.c recvfrom.c diff --git a/src/syscalls/pthread_mutex_lock.c b/src/syscalls/pthread_mutex_lock.c new file mode 100644 index 00000000..01d024de --- /dev/null +++ b/src/syscalls/pthread_mutex_lock.c @@ -0,0 +1,37 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for pthread_mutex_lock +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +#include + +int FTLpthread_mutex_lock(pthread_mutex_t *__mutex, const char *file, const char *func, const int line) +{ + ssize_t ret = 0; + do + { + // Reset errno before trying to write + errno = 0; + ret = pthread_mutex_lock(__mutex); + } + // Try again if the last accept() call failed due to an interruption by an + // incoming signal + while(ret < 0 && errno == EINTR); + + // Final error checking (may have faild for some other reason then an + // EINTR = interrupted system call) + if(ret < 0) + logg("WARN: Could not pthread_mutex_lock() in %s() (%s:%i): %s", + func, file, line, strerror(errno)); + + return ret; +} \ No newline at end of file diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index caa116e1..4243265b 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -26,4 +26,7 @@ int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char ssize_t FTLrecv(int sockfd, void *buf, size_t len, int flags, const char *file, const char *func, const int line); ssize_t FTLrecvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen, const char *file, const char *func, const int line); +// Interrupt-safe thread routines +int FTLpthread_mutex_lock(pthread_mutex_t *__mutex, const char *file, const char *func, const int line); + #endif //SYSCALLS_H From ffdc52a1d1e4f8f82e83e49701d62fd33e77aa52 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 19:52:19 +0100 Subject: [PATCH 13/26] Add interrupt-safe select() routine Signed-off-by: DL6ER --- src/FTL.h | 1 + src/syscalls/CMakeLists.txt | 1 + src/syscalls/select.c | 37 +++++++++++++++++++++++++++++++++++++ src/syscalls/syscalls.h | 3 +++ 4 files changed, 42 insertions(+) create mode 100644 src/syscalls/select.c diff --git a/src/FTL.h b/src/FTL.h index 8c9c67f0..ef2398d9 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -130,6 +130,7 @@ #define accept(sockfd, addr, addrlen) FTLaccept(sockfd, addr, addrlen, __FILE__, __FUNCTION__, __LINE__) #define recv(sockfd, buf, len, flags) FTLrecv(sockfd, buf, len, flags, __FILE__, __FUNCTION__, __LINE__) #define recvfrom(sockfd, buf, len, flags, src_addr, addrlen) FTLrecvfrom(sockfd, buf, len, flags, src_addr, addrlen, __FILE__, __FUNCTION__, __LINE__) +#define select(nfds, readfds, writefds, exceptfds, timeout) FTLselect(nfds, readfds, writefds, exceptfds, timeout, __FILE__, __FUNCTION__, __LINE__) #define pthread_mutex_lock(mutex) FTLpthread_mutex_lock(mutex, __FILE__, __FUNCTION__, __LINE__) #include "syscalls/syscalls.h" diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index 2039c251..46a8689a 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -17,6 +17,7 @@ set(sources realloc.c recv.c recvfrom.c + select.c strdup.c syscalls.h vfprintf.c diff --git a/src/syscalls/select.c b/src/syscalls/select.c new file mode 100644 index 00000000..83f676ec --- /dev/null +++ b/src/syscalls/select.c @@ -0,0 +1,37 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for select +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +#include + +int FTLselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout, const char *file, const char *func, const int line) +{ + int ret = 0; + do + { + // Reset errno before trying to write + errno = 0; + ret = select(nfds, readfds, writefds, exceptfds, timeout); + } + // Try again if the last accept() call failed due to an interruption by an + // incoming signal + while(ret < 0 && errno == EINTR); + + // Final error checking (may have faild for some other reason then an + // EINTR = interrupted system call) + if(ret < 0) + logg("WARN: Could not select() in %s() (%s:%i): %s", + func, file, line, strerror(errno)); + + return ret; +} \ No newline at end of file diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index 4243265b..53ec360c 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -17,7 +17,9 @@ void *FTLrealloc(void *ptr_in, size_t size, const char *file, const char *func, void FTLfree(void *ptr, const char*file, const char *func, const int line); // Interrupt-safe printing routines +// printf() is derived from fprintf(stdout, ...) int FTLfprintf(FILE *stream, const char*file, const char *func, const int line, const char *format, ...) __attribute__ ((format (gnu_printf, 5, 6))); +// vprintf() is derived from vfprintf(stdout, ...) int FTLvfprintf(FILE *stream, const char*file, const char *func, const int line, const char *format, va_list args) __attribute__ ((format (gnu_printf, 5, 0))); // Interrupt-safe socket routines @@ -25,6 +27,7 @@ ssize_t FTLwrite(int fd, const void *buf, size_t total, const char *file, const int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char *file, const char *func, const int line); ssize_t FTLrecv(int sockfd, void *buf, size_t len, int flags, const char *file, const char *func, const int line); ssize_t FTLrecvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen, const char *file, const char *func, const int line); +int FTLselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout, const char *file, const char *func, const int line); // Interrupt-safe thread routines int FTLpthread_mutex_lock(pthread_mutex_t *__mutex, const char *file, const char *func, const int line); From 67b1a65464f883e23a66af7176106e977396623c Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 19:58:27 +0100 Subject: [PATCH 14/26] Add interrupt-safe fopen() routine Signed-off-by: DL6ER --- src/FTL.h | 1 + src/syscalls/CMakeLists.txt | 1 + src/syscalls/fopen.c | 35 +++++++++++++++++++++++++++++++++++ src/syscalls/syscalls.h | 3 +++ 4 files changed, 40 insertions(+) create mode 100644 src/syscalls/fopen.c diff --git a/src/FTL.h b/src/FTL.h index ef2398d9..3e211e3a 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -132,6 +132,7 @@ #define recvfrom(sockfd, buf, len, flags, src_addr, addrlen) FTLrecvfrom(sockfd, buf, len, flags, src_addr, addrlen, __FILE__, __FUNCTION__, __LINE__) #define select(nfds, readfds, writefds, exceptfds, timeout) FTLselect(nfds, readfds, writefds, exceptfds, timeout, __FILE__, __FUNCTION__, __LINE__) #define pthread_mutex_lock(mutex) FTLpthread_mutex_lock(mutex, __FILE__, __FUNCTION__, __LINE__) +#define fopen(pathname, mode) FTLfopen(pathname, mode, __FILE__, __FUNCTION__, __LINE__) #include "syscalls/syscalls.h" // Preprocessor help functions diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index 46a8689a..0c105497 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -11,6 +11,7 @@ set(sources accept.c calloc.c + fopen.c fprintf.c free.c pthread_mutex_lock.c diff --git a/src/syscalls/fopen.c b/src/syscalls/fopen.c new file mode 100644 index 00000000..81c47520 --- /dev/null +++ b/src/syscalls/fopen.c @@ -0,0 +1,35 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for fopen +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +FILE *FTLfopen(const char *pathname, const char *mode, const char *file, const char *func, const int line) +{ + FILE *file_ptr = 0; + do + { + // Reset errno before trying to write + errno = 0; + file_ptr = fopen(pathname, mode); + } + // Try again if the last accept() call failed due to an interruption by an + // incoming signal + while(file_ptr == NULL && errno == EINTR); + + // Final error checking (may have faild for some other reason then an + // EINTR = interrupted system call) + if(file_ptr == NULL) + logg("WARN: Could not fopen(%s, %s) in %s() (%s:%i): %s", + pathname, mode, func, file, line, strerror(errno)); + + return file_ptr; +} \ No newline at end of file diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index 53ec360c..f14d04fa 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -32,4 +32,7 @@ int FTLselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, st // Interrupt-safe thread routines int FTLpthread_mutex_lock(pthread_mutex_t *__mutex, const char *file, const char *func, const int line); +// Interrupt-safe file routines +FILE *FTLfopen(const char *pathname, const char *mode, const char *file, const char *func, const int line); + #endif //SYSCALLS_H From 543ea8558725faa094f0587588dcd7f3db7d0100 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 20:03:55 +0100 Subject: [PATCH 15/26] Add interrupt-safe sendto() routine Signed-off-by: DL6ER --- src/FTL.h | 1 + src/syscalls/CMakeLists.txt | 1 + src/syscalls/sendto.c | 38 +++++++++++++++++++++++++++++++++++++ src/syscalls/syscalls.h | 1 + 4 files changed, 41 insertions(+) create mode 100644 src/syscalls/sendto.c diff --git a/src/FTL.h b/src/FTL.h index 3e211e3a..052f0ff6 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -130,6 +130,7 @@ #define accept(sockfd, addr, addrlen) FTLaccept(sockfd, addr, addrlen, __FILE__, __FUNCTION__, __LINE__) #define recv(sockfd, buf, len, flags) FTLrecv(sockfd, buf, len, flags, __FILE__, __FUNCTION__, __LINE__) #define recvfrom(sockfd, buf, len, flags, src_addr, addrlen) FTLrecvfrom(sockfd, buf, len, flags, src_addr, addrlen, __FILE__, __FUNCTION__, __LINE__) +#define sendto(sockfd, buf, len, flags, dest_addr, addrlen) FTLsendto(sockfd, buf, len, flags, dest_addr, addrlen, __FILE__, __FUNCTION__, __LINE__) #define select(nfds, readfds, writefds, exceptfds, timeout) FTLselect(nfds, readfds, writefds, exceptfds, timeout, __FILE__, __FUNCTION__, __LINE__) #define pthread_mutex_lock(mutex) FTLpthread_mutex_lock(mutex, __FILE__, __FUNCTION__, __LINE__) #define fopen(pathname, mode) FTLfopen(pathname, mode, __FILE__, __FUNCTION__, __LINE__) diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index 0c105497..3b9d60b3 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -19,6 +19,7 @@ set(sources recv.c recvfrom.c select.c + sendto.c strdup.c syscalls.h vfprintf.c diff --git a/src/syscalls/sendto.c b/src/syscalls/sendto.c new file mode 100644 index 00000000..1f63ce77 --- /dev/null +++ b/src/syscalls/sendto.c @@ -0,0 +1,38 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for sendto +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +#include +#include + +ssize_t FTLsendto(int sockfd, void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen, const char *file, const char *func, const int line) +{ + ssize_t ret = 0; + do + { + // Reset errno before trying to write + errno = 0; + ret = sendto(sockfd, buf, len, flags, dest_addr, addrlen); + } + // Try again if the last accept() call failed due to an interruption by an + // incoming signal + while(ret < 0 && errno == EINTR); + + // Final error checking (may have faild for some other reason then an + // EINTR = interrupted system call) + if(ret < 0) + logg("WARN: Could not sendto() in %s() (%s:%i): %s", + func, file, line, strerror(errno)); + + return ret; +} \ No newline at end of file diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index f14d04fa..3fcc303e 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -28,6 +28,7 @@ int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char ssize_t FTLrecv(int sockfd, void *buf, size_t len, int flags, const char *file, const char *func, const int line); ssize_t FTLrecvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen, const char *file, const char *func, const int line); int FTLselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout, const char *file, const char *func, const int line); +ssize_t FTLsendto(int sockfd, void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen, const char *file, const char *func, const int line); // Interrupt-safe thread routines int FTLpthread_mutex_lock(pthread_mutex_t *__mutex, const char *file, const char *func, const int line); From d234dad71c45beace8e06c740a83ace4dfc4806c Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 20:06:17 +0100 Subject: [PATCH 16/26] Backup and restore errno in real-time signal handler. Signed-off-by: DL6ER --- src/signals.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/signals.c b/src/signals.c index f39dd6cb..ebab301c 100644 --- a/src/signals.c +++ b/src/signals.c @@ -245,10 +245,17 @@ static void __attribute__((noreturn)) signal_handler(int sig, siginfo_t *si, voi } static void SIGRT_handler(int signum, siginfo_t *si, void *unused) -{ +{ + // Backup errno + const int _errno = errno; + // Ignore real-time signals outside of the main process (TCP forks) if(mpid != getpid()) + { + // Restore errno before returning + errno = _errno; return; + } int rtsig = signum - SIGRTMIN; logg("Received: %s (%d -> %d)", strsignal(signum), signum, rtsig); @@ -288,6 +295,9 @@ static void SIGRT_handler(int signum, siginfo_t *si, void *unused) // Parse neighbor cache set_event(PARSE_NEIGHBOR_CACHE); } + + // Restore errno before returning back to previous context + errno = _errno; } // Register SIGSEGV handler From d4d4a0b1d6b19659f819e3f1b9a3bc24d854e610 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 21:02:00 +0100 Subject: [PATCH 17/26] Add interrupt-safe vsnprintf() routine Signed-off-by: DL6ER --- src/FTL.h | 1 + src/syscalls/CMakeLists.txt | 1 + src/syscalls/accept.c | 1 + src/syscalls/fopen.c | 1 + src/syscalls/pthread_mutex_lock.c | 1 + src/syscalls/recv.c | 1 + src/syscalls/recvfrom.c | 1 + src/syscalls/select.c | 1 + src/syscalls/sendto.c | 1 + src/syscalls/syscalls.h | 4 +++ src/syscalls/vfprintf.c | 49 ++++++++++++------------- src/syscalls/vsnprintf.c | 59 +++++++++++++++++++++++++++++++ src/syscalls/write.c | 1 + 13 files changed, 98 insertions(+), 24 deletions(-) create mode 100644 src/syscalls/vsnprintf.c diff --git a/src/FTL.h b/src/FTL.h index 052f0ff6..2a1f48be 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -126,6 +126,7 @@ #define fprintf(stream, format, ...) FTLfprintf(stream, __FILE__, __FUNCTION__, __LINE__, format, ##__VA_ARGS__) #define vprintf(format, args) FTLvfprintf(stdout, __FILE__, __FUNCTION__, __LINE__, format, args) #define vfprintf(stream, format, args) FTLvfprintf(stream, __FILE__, __FUNCTION__, __LINE__, format, args) +#define vsnprintf(buffer, maxlen, format, args) FTLvsnprintf(__FILE__, __FUNCTION__, __LINE__, buffer, maxlen, format, args) #define write(fd, buf, n) FTLwrite(fd, buf, n, __FILE__, __FUNCTION__, __LINE__) #define accept(sockfd, addr, addrlen) FTLaccept(sockfd, addr, addrlen, __FILE__, __FUNCTION__, __LINE__) #define recv(sockfd, buf, len, flags) FTLrecv(sockfd, buf, len, flags, __FILE__, __FUNCTION__, __LINE__) diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index 3b9d60b3..1597b2c3 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -23,6 +23,7 @@ set(sources strdup.c syscalls.h vfprintf.c + vsnprintf.c write.c ) diff --git a/src/syscalls/accept.c b/src/syscalls/accept.c index 8dc12d21..5b9cdd94 100644 --- a/src/syscalls/accept.c +++ b/src/syscalls/accept.c @@ -12,6 +12,7 @@ //#include "syscalls.h" is implicitly done in FTL.h #include "../log.h" +#undef accept int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char *file, const char *func, const int line) { int ret = 0; diff --git a/src/syscalls/fopen.c b/src/syscalls/fopen.c index 81c47520..ac06bac4 100644 --- a/src/syscalls/fopen.c +++ b/src/syscalls/fopen.c @@ -12,6 +12,7 @@ //#include "syscalls.h" is implicitly done in FTL.h #include "../log.h" +#undef fopen FILE *FTLfopen(const char *pathname, const char *mode, const char *file, const char *func, const int line) { FILE *file_ptr = 0; diff --git a/src/syscalls/pthread_mutex_lock.c b/src/syscalls/pthread_mutex_lock.c index 01d024de..da741764 100644 --- a/src/syscalls/pthread_mutex_lock.c +++ b/src/syscalls/pthread_mutex_lock.c @@ -14,6 +14,7 @@ #include +#undef pthread_mutex_lock int FTLpthread_mutex_lock(pthread_mutex_t *__mutex, const char *file, const char *func, const int line) { ssize_t ret = 0; diff --git a/src/syscalls/recv.c b/src/syscalls/recv.c index 404da899..84f2d4bd 100644 --- a/src/syscalls/recv.c +++ b/src/syscalls/recv.c @@ -14,6 +14,7 @@ #include +#undef recv ssize_t FTLrecv(int sockfd, void *buf, size_t len, int flags, const char *file, const char *func, const int line) { ssize_t ret = 0; diff --git a/src/syscalls/recvfrom.c b/src/syscalls/recvfrom.c index 347194a8..f28c9066 100644 --- a/src/syscalls/recvfrom.c +++ b/src/syscalls/recvfrom.c @@ -15,6 +15,7 @@ #include #include +#undef recvfrom ssize_t FTLrecvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen, const char *file, const char *func, const int line) { ssize_t ret = 0; diff --git a/src/syscalls/select.c b/src/syscalls/select.c index 83f676ec..5c26352d 100644 --- a/src/syscalls/select.c +++ b/src/syscalls/select.c @@ -14,6 +14,7 @@ #include +#undef select int FTLselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout, const char *file, const char *func, const int line) { int ret = 0; diff --git a/src/syscalls/sendto.c b/src/syscalls/sendto.c index 1f63ce77..9c0e165e 100644 --- a/src/syscalls/sendto.c +++ b/src/syscalls/sendto.c @@ -15,6 +15,7 @@ #include #include +#undef sendto ssize_t FTLsendto(int sockfd, void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen, const char *file, const char *func, const int line) { ssize_t ret = 0; diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index 3fcc303e..583e8916 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -21,6 +21,7 @@ void FTLfree(void *ptr, const char*file, const char *func, const int line); int FTLfprintf(FILE *stream, const char*file, const char *func, const int line, const char *format, ...) __attribute__ ((format (gnu_printf, 5, 6))); // vprintf() is derived from vfprintf(stdout, ...) int FTLvfprintf(FILE *stream, const char*file, const char *func, const int line, const char *format, va_list args) __attribute__ ((format (gnu_printf, 5, 0))); +int FTLvsnprintf(const char* file, const char *func, const int line, char *__restrict__ buffer, size_t maxlen, const char *format, va_list args) __attribute__ ((format (gnu_printf, 6, 0))); // Interrupt-safe socket routines ssize_t FTLwrite(int fd, const void *buf, size_t total, const char *file, const char *func, const int line); @@ -36,4 +37,7 @@ int FTLpthread_mutex_lock(pthread_mutex_t *__mutex, const char *file, const char // Interrupt-safe file routines FILE *FTLfopen(const char *pathname, const char *mode, const char *file, const char *func, const int line); +// Syscall helpers +void syscalls_report_error(const char *error, FILE *stream, const int _errno, const char *format, const char *func, const char *file, const int line); + #endif //SYSCALLS_H diff --git a/src/syscalls/vfprintf.c b/src/syscalls/vfprintf.c index 501791ed..bad620b9 100644 --- a/src/syscalls/vfprintf.c +++ b/src/syscalls/vfprintf.c @@ -75,12 +75,15 @@ static int fputs_convert_newline(const char *string, FILE *stream) // Special error reporting for our own vfprintf() // Since we cannot rely on (heap) being available (allocation may have failed // earlier), we do the reporting entirely manually, writing one string at a time -static void report_error(const char *error, FILE *stream, const char *format, const char *func, const char *file, const int line) +void syscalls_report_error(const char *error, FILE *stream, const int _errno, const char *format, const char *func, const char *file, const int line) { + char linestr[16] = { 0 }; + itoa(line, linestr); + fputs("WARN: ", stream); fputs(error, stream); fputs(": ", stream); - fputs(strerror(errno), stream); + fputs(strerror(_errno), stream); fputs("\n Not processing string \"", stream); fputs_convert_newline(format, stream); fputs("\" in ", stream); @@ -88,8 +91,6 @@ static void report_error(const char *error, FILE *stream, const char *format, co fputs("() [", stream); fputs(file, stream); fputs(":", stream); - char linestr[16] = { 0 }; - itoa(line, linestr); fputs(linestr, stream); fputs("]\n", stream); } @@ -102,22 +103,22 @@ int FTLvfprintf(FILE *stream, const char* file, const char *func, const int line int _errno, length = 0; do { - // The va_copy() macro copies the (previously initialized) variable - // argument list args to the local _args. The behavior is as if - // va_start() were applied to _args with the same last argument, - // followed by the same number of va_arg() invocations that was used to - // reach the current state of args. We do this to be able to reuse the - // arguments in args when we need to redo the string preparation - // procedure - va_list _args; - va_copy(_args, args); + // The va_copy() macro copies the (previously initialized) variable + // argument list args to the local _args. The behavior is as if + // va_start() were applied to _args with the same last argument, + // followed by the same number of va_arg() invocations that was used to + // reach the current state of args. We do this to be able to reuse the + // arguments in args when we need to redo the string preparation + // procedure + va_list _args; + va_copy(_args, args); // Reset errno before trying to get the string errno = 0; - // Do the actual string transformation + // Do the actual string transformation length = vasprintf(&buffer, format, _args); - // Copy errno into buffer before calling va_end() - _errno = errno; - va_end(_args); + // Copy errno into buffer before calling va_end() + _errno = errno; + va_end(_args); } // Try again to allocate memory if this failed due to an interruption by // an incoming signal @@ -126,12 +127,12 @@ int FTLvfprintf(FILE *stream, const char* file, const char *func, const int line // Handle other errors than EINTR if(length < 0 || buffer == NULL) { - report_error("vfprintf() failed to allocate memory", - stream, format, func, file, line); + syscalls_report_error("vfprintf() failed to allocate memory", + stream, _errno, format, func, file, line); - // Free the buffer in case anything got allocated - if(buffer != NULL) - free(buffer); + // Free the buffer in case anything got allocated + if(buffer != NULL) + free(buffer); // Return early, there isn't anything we can do here return length; @@ -155,8 +156,8 @@ int FTLvfprintf(FILE *stream, const char* file, const char *func, const int line // EINTR = interrupted system call) if(_buffer < buffer) { - report_error("vfprintf() did not print all characters", - stream, format, func, file, line); + syscalls_report_error("vfprintf() did not print all characters", + stream, errno, format, func, file, line); } // Free allocated memory diff --git a/src/syscalls/vsnprintf.c b/src/syscalls/vsnprintf.c new file mode 100644 index 00000000..bd1b04ae --- /dev/null +++ b/src/syscalls/vsnprintf.c @@ -0,0 +1,59 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for vsnprintf +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +#undef vsnprintf +int FTLvsnprintf(const char* file, const char *func, const int line, char *__restrict__ buffer, size_t maxlen, const char *format, va_list args) +{ + // Sanity check + if(buffer == NULL) + { + syscalls_report_error("vsnprintf() called with NULL buffer", + stdout, 0, format, func, file, line); + return 0; + } + // Print into dynamically allocated memory + int _errno, length = 0; + do + { + // The va_copy() macro copies the (previously initialized) variable + // argument list args to the local _args. The behavior is as if + // va_start() were applied to _args with the same last argument, + // followed by the same number of va_arg() invocations that was used to + // reach the current state of args. We do this to be able to reuse the + // arguments in args when we need to redo the string preparation + // procedure + va_list _args; + va_copy(_args, args); + // Reset errno before trying to get the string + errno = 0; + // Do the actual string transformation + length = vsnprintf(buffer, maxlen, format, _args); + // Copy errno into buffer before calling va_end() + _errno = errno; + va_end(_args); + } + // Try again to allocate memory if this failed due to an interruption by + // an incoming signal + while(length < 0 && _errno == EINTR); + + // Handle other errors than EINTR + if(length < 0) + { + syscalls_report_error("vsnprintf() failed to print into buffer", + stdout, _errno, format, func, file, line); + } + + // Return number of written bytes + return length; +} diff --git a/src/syscalls/write.c b/src/syscalls/write.c index 3ea90641..b5787e89 100644 --- a/src/syscalls/write.c +++ b/src/syscalls/write.c @@ -12,6 +12,7 @@ //#include "syscalls.h" is implicitly done in FTL.h #include "../log.h" +#undef write ssize_t FTLwrite(int fd, const void *buf, size_t total, const char *file, const char *func, const int line) { if(buf == NULL) From 70a4ad13e2ac53be33777904eb57dfd19e8f122a Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 21:06:21 +0100 Subject: [PATCH 18/26] Add interrupt-safe snprintf() routine Signed-off-by: DL6ER --- src/FTL.h | 1 + src/syscalls/CMakeLists.txt | 1 + src/syscalls/snprintf.c | 23 +++++++++++++++++++++++ src/syscalls/syscalls.h | 3 ++- src/syscalls/vsnprintf.c | 2 +- 5 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/syscalls/snprintf.c diff --git a/src/FTL.h b/src/FTL.h index 2a1f48be..35edfbac 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -126,6 +126,7 @@ #define fprintf(stream, format, ...) FTLfprintf(stream, __FILE__, __FUNCTION__, __LINE__, format, ##__VA_ARGS__) #define vprintf(format, args) FTLvfprintf(stdout, __FILE__, __FUNCTION__, __LINE__, format, args) #define vfprintf(stream, format, args) FTLvfprintf(stream, __FILE__, __FUNCTION__, __LINE__, format, args) +#define snprintf(buffer, maxlen, format, ...) FTLsnprintf(__FILE__, __FUNCTION__, __LINE__, buffer, maxlen, format, ##__VA_ARGS__) #define vsnprintf(buffer, maxlen, format, args) FTLvsnprintf(__FILE__, __FUNCTION__, __LINE__, buffer, maxlen, format, args) #define write(fd, buf, n) FTLwrite(fd, buf, n, __FILE__, __FUNCTION__, __LINE__) #define accept(sockfd, addr, addrlen) FTLaccept(sockfd, addr, addrlen, __FILE__, __FUNCTION__, __LINE__) diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index 1597b2c3..847c3ff5 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -20,6 +20,7 @@ set(sources recvfrom.c select.c sendto.c + snprintf.c strdup.c syscalls.h vfprintf.c diff --git a/src/syscalls/snprintf.c b/src/syscalls/snprintf.c new file mode 100644 index 00000000..0460ac15 --- /dev/null +++ b/src/syscalls/snprintf.c @@ -0,0 +1,23 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for snprintf +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +int FTLsnprintf(const char* file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, ...) +{ + va_list args; + va_start(args, format); + const int length = FTLvsnprintf(file, func, line, buffer, maxlen, format, args); + va_end(args); + + return length; +} diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index 583e8916..33ef2598 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -21,7 +21,8 @@ void FTLfree(void *ptr, const char*file, const char *func, const int line); int FTLfprintf(FILE *stream, const char*file, const char *func, const int line, const char *format, ...) __attribute__ ((format (gnu_printf, 5, 6))); // vprintf() is derived from vfprintf(stdout, ...) int FTLvfprintf(FILE *stream, const char*file, const char *func, const int line, const char *format, va_list args) __attribute__ ((format (gnu_printf, 5, 0))); -int FTLvsnprintf(const char* file, const char *func, const int line, char *__restrict__ buffer, size_t maxlen, const char *format, va_list args) __attribute__ ((format (gnu_printf, 6, 0))); +int FTLsnprintf(const char* file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, ...) __attribute__ ((format (gnu_printf, 6, 7))); +int FTLvsnprintf(const char* file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, va_list args) __attribute__ ((format (gnu_printf, 6, 0))); // Interrupt-safe socket routines ssize_t FTLwrite(int fd, const void *buf, size_t total, const char *file, const char *func, const int line); diff --git a/src/syscalls/vsnprintf.c b/src/syscalls/vsnprintf.c index bd1b04ae..c195fefe 100644 --- a/src/syscalls/vsnprintf.c +++ b/src/syscalls/vsnprintf.c @@ -13,7 +13,7 @@ #include "../log.h" #undef vsnprintf -int FTLvsnprintf(const char* file, const char *func, const int line, char *__restrict__ buffer, size_t maxlen, const char *format, va_list args) +int FTLvsnprintf(const char* file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, va_list args) { // Sanity check if(buffer == NULL) From 20fa5ef6270ec644de3bf7da1c8ce8c22baaf53a Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 21:12:29 +0100 Subject: [PATCH 19/26] Add interrupt-safe vsprintf() routine Signed-off-by: DL6ER --- src/FTL.h | 1 + src/syscalls/fprintf.c | 2 +- src/syscalls/snprintf.c | 2 +- src/syscalls/syscalls.h | 5 ++-- src/syscalls/vfprintf.c | 2 +- src/syscalls/vsnprintf.c | 2 +- src/syscalls/vsprintf.c | 59 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 src/syscalls/vsprintf.c diff --git a/src/FTL.h b/src/FTL.h index 35edfbac..7ca0e1b2 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -126,6 +126,7 @@ #define fprintf(stream, format, ...) FTLfprintf(stream, __FILE__, __FUNCTION__, __LINE__, format, ##__VA_ARGS__) #define vprintf(format, args) FTLvfprintf(stdout, __FILE__, __FUNCTION__, __LINE__, format, args) #define vfprintf(stream, format, args) FTLvfprintf(stream, __FILE__, __FUNCTION__, __LINE__, format, args) +#define vsprintf(buffer, format, args) FTLvsprintf(__FILE__, __FUNCTION__, __LINE__, buffer, format, args) #define snprintf(buffer, maxlen, format, ...) FTLsnprintf(__FILE__, __FUNCTION__, __LINE__, buffer, maxlen, format, ##__VA_ARGS__) #define vsnprintf(buffer, maxlen, format, args) FTLvsnprintf(__FILE__, __FUNCTION__, __LINE__, buffer, maxlen, format, args) #define write(fd, buf, n) FTLwrite(fd, buf, n, __FILE__, __FUNCTION__, __LINE__) diff --git a/src/syscalls/fprintf.c b/src/syscalls/fprintf.c index 90b88652..be3bee68 100644 --- a/src/syscalls/fprintf.c +++ b/src/syscalls/fprintf.c @@ -12,7 +12,7 @@ //#include "syscalls.h" is implicitly done in FTL.h #include "../log.h" -int FTLfprintf(FILE *stream, const char* file, const char *func, const int line, const char *format, ...) +int FTLfprintf(FILE *stream, const char *file, const char *func, const int line, const char *format, ...) { va_list args; va_start(args, format); diff --git a/src/syscalls/snprintf.c b/src/syscalls/snprintf.c index 0460ac15..699d942c 100644 --- a/src/syscalls/snprintf.c +++ b/src/syscalls/snprintf.c @@ -12,7 +12,7 @@ //#include "syscalls.h" is implicitly done in FTL.h #include "../log.h" -int FTLsnprintf(const char* file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, ...) +int FTLsnprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, ...) { va_list args; va_start(args, format); diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index 33ef2598..15dcca12 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -21,8 +21,9 @@ void FTLfree(void *ptr, const char*file, const char *func, const int line); int FTLfprintf(FILE *stream, const char*file, const char *func, const int line, const char *format, ...) __attribute__ ((format (gnu_printf, 5, 6))); // vprintf() is derived from vfprintf(stdout, ...) int FTLvfprintf(FILE *stream, const char*file, const char *func, const int line, const char *format, va_list args) __attribute__ ((format (gnu_printf, 5, 0))); -int FTLsnprintf(const char* file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, ...) __attribute__ ((format (gnu_printf, 6, 7))); -int FTLvsnprintf(const char* file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, va_list args) __attribute__ ((format (gnu_printf, 6, 0))); +int FTLvsprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const char *format, va_list args) __attribute__ ((format (gnu_printf, 5, 0))); +int FTLsnprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, ...) __attribute__ ((format (gnu_printf, 6, 7))); +int FTLvsnprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, va_list args) __attribute__ ((format (gnu_printf, 6, 0))); // Interrupt-safe socket routines ssize_t FTLwrite(int fd, const void *buf, size_t total, const char *file, const char *func, const int line); diff --git a/src/syscalls/vfprintf.c b/src/syscalls/vfprintf.c index bad620b9..f2e65353 100644 --- a/src/syscalls/vfprintf.c +++ b/src/syscalls/vfprintf.c @@ -96,7 +96,7 @@ void syscalls_report_error(const char *error, FILE *stream, const int _errno, co } // The actual vfprintf() routine -int FTLvfprintf(FILE *stream, const char* file, const char *func, const int line, const char *format, va_list args) +int FTLvfprintf(FILE *stream, const char *file, const char *func, const int line, const char *format, va_list args) { // Print into dynamically allocated memory char *buffer = NULL; diff --git a/src/syscalls/vsnprintf.c b/src/syscalls/vsnprintf.c index c195fefe..10f7b6c2 100644 --- a/src/syscalls/vsnprintf.c +++ b/src/syscalls/vsnprintf.c @@ -13,7 +13,7 @@ #include "../log.h" #undef vsnprintf -int FTLvsnprintf(const char* file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, va_list args) +int FTLvsnprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, va_list args) { // Sanity check if(buffer == NULL) diff --git a/src/syscalls/vsprintf.c b/src/syscalls/vsprintf.c new file mode 100644 index 00000000..b31ba414 --- /dev/null +++ b/src/syscalls/vsprintf.c @@ -0,0 +1,59 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for vsprintf +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +#undef vsprintf +int FTLvsprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const char *format, va_list args) +{ + // Sanity check + if(buffer == NULL) + { + syscalls_report_error("vsprintf() called with NULL buffer", + stdout, 0, format, func, file, line); + return 0; + } + // Print into dynamically allocated memory + int _errno, length = 0; + do + { + // The va_copy() macro copies the (previously initialized) variable + // argument list args to the local _args. The behavior is as if + // va_start() were applied to _args with the same last argument, + // followed by the same number of va_arg() invocations that was used to + // reach the current state of args. We do this to be able to reuse the + // arguments in args when we need to redo the string preparation + // procedure + va_list _args; + va_copy(_args, args); + // Reset errno before trying to get the string + errno = 0; + // Do the actual string transformation + length = vsprintf(buffer, format, _args); + // Copy errno into buffer before calling va_end() + _errno = errno; + va_end(_args); + } + // Try again to allocate memory if this failed due to an interruption by + // an incoming signal + while(length < 0 && _errno == EINTR); + + // Handle other errors than EINTR + if(length < 0) + { + syscalls_report_error("vsprintf() failed to print into buffer", + stdout, _errno, format, func, file, line); + } + + // Return number of written bytes + return length; +} From ab0daeb7bb17b05aaf6bff2ba503a826fb7c6802 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 9 Dec 2020 21:16:06 +0100 Subject: [PATCH 20/26] Add interrupt-safe sprintf() routine Signed-off-by: DL6ER --- src/FTL.h | 2 ++ src/syscalls/CMakeLists.txt | 2 ++ src/syscalls/sprintf.c | 23 +++++++++++++++++++++++ src/syscalls/syscalls.h | 5 ++++- 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/syscalls/sprintf.c diff --git a/src/FTL.h b/src/FTL.h index 7ca0e1b2..b97ca183 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -118,6 +118,7 @@ // and report accordingly in the log. This will make debugging FTL crashs // caused by insufficient memory or by code bugs (not properly dealing // with NULL pointers) much easier. +#undef strdup // strdup() is a macro in itself, it needs special handling #define free(ptr) FTLfree(ptr, __FILE__, __FUNCTION__, __LINE__) #define strdup(str_in) FTLstrdup(str_in, __FILE__, __FUNCTION__, __LINE__) #define calloc(numer_of_elements, element_size) FTLcalloc(numer_of_elements, element_size, __FILE__, __FUNCTION__, __LINE__) @@ -126,6 +127,7 @@ #define fprintf(stream, format, ...) FTLfprintf(stream, __FILE__, __FUNCTION__, __LINE__, format, ##__VA_ARGS__) #define vprintf(format, args) FTLvfprintf(stdout, __FILE__, __FUNCTION__, __LINE__, format, args) #define vfprintf(stream, format, args) FTLvfprintf(stream, __FILE__, __FUNCTION__, __LINE__, format, args) +#define sprintf(buffer, format, ...) FTLsprintf(__FILE__, __FUNCTION__, __LINE__, buffer, format, ##__VA_ARGS__) #define vsprintf(buffer, format, args) FTLvsprintf(__FILE__, __FUNCTION__, __LINE__, buffer, format, args) #define snprintf(buffer, maxlen, format, ...) FTLsnprintf(__FILE__, __FUNCTION__, __LINE__, buffer, maxlen, format, ##__VA_ARGS__) #define vsnprintf(buffer, maxlen, format, args) FTLvsnprintf(__FILE__, __FUNCTION__, __LINE__, buffer, maxlen, format, args) diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index 847c3ff5..fe0940a4 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -21,10 +21,12 @@ set(sources select.c sendto.c snprintf.c + sprintf.c strdup.c syscalls.h vfprintf.c vsnprintf.c + vsprintf.c write.c ) diff --git a/src/syscalls/sprintf.c b/src/syscalls/sprintf.c new file mode 100644 index 00000000..a6cc4094 --- /dev/null +++ b/src/syscalls/sprintf.c @@ -0,0 +1,23 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for sprintf +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +int FTLsprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const char *format, ...) +{ + va_list args; + va_start(args, format); + const int length = FTLvsprintf(file, func, line, buffer, format, args); + va_end(args); + + return length; +} diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index 15dcca12..07f2f7dc 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -18,10 +18,13 @@ void FTLfree(void *ptr, const char*file, const char *func, const int line); // Interrupt-safe printing routines // printf() is derived from fprintf(stdout, ...) -int FTLfprintf(FILE *stream, const char*file, const char *func, const int line, const char *format, ...) __attribute__ ((format (gnu_printf, 5, 6))); // vprintf() is derived from vfprintf(stdout, ...) +int FTLfprintf(FILE *stream, const char*file, const char *func, const int line, const char *format, ...) __attribute__ ((format (gnu_printf, 5, 6))); int FTLvfprintf(FILE *stream, const char*file, const char *func, const int line, const char *format, va_list args) __attribute__ ((format (gnu_printf, 5, 0))); + +int FTLsprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const char *format, ...) __attribute__ ((format (gnu_printf, 5, 6))); int FTLvsprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const char *format, va_list args) __attribute__ ((format (gnu_printf, 5, 0))); + int FTLsnprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, ...) __attribute__ ((format (gnu_printf, 6, 7))); int FTLvsnprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, va_list args) __attribute__ ((format (gnu_printf, 6, 0))); From 85c8af44de3479d0074c1239836b710c66f332ef Mon Sep 17 00:00:00 2001 From: DL6ER Date: Thu, 10 Dec 2020 22:01:47 +0100 Subject: [PATCH 21/26] Add interrupt-safe asprintf() and vasprintf() routines Signed-off-by: DL6ER --- src/FTL.h | 2 ++ src/syscalls/CMakeLists.txt | 2 ++ src/syscalls/asprintf.c | 23 +++++++++++++++ src/syscalls/syscalls.h | 3 ++ src/syscalls/vasprintf.c | 59 +++++++++++++++++++++++++++++++++++++ 5 files changed, 89 insertions(+) create mode 100644 src/syscalls/asprintf.c create mode 100644 src/syscalls/vasprintf.c diff --git a/src/FTL.h b/src/FTL.h index b97ca183..05f4f34d 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -129,6 +129,8 @@ #define vfprintf(stream, format, args) FTLvfprintf(stream, __FILE__, __FUNCTION__, __LINE__, format, args) #define sprintf(buffer, format, ...) FTLsprintf(__FILE__, __FUNCTION__, __LINE__, buffer, format, ##__VA_ARGS__) #define vsprintf(buffer, format, args) FTLvsprintf(__FILE__, __FUNCTION__, __LINE__, buffer, format, args) +#define asprintf(buffer, format, ...) FTLasprintf(__FILE__, __FUNCTION__, __LINE__, buffer, format, ##__VA_ARGS__) +#define vasprintf(buffer, format, args) FTLvasprintf(__FILE__, __FUNCTION__, __LINE__, buffer, format, args) #define snprintf(buffer, maxlen, format, ...) FTLsnprintf(__FILE__, __FUNCTION__, __LINE__, buffer, maxlen, format, ##__VA_ARGS__) #define vsnprintf(buffer, maxlen, format, args) FTLvsnprintf(__FILE__, __FUNCTION__, __LINE__, buffer, maxlen, format, args) #define write(fd, buf, n) FTLwrite(fd, buf, n, __FILE__, __FUNCTION__, __LINE__) diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index fe0940a4..e1b971e7 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -10,6 +10,7 @@ set(sources accept.c + asprintf.c calloc.c fopen.c fprintf.c @@ -24,6 +25,7 @@ set(sources sprintf.c strdup.c syscalls.h + vasprintf.c vfprintf.c vsnprintf.c vsprintf.c diff --git a/src/syscalls/asprintf.c b/src/syscalls/asprintf.c new file mode 100644 index 00000000..4da1ea82 --- /dev/null +++ b/src/syscalls/asprintf.c @@ -0,0 +1,23 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for asprintf +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +int FTLasprintf(const char *file, const char *func, const int line, char **buffer, const char *format, ...) +{ + va_list args; + va_start(args, format); + const int length = FTLvasprintf(file, func, line, buffer, format, args); + va_end(args); + + return length; +} diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index 07f2f7dc..230068b6 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -25,6 +25,9 @@ int FTLvfprintf(FILE *stream, const char*file, const char *func, const int line, int FTLsprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const char *format, ...) __attribute__ ((format (gnu_printf, 5, 6))); int FTLvsprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const char *format, va_list args) __attribute__ ((format (gnu_printf, 5, 0))); +int FTLasprintf(const char *file, const char *func, const int line, char **buffer, const char *format, ...) __attribute__ ((format (gnu_printf, 5, 6))); +int FTLvasprintf(const char *file, const char *func, const int line, char **buffer, const char *format, va_list args) __attribute__ ((format (gnu_printf, 5, 0))); + int FTLsnprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, ...) __attribute__ ((format (gnu_printf, 6, 7))); int FTLvsnprintf(const char *file, const char *func, const int line, char *__restrict__ buffer, const size_t maxlen, const char *format, va_list args) __attribute__ ((format (gnu_printf, 6, 0))); diff --git a/src/syscalls/vasprintf.c b/src/syscalls/vasprintf.c new file mode 100644 index 00000000..8300a8c5 --- /dev/null +++ b/src/syscalls/vasprintf.c @@ -0,0 +1,59 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for vasprintf +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" + +#undef vasprintf +int FTLvasprintf(const char *file, const char *func, const int line, char **buffer, const char *format, va_list args) +{ + // Sanity check + if(buffer == NULL) + { + syscalls_report_error("vasprintf() called with NULL buffer", + stdout, 0, format, func, file, line); + return 0; + } + // Print into dynamically allocated memory + int _errno, length = 0; + do + { + // The va_copy() macro copies the (previously initialized) variable + // argument list args to the local _args. The behavior is as if + // va_start() were applied to _args with the same last argument, + // followed by the same number of va_arg() invocations that was used to + // reach the current state of args. We do this to be able to reuse the + // arguments in args when we need to redo the string preparation + // procedure + va_list _args; + va_copy(_args, args); + // Reset errno before trying to get the string + errno = 0; + // Do the actual string transformation + length = vasprintf(buffer, format, _args); + // Copy errno into buffer before calling va_end() + _errno = errno; + va_end(_args); + } + // Try again to allocate memory if this failed due to an interruption by + // an incoming signal + while(length < 0 && _errno == EINTR); + + // Handle other errors than EINTR + if(length < 0) + { + syscalls_report_error("vasprintf() failed to print into buffer", + stdout, _errno, format, func, file, line); + } + + // Return number of written bytes + return length; +} From fd788585a1e3a51cc8c2834954a0d1f6e5ea6fe7 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 20 Dec 2020 10:12:50 +0100 Subject: [PATCH 22/26] Add interrupt-safe fallocate() routine, due to the special nature of the fallocate() macro, we hav to use a modified name fTLallocate() to implement this function Signed-off-by: DL6ER --- src/FTL.h | 1 + src/shmem.c | 10 +++++----- src/syscalls/CMakeLists.txt | 1 + src/syscalls/ftlallocate.c | 37 +++++++++++++++++++++++++++++++++++++ src/syscalls/syscalls.h | 2 ++ 5 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 src/syscalls/ftlallocate.c diff --git a/src/FTL.h b/src/FTL.h index 05f4f34d..4b659f85 100644 --- a/src/FTL.h +++ b/src/FTL.h @@ -141,6 +141,7 @@ #define select(nfds, readfds, writefds, exceptfds, timeout) FTLselect(nfds, readfds, writefds, exceptfds, timeout, __FILE__, __FUNCTION__, __LINE__) #define pthread_mutex_lock(mutex) FTLpthread_mutex_lock(mutex, __FILE__, __FUNCTION__, __LINE__) #define fopen(pathname, mode) FTLfopen(pathname, mode, __FILE__, __FUNCTION__, __LINE__) +#define ftlallocate(fd, offset, len) FTLfallocate(fd, offset, len, __FILE__, __FUNCTION__, __LINE__) #include "syscalls/syscalls.h" // Preprocessor help functions diff --git a/src/shmem.c b/src/shmem.c index bd922480..312ccac9 100644 --- a/src/shmem.c +++ b/src/shmem.c @@ -507,10 +507,10 @@ SharedMemory create_shm(const char *name, const size_t size, bool create_new) } // Allocate shared memory object to specified size - // Using fallocate() will ensure that there's actually space for + // Using f[tl]allocate() will ensure that there's actually space for // this file. Otherwise we end up with a sparse file that can give // SIGBUS if we run out of space while writing to it. - const int ret = fallocate(fd, 0, 0U, size); + const int ret = ftlallocate(fd, 0U, size); if(ret != 0) { logg("FATAL: create_shm(): Failed to resize \"%s\" (%i) to %zu: %s (%i)", @@ -631,10 +631,10 @@ bool realloc_shm(SharedMemory *sharedMemory, const size_t size1, const size_t si } // Allocate shared memory object to specified size - // Using fallocate() will ensure that there's actually space for + // Using f[tl]allocate() will ensure that there's actually space for // this file. Otherwise we end up with a sparse file that can give // SIGBUS if we run out of space while writing to it. - const int ret = fallocate(fd, 0, 0U, size); + const int ret = ftlallocate(fd, 0U, size); if(ret != 0) { logg("FATAL: realloc_shm(): Failed to resize \"%s\" (%i) to %zu: %s (%i)", @@ -643,7 +643,7 @@ bool realloc_shm(SharedMemory *sharedMemory, const size_t size1, const size_t si } // Close shared memory object file descriptor as it is no longer - // needed after having called fallocate() + // needed after having called f[tl]allocate() close(fd); // Update shm counters to indicate that at least one shared memory object changed diff --git a/src/syscalls/CMakeLists.txt b/src/syscalls/CMakeLists.txt index e1b971e7..8582ac51 100644 --- a/src/syscalls/CMakeLists.txt +++ b/src/syscalls/CMakeLists.txt @@ -12,6 +12,7 @@ set(sources accept.c asprintf.c calloc.c + ftlallocate.c fopen.c fprintf.c free.c diff --git a/src/syscalls/ftlallocate.c b/src/syscalls/ftlallocate.c new file mode 100644 index 00000000..5095d296 --- /dev/null +++ b/src/syscalls/ftlallocate.c @@ -0,0 +1,37 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2020 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* FTL Engine +* Pi-hole syscall implementation for fallocate +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +#include "../FTL.h" +//#include "syscalls.h" is implicitly done in FTL.h +#include "../log.h" +#include + +// off_t is automatically set as off64_t when this is a 64bit system +int FTLfallocate(const int fd, const off_t offset, const off_t len, const char *file, const char *func, const int line) +{ + int ret = 0; + do + { + // Reset errno before trying to write + errno = 0; + ret = posix_fallocate(fd, offset, len); + } + // Try again if the last posix_fallocate() call failed due to an + // interruption by an incoming signal + while(ret < 0 && errno == EINTR); + + // Final error checking (may have faild for some other reason then an + // EINTR = interrupted system call) + if(ret < 0) + logg("WARN: Could not fallocate() in %s() (%s:%i): %s", + func, file, line, strerror(errno)); + + return ret; +} \ No newline at end of file diff --git a/src/syscalls/syscalls.h b/src/syscalls/syscalls.h index 230068b6..1b2787cd 100644 --- a/src/syscalls/syscalls.h +++ b/src/syscalls/syscalls.h @@ -15,6 +15,8 @@ char *FTLstrdup(const char *src, const char *file, const char *func, const int l void *FTLcalloc(size_t n, size_t size, const char *file, const char *func, const int line) __attribute__((malloc)) __attribute__((alloc_size(1,2))); void *FTLrealloc(void *ptr_in, size_t size, const char *file, const char *func, const int line) __attribute__((alloc_size(2))); void FTLfree(void *ptr, const char*file, const char *func, const int line); +int FTLfallocate(const int fd, const off_t offset, const off_t len, const char *file, const char *func, const int line); + // Interrupt-safe printing routines // printf() is derived from fprintf(stdout, ...) From 9627ca6909785b93edfd3703ffe284c5a4efb90f Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 20 Dec 2020 10:37:39 +0100 Subject: [PATCH 23/26] Prevent possible deadlock if log is not writable (e.g., permission denied) Signed-off-by: DL6ER --- src/log.c | 30 ++++++++++++++++-------------- src/log.h | 2 +- src/main.c | 6 ------ 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/log.c b/src/log.c index 28885f41..51c171d3 100644 --- a/src/log.c +++ b/src/log.c @@ -27,6 +27,7 @@ static pthread_mutex_t lock; static FILE *logfile = NULL; +static bool FTL_log_ready = false; static bool print_log = true, print_stdout = true; void log_ctrl(bool plog, bool pstdout) @@ -41,27 +42,25 @@ static void close_FTL_log(void) fclose(logfile); } -void init_FTL_log(void) +void open_FTL_log(const bool init) { - if (pthread_mutex_init(&lock, NULL) != 0) + if(init) { - printf("FATAL: Log mutex init failed\n"); - // Return failure - exit(EXIT_FAILURE); - } -} + // Initialize logging mutex + if (pthread_mutex_init(&lock, NULL) != 0) + { + printf("FATAL: Log mutex init failed\n"); + // Return failure + exit(EXIT_FAILURE); + } -void open_FTL_log(const bool test) -{ - if(test) - { // Obtain log file location getLogFilePath(); } // Open the log file in append/create mode logfile = fopen(FTLfiles.log, "a+"); - if((logfile == NULL) && test){ + if((logfile == NULL) && init){ syslog(LOG_ERR, "Opening of FTL\'s log file failed!"); printf("FATAL: Opening of FTL log (%s) failed!\n",FTLfiles.log); printf(" Make sure it exists and is writeable by user %s\n", username); @@ -69,7 +68,10 @@ void open_FTL_log(const bool test) exit(EXIT_FAILURE); } - if(test) + // Set log as ready (we were able to open it) + FTL_log_ready = true; + + if(init) { close_FTL_log(); } @@ -140,7 +142,7 @@ void _FTL_log(const bool newline, const char *format, ...) printf("\n"); } - if(print_log) + if(print_log && FTL_log_ready) { // Open log file open_FTL_log(false); diff --git a/src/log.h b/src/log.h index c6cd0516..eb99cd52 100644 --- a/src/log.h +++ b/src/log.h @@ -14,7 +14,7 @@ #include void init_FTL_log(void); -void open_FTL_log(const bool test); +void open_FTL_log(const bool init); void log_counter_info(void); void format_memory_size(char * const prefix, unsigned long long int bytes, double * const formated); diff --git a/src/main.c b/src/main.c index 8b6864a1..aa68c320 100644 --- a/src/main.c +++ b/src/main.c @@ -39,12 +39,6 @@ int main (int argc, char* argv[]) // it if needed username = getUserName(); - // This only prepares the log file lock, we - // do not want to log already here (parsing - // args may bring up something we want to do - // separated from the log in foreground) - init_FTL_log(); - // Parse arguments // We run this also for no direct arguments // to have arg{c,v}_dnsmasq initialized From f88b14985e3a9ffeef32b5e1c503315946a506f1 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 20 Dec 2020 10:40:23 +0100 Subject: [PATCH 24/26] Don't fail when trying to free(NULL) Signed-off-by: DL6ER --- src/syscalls/fopen.c | 2 +- src/syscalls/free.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/syscalls/fopen.c b/src/syscalls/fopen.c index ac06bac4..96f4bb07 100644 --- a/src/syscalls/fopen.c +++ b/src/syscalls/fopen.c @@ -29,7 +29,7 @@ FILE *FTLfopen(const char *pathname, const char *mode, const char *file, const c // Final error checking (may have faild for some other reason then an // EINTR = interrupted system call) if(file_ptr == NULL) - logg("WARN: Could not fopen(%s, %s) in %s() (%s:%i): %s", + logg("WARN: Could not fopen(\"%s\", \"%s\") in %s() (%s:%i): %s", pathname, mode, func, file, line, strerror(errno)); return file_ptr; diff --git a/src/syscalls/free.c b/src/syscalls/free.c index da08daf1..d3a48ad9 100644 --- a/src/syscalls/free.c +++ b/src/syscalls/free.c @@ -20,7 +20,10 @@ void FTLfree(void *ptr, const char *file, const char *func, const int line) // realloc(). Otherwise, or if free(ptr) has already been called before, // undefined behavior occurs. If ptr is NULL, no operation is performed. if(ptr == NULL) - logg("FATAL: Trying to free NULL pointer in %s() (%s:%i)", func, file, line); + { + logg("WARN: Trying to free NULL pointer in %s() (%s:%i)", func, file, line); + return; + } free(ptr); } From b52eb1f2a5bd27e7f9589ee511560d26e35c7b9e Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 20 Dec 2020 10:44:34 +0100 Subject: [PATCH 25/26] Fix Unix socket error handling Signed-off-by: DL6ER --- src/api/socket.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/api/socket.c b/src/api/socket.c index 2201dbbf..eba21f26 100644 --- a/src/api/socket.c +++ b/src/api/socket.c @@ -512,8 +512,11 @@ void *socket_listening_thread(void *args) // Return early to avoid CPU spinning if Unix socket is not available sock_avail = bind_to_unix_socket(&socketfd); - if(sock_avail) + if(!sock_avail) + { + logg("INFO: Unix socket will not be available"); return NULL; + } // Listen as long as FTL is not killed while(!killed) From 0837b8d2df3e2a4e82a50c9350a8a7c16198f2fc Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 20 Dec 2020 10:48:26 +0100 Subject: [PATCH 26/26] Do not print user change information if there is no user change Signed-off-by: DL6ER --- src/dnsmasq_interface.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dnsmasq_interface.c b/src/dnsmasq_interface.c index 0a0e96f1..0801bd32 100644 --- a/src/dnsmasq_interface.c +++ b/src/dnsmasq_interface.c @@ -1774,7 +1774,9 @@ void FTL_fork_and_bind_sockets(struct passwd *ent_pw) // option states to run as a different user/group (e.g. "nobody") if(getuid() == 0) { - if(ent_pw != NULL) + // Only print this and change ownership of shmem objects when + // we're actually dropping root (user/group my be set to root) + if(ent_pw != NULL && ent_pw->pw_uid != 0) { logg("INFO: FTL is going to drop from root to user %s (UID %d)", ent_pw->pw_name, (int)ent_pw->pw_uid);