Merge pull request #969 from pi-hole/tweak/interruptsafe_systemcalls

Implement interrupt-safe systemcalls
This commit is contained in:
DL6ER
2020-12-21 10:05:03 +01:00
committed by GitHub
54 changed files with 1110 additions and 206 deletions
+2 -2
View File
@@ -131,8 +131,6 @@ set(sources
log.h
main.c
main.h
memory.c
memory.h
overTime.c
overTime.h
regex.c
@@ -174,6 +172,7 @@ add_executable(pihole-FTL
$<TARGET_OBJECTS:sqlite3>
$<TARGET_OBJECTS:lua>
$<TARGET_OBJECTS:tre-regex>
$<TARGET_OBJECTS:syscalls>
)
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)
+22 -3
View File
@@ -114,16 +114,35 @@
// 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.
#undef strdup // strdup() is a macro in itself, it needs special handling
#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__)
#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 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__)
#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__)
#define ftlallocate(fd, offset, len) FTLfallocate(fd, offset, len, __FILE__, __FUNCTION__, __LINE__)
#include "syscalls/syscalls.h"
// Preprocessor help functions
#define str(x) # x
+11 -11
View File
@@ -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));
}
+10 -14
View File
@@ -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
@@ -223,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)
{
@@ -519,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)
-1
View File
@@ -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);
-1
View File
@@ -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
-1
View File
@@ -14,7 +14,6 @@
#undef __USE_XOPEN
#include "FTL.h"
#include "capabilities.h"
#include "memory.h"
#include "config.h"
#include "log.h"
-1
View File
@@ -10,7 +10,6 @@
#include "FTL.h"
#include "config.h"
#include "memory.h"
#include "setupVars.h"
#include "log.h"
// nice()
-1
View File
@@ -10,7 +10,6 @@
#include "FTL.h"
#include "daemon.h"
#include "memory.h"
#include "config.h"
#include "log.h"
// sleepms()
-2
View File
@@ -17,8 +17,6 @@
#include "../config.h"
// logg()
#include "../log.h"
// calloc()
#include "../memory.h"
// getAliasclientIDfromIP()
#include "network-table.h"
-1
View File
@@ -13,7 +13,6 @@
#include "network-table.h"
#include "message-table.h"
#include "../shmem.h"
#include "../memory.h"
// struct config
#include "../config.h"
// logg()
+3
View File
@@ -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 ":"
+3 -6
View File
@@ -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
-2
View File
@@ -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"
-2
View File
@@ -25,8 +25,6 @@
#include "../config.h"
// getstr()
#include "../shmem.h"
// free()
#include "../memory.h"
static bool saving_failed_before = false;
-1
View File
@@ -10,7 +10,6 @@
#include "FTL.h"
#include "datastructure.h"
#include "memory.h"
#include "shmem.h"
#include "log.h"
// enum REGEX
+3 -2
View File
@@ -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"
@@ -1775,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);
-1
View File
@@ -10,7 +10,6 @@
#include "FTL.h"
#include "files.h"
#include "memory.h"
#include "config.h"
#include "setupVars.h"
#include "log.h"
-2
View File
@@ -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
+16 -15
View File
@@ -10,7 +10,6 @@
#include "FTL.h"
#include "version.h"
#include "memory.h"
// is_fork()
#include "daemon.h"
#include "config.h"
@@ -28,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)
@@ -42,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);
@@ -70,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();
}
@@ -141,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);
+1 -1
View File
@@ -14,7 +14,7 @@
#include <time.h>
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);
-6
View File
@@ -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
-95
View File
@@ -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 "memory.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);
}
-20
View File
@@ -1,20 +0,0 @@
/* Pi-hole: A black hole for Internet advertisements
* (c) 2019 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* FTL Engine
* Memory 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
#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)));
void FTLfree(void *ptr, const char* file, const char *function, const int line);
#endif //MEMORY_H
-2
View File
@@ -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"
-1
View File
@@ -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
-1
View File
@@ -11,7 +11,6 @@
#include "FTL.h"
#include "resolve.h"
#include "shmem.h"
#include "memory.h"
// struct config
#include "config.h"
// sleepms()
-1
View File
@@ -10,7 +10,6 @@
#include "FTL.h"
#include "log.h"
#include "memory.h"
#include "config.h"
#include "setupVars.h"
+5 -6
View File
@@ -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"
@@ -510,10 +509,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)",
@@ -634,10 +633,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)",
@@ -646,7 +645,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
+11 -3
View File
@@ -15,8 +15,6 @@
#include "signals.h"
// logg()
#include "log.h"
// free()
#include "memory.h"
// ls_dir()
#include "files.h"
// gettid()
@@ -247,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);
@@ -290,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
+37
View File
@@ -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
# /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
accept.c
asprintf.c
calloc.c
ftlallocate.c
fopen.c
fprintf.c
free.c
pthread_mutex_lock.c
realloc.c
recv.c
recvfrom.c
select.c
sendto.c
snprintf.c
sprintf.c
strdup.c
syscalls.h
vasprintf.c
vfprintf.c
vsnprintf.c
vsprintf.c
write.c
)
add_library(syscalls OBJECT ${sources})
target_compile_options(syscalls PRIVATE ${EXTRAWARN})
+36
View File
@@ -0,0 +1,36 @@
/* 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"
#undef accept
int FTLaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, const char *file, const char *func, 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",
func, file, line, strerror(errno));
return ret;
}
+23
View File
@@ -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;
}
+39
View File
@@ -0,0 +1,39 @@
/* 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 *func, const int line)
{
// 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
// passed to free().
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, func, file, line);
return ptr;
}
+36
View File
@@ -0,0 +1,36 @@
/* 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"
#undef fopen
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;
}
+23
View File
@@ -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 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 *file, const char *func, const int line, const char *format, ...)
{
va_list args;
va_start(args, format);
const int length = FTLvfprintf(stream, file, func, line, format, args);
va_end(args);
return length;
}
+29
View File
@@ -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 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 *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("WARN: Trying to free NULL pointer in %s() (%s:%i)", func, file, line);
return;
}
free(ptr);
}
+37
View File
@@ -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 <fcntl.h>
// 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;
}
+38
View File
@@ -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 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 <pthread.h>
#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;
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;
}
+43
View File
@@ -0,0 +1,43 @@
/* 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 * 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(), calloc() or realloc().
// If the area pointed to was moved, a free(ptr) is done implicitly.
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, func, file, line);
return ptr_out;
}
+38
View File
@@ -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 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 <sys/socket.h>
#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;
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;
}
+39
View File
@@ -0,0 +1,39 @@
/* 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 <sys/types.h>
#include <sys/socket.h>
#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;
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;
}
+38
View File
@@ -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 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 <sys/select.h>
#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;
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;
}
+39
View File
@@ -0,0 +1,39 @@
/* 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 <sys/types.h>
#include <sys/socket.h>
#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;
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;
}
+23
View File
@@ -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;
}
+23
View File
@@ -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;
}
+38
View File
@@ -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"
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)", func, file, line);
return NULL;
}
const size_t len = strlen(src);
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()
if(dest == NULL)
return NULL;
// Use memcpy as memory areas cannot overlap
memcpy(dest, src, len);
dest[len] = '\0';
return dest;
}
+53
View File
@@ -0,0 +1,53 @@
/* 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
* Syscall prototypes
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
#ifndef SYSCALLS_H
#define SYSCALLS_H
// 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);
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, ...)
// 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 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)));
// 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);
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);
// 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
+59
View File
@@ -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;
}
+168
View File
@@ -0,0 +1,168 @@
/* 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"
// 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<j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
// Variant of fputs that prints newline characters as "\n"
static int fputs_convert_newline(const char *string, FILE *stream)
{
int pos = 0;
while(string[pos] != '\0')
{
if(string[pos] == '\n')
{
fputc('\\', stream);
fputc('n', stream);
}
else
{
fputc(string[pos], stream);
}
pos++;
}
return pos;
}
// 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
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("\n Not processing string \"", stream);
fputs_convert_newline(format, stream);
fputs("\" in ", stream);
fputs(func, stream);
fputs("() [", stream);
fputs(file, stream);
fputs(":", stream);
fputs(linestr, stream);
fputs("]\n", stream);
}
// The actual vfprintf() routine
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;
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)
{
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);
// 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)
{
syscalls_report_error("vfprintf() did not print all characters",
stream, errno, format, func, file, line);
}
// Free allocated memory
free(buffer);
// Return number of written bytes
return length;
}
+59
View File
@@ -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, const 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;
}
+59
View File
@@ -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;
}
+46
View File
@@ -0,0 +1,46 @@
/* 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"
#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)
{
logg("ERROR: Trying to write a NULL string in %s() (%s:%i)", func, 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",
func, file, line, strerror(errno));
return written;
}
-1
View File
@@ -10,7 +10,6 @@
#include "FTL.h"
#include "timers.h"
#include "memory.h"
#include "log.h"
struct timespec t0[NUMTIMERS];