1
0

proj: Implement semaphore functions

This commit is contained in:
2025-02-17 15:00:30 +01:00
parent 9104c555eb
commit cc2b270d8f
4 changed files with 653 additions and 191 deletions

View File

@@ -1,12 +1,18 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from typing import Optional, TypedDict
from socketserver import UnixStreamServer, StreamRequestHandler, ThreadingMixIn from socketserver import UnixStreamServer, StreamRequestHandler, ThreadingMixIn
import argparse import argparse
import os import os
import re import re
type Pointer[T] = tuple[int, T]
type Flags = tuple[int, list[str]]
StructTimeSpec = TypedDict('StructTimeSpec', {'tv_sec': int, 'tv_nsec': int})
class ThreadedUnixStreamServer(ThreadingMixIn, UnixStreamServer): class ThreadedUnixStreamServer(ThreadingMixIn, UnixStreamServer):
pass pass
@@ -100,12 +106,35 @@ class Handler(StreamRequestHandler):
if idx < len(argument) and argument[idx] == ',': if idx < len(argument) and argument[idx] == ',':
idx += 1 idx += 1
return (val, list(l)), idx return (val, list(l)), idx
elif argument[idx] == '|':
m = re.match(r'^[| A-Za-z0-9_]*', argument[idx:])
flags = m.group(0)
if not flags.startswith('|') or not flags.endswith('|'):
raise ValueError()
idx += len(flags)
if idx < len(argument) and argument[idx] == ',':
idx += 1
flags = [f.strip() for f in flags[1:-1].split('|') if len(f.strip()) > 0]
return (val, flags), idx
elif argument[idx] == '"': elif argument[idx] == '"':
s, i = Handler.parse_str(argument[idx:]) s, i = Handler.parse_str(argument[idx:])
idx += i idx += i
if idx < len(argument) and argument[idx] == ',': if idx < len(argument) and argument[idx] == ',':
idx += 1 idx += 1
return (val, s), idx return (val, s), idx
elif argument[idx] == '{':
m = re.match(r'^[^}]*', argument[idx:])
value = m.group(0)
if not value.startswith('{') or not value.endswith('}'):
raise ValueError()
idx += len(value)
if idx < len(argument) and argument[idx] == ',':
idx += 1
entries = {}
for e in [v.strip() for v in value[1:-1].split(',') if len(e.strip()) > 0]:
k, v = e.split(':', 1)
entries[k.strip()] = int(v.strip(), 0)
return (val, entries), idx
else: else:
raise ValueError() raise ValueError()
@@ -133,7 +162,7 @@ class Handler(StreamRequestHandler):
try: try:
func = getattr(self, f'before_{func_name}') func = getattr(self, f'before_{func_name}')
if callable(func): if callable(func):
command = func(*args) command = func(*args) or 'ok'
else: else:
command = 'ok' command = 'ok'
except AttributeError: except AttributeError:
@@ -155,6 +184,42 @@ class Handler(StreamRequestHandler):
pass pass
print(f'[{self.pid}] -> {ret}') print(f'[{self.pid}] -> {ret}')
def before_malloc(self, size: int) -> str: pass
def after_malloc(self, size: int,
ret_value: int, errno: str = None) -> None: pass
def before_calloc(self, nmemb: int, size: int) -> str: pass
def after_calloc(self, nmemb: int, size: int,
ret_value: int, errno: str = None) -> None: pass
def before_realloc(self, ptr: int, size: int) -> str: pass
def after_realloc(self, ptr: int, size: int,
ret_value: int, errno: str = None) -> None: pass
def before_reallocarray(self, ptr: int, nmemb: int, size: int) -> str: pass
def after_reallocarray(self, ptr: int, nmemb: int, size: int,
ret_value: int, errno: str = None) -> None: pass
def before_free(self, ptr: int) -> str: pass
def after_free(self, ptr: int) -> None: pass
def before_getopt(self, argc: int, argv: Pointer[list[Pointer[bytes]]], optstring: Pointer[bytes]) -> str: pass
def after_getopt(self, argc: int, argv: Pointer[list[Pointer[bytes]]], optstring: Pointer[bytes],
ret_value: int) -> None: pass
def before_close(self, fildes: int) -> str: pass
def after_close(self, fildes: int,
ret_value: int, errno: str = None) -> None: pass
def before_sem_init(self, sem: int, pshared: int, value: int) -> str: pass
def after_sem_init(self, sem: int, pshared: int, value: int,
ret_value: int, errno: str = None) -> None: pass
def before_sem_open(self, name: str, oflag: Flags, mode: Optional[int], value: Optional[int]) -> str: pass
def after_sem_open(self, name: str, oflag: Flags, mode: Optional[int], value: Optional[int],
ret_value: int, errno: str = None) -> None: pass
def before_sem_post(self, sem: int) -> str: pass
def after_sem_post(self, sem: int,
ret_value: int, errno: str = None) -> None: pass
def before_sem_wait(self, sem: int) -> str: pass
def after_sem_wait(self, sem: int,
ret_value: int, errno: str = None) -> None: pass
def before_sem_timedwait(self, sem: int, abs_timeout: Pointer[StructTimeSpec]): pass
def after_sem_timedwait(self, sem: int, abs_timeout: Pointer[StructTimeSpec],
ret_value: int, errno: str = None): pass
class MemoryAllocationTester(Handler): class MemoryAllocationTester(Handler):
allocated: dict[int, int] allocated: dict[int, int]
@@ -184,20 +249,20 @@ class MemoryAllocationTester(Handler):
if total > self.max_allocated: if total > self.max_allocated:
self.max_allocated = total self.max_allocated = total
def after_malloc(self, size: int, ret_value: int) -> None: def after_malloc(self, size, ret_value, errno=None) -> None:
self.num_malloc += 1 self.num_malloc += 1
if ret_value != 0: if ret_value != 0:
print(ret_value) print(ret_value)
self.allocated[ret_value] = size self.allocated[ret_value] = size
self.update_max_allocated() self.update_max_allocated()
def after_calloc(self, nmemb: int, size: int, ret_value: int) -> None: def after_calloc(self, nmemb, size, ret_value, errno=None) -> None:
self.num_malloc += 1 self.num_malloc += 1
if ret_value != 0: if ret_value != 0:
self.allocated[ret_value] = nmemb * size self.allocated[ret_value] = nmemb * size
self.update_max_allocated() self.update_max_allocated()
def after_realloc(self, ptr: int, size: int, ret_value: int) -> None: def after_realloc(self, ptr, size, ret_value, errno=None) -> None:
self.num_realloc += 1 self.num_realloc += 1
if ptr != 0: if ptr != 0:
if ret_value != 0: if ret_value != 0:
@@ -205,7 +270,15 @@ class MemoryAllocationTester(Handler):
self.allocated[ret_value] = size self.allocated[ret_value] = size
self.update_max_allocated() self.update_max_allocated()
def after_free(self, ptr: int) -> None: def after_reallocarray(self, ptr, nmemb, size, ret_value, errno=None) -> None:
self.num_realloc += 1
if ptr != 0:
if ret_value != 0:
del self.allocated[ptr]
self.allocated[ret_value] = nmemb * size
self.update_max_allocated()
def after_free(self, ptr) -> None:
self.num_free += 1 self.num_free += 1
if ptr != 0: if ptr != 0:
del self.allocated[ptr] del self.allocated[ptr]

View File

@@ -20,18 +20,18 @@ class TestHandler(intercept.Handler):
else: else:
print("All blocks free'd!") print("All blocks free'd!")
def after_malloc(self, size: int, ret_value: int) -> None: def after_malloc(self, size, ret_value, errno=None) -> None:
if ret_value != 0: if ret_value != 0:
self.allocated[ret_value] = size self.allocated[ret_value] = size
def before_free(self, ptr: int) -> str: def before_free(self, ptr) -> str:
if ptr != 0: if ptr != 0:
del self.allocated[ptr] del self.allocated[ptr]
return 'ok' return 'ok'
class GetoptHandler(intercept.Handler): class GetoptHandler(intercept.Handler):
def after_getopt(self, argc: int, argv: tuple[int, list[tuple[int, bytes]]], optstring: tuple[int, bytes], ret_value: int) -> None: def after_getopt(self, argc, argv, optstring, ret_value) -> None:
print(argc, [v[1] for v in argv[1]], optstring[1], ret_value) print(argc, [v[1] for v in argv[1]], optstring[1], ret_value)

View File

@@ -22,10 +22,11 @@ test_kernel.ko: src/test_kernel.c
$(CC) -D__KERNEL__ -DMODULE -I/usr/src/linux/include -o $@ $^ $(CC) -D__KERNEL__ -DMODULE -I/usr/src/linux/include -o $@ $^
main: bin/main.o main: bin/main.o
$(CC) -o $@ $^ $(CFLAGS) -lc $(CC) -o $@ $^ $(CFLAGS) -lc -lpthread
main_intercept: bin/main.o src/intercept.c main_intercept: bin/main.o src/intercept.c
$(CC) -o $@ $^ $(CFLAGS) -lc -Wl,--wrap=malloc,--wrap=free,--wrap=calloc,--wrap=realloc,--wrap=reallocarray,--wrap=getopt $(CC) -o $@ $^ $(CFLAGS) -lc -Wl,--wrap=malloc,--wrap=free,--wrap=calloc,--wrap=realloc,--wrap=reallocarray,--wrap=getopt,--wrap=close,\
--wrap=sem_init,--wrap=sem_open,--wrap=sem_post,--wrap=sem_wait,--wrap=sem_trywait,--wrap=sem_timedwait,--wrap=sem_getvalue,--wrap=sem_close,--wrap=sem_unlink,--wrap=sem_destroy
clean: clean:
rm -rf main main_wrapped bin/* *.so *.ko *.o rm -rf main main_wrapped bin/* *.so *.ko *.o

View File

@@ -1,4 +1,6 @@
#define _GNU_SOURCE
#include <getopt.h> #include <getopt.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
@@ -10,8 +12,12 @@
#include <unistd.h> #include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <sys/stat.h>
#include <time.h> #include <time.h>
#include <stdarg.h> #include <stdarg.h>
#include <semaphore.h>
#define BUFFER_SIZE 256
#ifdef INTERCEPT_PRELOAD #ifdef INTERCEPT_PRELOAD
static void *(*__real_malloc)(size_t); static void *(*__real_malloc)(size_t);
@@ -20,6 +26,17 @@ static void *(*__real_realloc)(void *, size_t);
static void *(*__real_reallocarray)(void *, size_t, size_t); static void *(*__real_reallocarray)(void *, size_t, size_t);
static void (*__real_free)(void *); static void (*__real_free)(void *);
static int (*__real_getopt)(int, char *const [], const char *); static int (*__real_getopt)(int, char *const [], const char *);
static int (*__real_close)(int);
static int (*__real_sem_init)(sem_t *, int, unsigned int);
static sem_t *(*__real_sem_open)(const char *, int, ...);
static int (*__real_sem_post)(sem_t *);
static int (*__real_sem_wait)(sem_t *);
static int (*__real_sem_trywait)(sem_t *);
static int (*__real_sem_timedwait)(sem_t *restrict, const struct timespec *restrict);
static int (*__real_sem_getvalue)(sem_t *restrict, int *restrict);
static int (*__real_sem_close)(sem_t *);
static int (*__real_sem_unlink)(const char *);
static int (*__real_sem_destroy)(sem_t *);
#define __load(var, name) \ #define __load(var, name) \
if (((var) = dlsym(RTLD_NEXT, name)) == NULL) { \ if (((var) = dlsym(RTLD_NEXT, name)) == NULL) { \
fprintf(stderr, "intercept: unable to load symbol '%s': %s", name, strerror(errno)); \ fprintf(stderr, "intercept: unable to load symbol '%s': %s", name, strerror(errno)); \
@@ -33,9 +50,228 @@ extern void *__real_realloc(void *, size_t);
extern void *__real_reallocarray(void *, size_t, size_t); extern void *__real_reallocarray(void *, size_t, size_t);
extern void __real_free(void *); extern void __real_free(void *);
extern int __real_getopt(int, char *const [], const char *); extern int __real_getopt(int, char *const [], const char *);
extern int __real_close(int);
extern int __real_sem_init(sem_t *, int, unsigned int);
extern sem_t *__real_sem_open(const char *, int, ...);
extern int __real_sem_post(sem_t *);
extern int __real_sem_wait(sem_t *);
extern int __real_sem_trywait(sem_t *);
extern int __real_sem_timedwait(sem_t *restrict, const struct timespec *restrict);
extern int __real_sem_getvalue(sem_t *restrict, int *restrict);
extern int __real_sem_close(sem_t *);
extern int __real_sem_unlink(const char *);
extern int __real_sem_destroy(sem_t *);
#define __sym(name) __wrap_ ## name #define __sym(name) __wrap_ ## name
#endif #endif
#define if_invalid(name) if (strcmp(buf, "ok") != 0) { fprintf(stderr, "intercept: " #name ": invalid command: '%s'\n", buf); }
#define if_modify_int(name, type_1, var_1) if (strncmp(buf, "modify ", 7) == 0) { \
char *end_ptr = NULL; \
long val = strtol(buf + 7, &end_ptr, 0); \
if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) { \
var_1 = (type_1)val; \
} else { \
fprintf(stderr, "intercept: " #name ": invalid args in modify command: '%s'\n", buf + 7); \
} }
#define if_modify_int_int(name, type_1, var_1, type_2, var_2) if (strncmp(buf, "modify ", 7) == 0) { \
char *end_ptr_1 = NULL, *end_ptr_2 = NULL; \
long val_1 = strtol(buf + 7, &end_ptr_1, 0); \
long val_2 = 0; \
if (end_ptr_1 != NULL) val_2 = strtol(end_ptr_1 + 1, &end_ptr_2, 0); \
if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != buf + 7 && \
end_ptr_2 != NULL && end_ptr_2[0] == 0 && end_ptr_2 != end_ptr_1 + 1) \
{ \
var_1 = (type_1)val_1; \
var_2 = (type_2)val_2; \
} else { \
fprintf(stderr, "intercept: " #name ": invalid args in modify command: '%s'\n", buf + 7); \
} }
#define if_modify_int_int_int(name, type_1, var_1, type_2, var_2, type_3, var_3) if (strncmp(buf, "modify ", 7) == 0) { \
char *end_ptr_1 = NULL, *end_ptr_2 = NULL, *end_ptr_3; \
long val_1 = strtol(buf + 7, &end_ptr_1, 0); \
long val_2 = 0, val_3 = 0; \
if (end_ptr_1 != NULL) val_2 = strtol(end_ptr_1 + 1, &end_ptr_2, 0); \
if (end_ptr_2 != NULL) val_3 = strtol(end_ptr_2 + 1, &end_ptr_3, 0); \
if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != buf + 7 && \
end_ptr_2 != NULL && end_ptr_2[0] == ',' && end_ptr_2 != end_ptr_1 + 1 && \
end_ptr_3 != NULL && end_ptr_3[0] == 0 && end_ptr_3 != end_ptr_2 + 1) \
{ \
var_1 = (type_1)val_1; \
var_2 = (type_2)val_2; \
var_3 = (type_3)val_3; \
} else { \
fprintf(stderr, "intercept: " #name ": invalid args in modify command: '%s'\n", buf + 7); \
} }
#define if_return if (strcmp(buf, "return") == 0) { \
msg("return"); \
return; }
#define if_return_int(name) if (strncmp(buf, "return ", 7) == 0) { \
char *end_ptr = NULL; \
long val = strtol(buf + 7, &end_ptr, 0); \
if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) { \
msg("return %i", val); \
return val; \
} else { \
fprintf(stderr, "intercept: " #name ": invalid args in return command: '%s'\n", buf + 7); \
} }
#define if_return_int_errno(name) if (strncmp(buf, "return ", 7) == 0) { \
char *end_ptr = NULL; \
long val = strtol(buf + 7, &end_ptr, 0); \
if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) { \
msg("return %i; errno %s", val, strerrorname_np(errno)); \
return val; \
} else { \
fprintf(stderr, "intercept: " #name ": invalid args in return command: '%s'\n", buf + 7); \
} }
#define if_return_int_errno_int(name, type_1, var_1, name_1) if (strncmp(buf, "return ", 7) == 0) { \
char *end_ptr_1 = NULL, *end_ptr_2 = NULL; \
long val_1 = strtol(buf + 7, &end_ptr_1, 0); \
long val_2 = 0; \
if (end_ptr_1 != NULL) val_2 = strtol(end_ptr_1 + 1, &end_ptr_2, 0); \
if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != buf + 7 && \
end_ptr_2 != NULL && end_ptr_2[0] == 0 && end_ptr_2 != end_ptr_1 + 1) \
{ \
var_1 = (type_1)val_2; \
msg("return %i; errno %s; " name_1 "=%i", val_1, strerrorname_np(errno), var_1); \
return val_1; \
} else { \
fprintf(stderr, "intercept: " #name ": invalid args in return command: '%s'\n", buf + 7); \
} }
#define if_return_ptr_errno(name) if (strncmp(buf, "return ", 7) == 0) { \
char *end_ptr = NULL; \
long val = strtol(buf + 7, &end_ptr, 0); \
if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) { \
msg("return %p; errno %s", val, strerrorname_np(errno)); \
return (void *)val; \
} else { \
fprintf(stderr, "intercept: " #name ": invalid args in return command: '%s'\n", buf + 7); \
} }
#define if_error_1_ptr_errno(name, err1) if (strncmp(buf, "fail ", 5) == 0) { \
if (strcmp(buf + 5, #err1) == 0) { errno = err1; \
} else { \
errno = 0; \
fprintf(stderr, "intercept: " #name ": invalid error code in fail command: '%s'\n", buf + 5); \
} \
msg("return %p; errno %s", NULL, strerrorname_np(errno)); \
return NULL; }
#define if_error_1_int_errno(name, err1) if (strncmp(buf, "fail ", 5) == 0) { \
if (strcmp(buf + 5, #err1) == 0) { errno = err1; \
} else { \
errno = 0; \
fprintf(stderr, "intercept: " #name ": invalid error code in fail command: '%s'\n", buf + 5); \
} \
msg("return %i; errno %s", -1, strerrorname_np(errno)); \
return -1; }
#define if_error_2_int_errno(name, err1, err2) if (strncmp(buf, "fail ", 5) == 0) { \
if (strcmp(buf + 5, #err1) == 0) { errno = err1; \
} else if (strcmp(buf + 5, #err2) == 0) { errno = err2; \
} else { \
errno = 0; \
fprintf(stderr, "intercept: " #name ": invalid error code in fail command: '%s'\n", buf + 5); \
} \
msg("return %i; errno %s", -1, strerrorname_np(errno)); \
return -1; }
#define if_error_3_int_errno(name, err1, err2, err3) if (strncmp(buf, "fail ", 5) == 0) { \
if (strcmp(buf + 5, #err1) == 0) { errno = err1; \
} else if (strcmp(buf + 5, #err2) == 0) { errno = err2; \
} else if (strcmp(buf + 5, #err3) == 0) { errno = err3; \
} else { \
errno = 0; \
fprintf(stderr, "intercept: " #name ": invalid error code in fail command: '%s'\n", buf + 5); \
} \
msg("return %i; errno %s", -1, strerrorname_np(errno)); \
return -1; }
#define if_error_8_ptr_errno(name, err1, err2, err3, err4, err5, err6, err7, err8) if (strncmp(buf, "fail ", 5) == 0) { \
if (strcmp(buf + 5, #err1) == 0) { errno = err1; \
} else if (strcmp(buf + 5, #err2) == 0) { errno = err2; \
} else if (strcmp(buf + 5, #err3) == 0) { errno = err3; \
} else if (strcmp(buf + 5, #err4) == 0) { errno = err4; \
} else if (strcmp(buf + 5, #err5) == 0) { errno = err5; \
} else if (strcmp(buf + 5, #err6) == 0) { errno = err6; \
} else if (strcmp(buf + 5, #err6) == 0) { errno = err7; \
} else if (strcmp(buf + 5, #err8) == 0) { errno = err8; \
} else { \
errno = 0; \
fprintf(stderr, "intercept: " #name ": invalid error code in fail command: '%s'\n", buf + 5); \
} \
msg("return %p; errno %s", NULL, strerrorname_np(errno)); \
return NULL; }
static char *strtostr(char *ptr, char **end_ptr, char *buf) {
if (ptr[0] != '"') return NULL;
int i = 0, esc = 0, hex = 0;
for (*end_ptr = ptr + 1; *end_ptr[0] != 0; (*end_ptr)++) {
char ch = *end_ptr[0];
if (esc) {
if (esc == 2) {
if (ch >= '0' && ch <= '9') {
hex = (ch - '0') << 4;
} else if (ch >= 'A' && ch <= 'F') {
hex = (ch - 'A' + 10) << 4;
} else if (ch >= 'a' && ch <= 'f') {
hex = (ch - 'a' + 10) << 4;
} else {
return NULL;
}
esc = 3;
continue;
} else if (esc == 3) {
if (ch >= '0' && ch <= '9') {
hex |= (ch - '0');
} else if (ch >= 'A' && ch <= 'F') {
hex |= (ch - 'A' + 10);
} else if (ch >= 'a' && ch <= 'f') {
hex |= (ch - 'a' + 10);
} else {
return NULL;
}
buf[i++] = (char)hex;
esc = 0;
continue;
}
switch (ch) {
case 'a': ch = '\a'; break;
case 'b': ch = '\b'; break;
case 't': ch = '\t'; break;
case 'n': ch = '\n'; break;
case 'v': ch = '\v'; break;
case 'f': ch = '\f'; break;
case 'r': ch = '\r'; break;
case '0': ch = 0; break;
case 'x': esc = 2; continue;
case '"':
case '\\':
break;
default: return NULL;
}
buf[i++] = ch;
esc = 0;
} else if (ch == '\\') {
esc = 1;
} else if (ch == '"') {
(*end_ptr)++;
return buf;
} else {
buf[i++] = ch;
}
}
return NULL;
}
static int mode = 0; static int mode = 0;
static int intercept = 0; static int intercept = 0;
@@ -202,6 +438,17 @@ static void init(void) {
__load(__real_reallocarray, "reallocarray"); __load(__real_reallocarray, "reallocarray");
__load(__real_free, "free"); __load(__real_free, "free");
__load(__real_getopt, "getopt"); __load(__real_getopt, "getopt");
__load(__real_close, "close");
__load(__real_sem_init, "sem_init");
__load(__real_sem_open, "sem_open");
__load(__real_sem_post, "sem_post");
__load(__real_sem_wait, "sem_wait");
__load(__real_sem_wait, "sem_trywait");
__load(__real_sem_wait, "sem_timedwait");
__load(__real_sem_getvalue, "sem_getvalue");
__load(__real_sem_close, "sem_close");
__load(__real_sem_unlink, "sem_unlink");
__load(__real_sem_destroy, "sem_destroy");
#endif #endif
atexit(fin); atexit(fin);
const char *val = getenv("INTERCEPT"); const char *val = getenv("INTERCEPT");
@@ -254,43 +501,15 @@ void *__sym(malloc)(size_t size) {
init(); init();
msg("malloc(%li)", size); msg("malloc(%li)", size);
if (mode >= 4) { if (mode >= 4) {
char buf[256]; char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf)); rcv(buf, sizeof(buf));
if (strncmp(buf, "modify ", 7) == 0) { if_modify_int(malloc, size_t, size)
// modify <size> else if_return_ptr_errno(malloc)
char *end_ptr = NULL; else if_error_1_ptr_errno(malloc, ENOMEM)
long val = strtol(buf + 7, &end_ptr, 0); else if_invalid(malloc)
if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) {
size = val;
} else {
fprintf(stderr, "intercept: malloc: invalid args in modify command: '%s'\n", buf + 7);
}
} else if (strncmp(buf, "return ", 7) == 0) {
// return <ptr>
char *end_ptr = NULL;
long val = strtol(buf + 7, &end_ptr, 0);
if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) {
msg("return %p", val);
return (void *)val;
} else {
fprintf(stderr, "intercept: malloc: invalid args in return command: '%s'\n", buf + 7);
}
} else if (strncmp(buf, "fail ", 5) == 0) {
// fail <error>
if (strcmp(buf + 5, "ENOMEM") == 0) {
errno = ENOMEM;
} else {
errno = 0;
fprintf(stderr, "intercept: malloc: invalid error code in fail command: '%s'\n", buf + 5);
}
msg("return %p", NULL);
return NULL;
} else if (strcmp(buf, "ok") != 0) {
fprintf(stderr, "intercept: malloc: invalid command: '%s'\n", buf);
}
} }
void *ret = __real_malloc(size); void *ret = __real_malloc(size);
msg("return %p", ret); msg("return %p; errno %s", ret, strerrorname_np(errno));
return ret; return ret;
} }
@@ -298,46 +517,15 @@ void *__sym(calloc)(size_t nmemb, size_t size) {
init(); init();
msg("calloc(%li, %li)", nmemb, size); msg("calloc(%li, %li)", nmemb, size);
if (mode >= 4) { if (mode >= 4) {
char buf[256]; char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf)); rcv(buf, sizeof(buf));
if (strncmp(buf, "modify ", 7) == 0) { if_modify_int_int(calloc, size_t, nmemb, size_t, size)
// modify <nmemb>,<size> else if_return_ptr_errno(calloc)
char *end_ptr_1 = NULL, *end_ptr_2 = NULL; else if_error_1_ptr_errno(calloc, ENOMEM)
long val_1 = strtol(buf + 7, &end_ptr_1, 0); else if_invalid(calloc)
long val_2 = 0;
if (end_ptr_1 != NULL) val_2 = strtol(end_ptr_1 + 1, &end_ptr_2, 0);
if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != buf + 7 && end_ptr_2 != NULL && end_ptr_2[0] == 0 && end_ptr_2 != end_ptr_1 + 1) {
nmemb = val_1;
size = val_2;
} else {
fprintf(stderr, "intercept: calloc: invalid args in modify command: '%s'\n", buf + 7);
}
} else if (strncmp(buf, "return ", 7) == 0) {
// return <ptr>
char *end_ptr = NULL;
long val = strtol(buf + 7, &end_ptr, 0);
if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) {
msg("return %p", val);
return (void *)val;
} else {
fprintf(stderr, "intercept: calloc: invalid args in return command: '%s'\n", buf + 7);
}
} else if (strncmp(buf, "fail ", 5) == 0) {
// fail <error>
if (strcmp(buf + 5, "ENOMEM") == 0) {
errno = ENOMEM;
} else {
errno = 0;
fprintf(stderr, "intercept: calloc: invalid error code in fail command: '%s'\n", buf + 5);
}
msg("return %p", NULL);
return NULL;
} else if (strcmp(buf, "ok") != 0) {
fprintf(stderr, "intercept: calloc: invalid command: '%s'\n", buf);
}
} }
void *ret = __real_calloc(nmemb, size); void *ret = __real_calloc(nmemb, size);
msg("return %p", ret); msg("return %p; errno %s", ret, strerrorname_np(errno));
return ret; return ret;
} }
@@ -345,47 +533,15 @@ void *__sym(realloc)(void *ptr, size_t size) {
init(); init();
msg("realloc(%p, %li)", ptr, size); msg("realloc(%p, %li)", ptr, size);
if (mode >= 4) { if (mode >= 4) {
char buf[256]; char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf)); rcv(buf, sizeof(buf));
if (strncmp(buf, "modify ", 7) == 0) { if_modify_int_int(realloc, void *, ptr, size_t, size)
// modify <ptr>,<size> else if_return_ptr_errno(realloc)
char *end_ptr_1 = NULL, *end_ptr_2 = NULL; else if_error_1_ptr_errno(realloc, ENOMEM)
long val_1 = strtol(buf + 7, &end_ptr_1, 0); else if_invalid(realloc)
long val_2 = 0;
if (end_ptr_1 != NULL) val_2 = strtol(end_ptr_1 + 1, &end_ptr_2, 0);
if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != buf + 7 &&
end_ptr_2 != NULL && end_ptr_2[0] == 0 && end_ptr_2 != end_ptr_1 + 1) {
ptr = (void *)val_1;
size = val_2;
} else {
fprintf(stderr, "intercept: realloc: invalid args in modify command: '%s'\n", buf + 7);
}
} else if (strncmp(buf, "return ", 7) == 0) {
// return <ptr>
char *end_ptr = NULL;
long val = strtol(buf + 7, &end_ptr, 0);
if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) {
msg("return %p", val);
return (void *)val;
} else {
fprintf(stderr, "intercept: realloc: invalid args in return command: '%s'\n", buf + 7);
}
} else if (strncmp(buf, "fail ", 5) == 0) {
// fail <error>
if (strcmp(buf + 5, "ENOMEM") == 0) {
errno = ENOMEM;
} else {
errno = 0;
fprintf(stderr, "intercept: realloc: invalid error code in fail command: '%s'\n", buf + 5);
}
msg("return %p", NULL);
return NULL;
} else if (strcmp(buf, "ok") != 0) {
fprintf(stderr, "intercept: realloc: invalid command: '%s'\n", buf);
}
} }
void *ret = __real_realloc(ptr, size); void *ret = __real_realloc(ptr, size);
msg("return %p", ret); msg("return %p; errno %s", ret, strerrorname_np(errno));
return ret; return ret;
} }
@@ -393,50 +549,15 @@ void *__sym(reallocarray)(void *ptr, size_t nmemb, size_t size) {
init(); init();
msg("reallocarray(%p, %li)", ptr, size); msg("reallocarray(%p, %li)", ptr, size);
if (mode >= 4) { if (mode >= 4) {
char buf[256]; char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf)); rcv(buf, sizeof(buf));
if (strncmp(buf, "modify ", 7) == 0) { if_modify_int_int_int(reallocarray, void *, ptr, size_t, nmemb, size_t, size)
// modify <ptr>,<nmemb>,<size> else if_return_ptr_errno(reallocarray)
char *end_ptr_1 = NULL, *end_ptr_2 = NULL, *end_ptr_3; else if_error_1_ptr_errno(reallocarray, ENOMEM)
long val_1 = strtol(buf + 7, &end_ptr_1, 0); else if_invalid(reallocarray)
long val_2 = 0, val_3 = 0;
if (end_ptr_1 != NULL) val_2 = strtol(end_ptr_1 + 1, &end_ptr_2, 0);
if (end_ptr_2 != NULL) val_3 = strtol(end_ptr_2 + 1, &end_ptr_3, 0);
if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != buf + 7 &&
end_ptr_2 != NULL && end_ptr_2[0] == ',' && end_ptr_2 != end_ptr_1 + 1 &&
end_ptr_3 != NULL && end_ptr_3[0] == 0 && end_ptr_3 != end_ptr_2 + 1) {
ptr = (void *)val_1;
nmemb = val_2;
size = val_3;
} else {
fprintf(stderr, "intercept: reallocarray: invalid args in modify command: '%s'\n", buf + 7);
}
} else if (strncmp(buf, "return ", 7) == 0) {
// return <ptr>
char *end_ptr = NULL;
long val = strtol(buf + 7, &end_ptr, 0);
if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) {
msg("return %p", val);
return (void *)val;
} else {
fprintf(stderr, "intercept: reallocarray: invalid args in return command: '%s'\n", buf + 7);
}
} else if (strncmp(buf, "fail ", 5) == 0) {
// fail <error>
if (strcmp(buf + 5, "ENOMEM") == 0) {
errno = ENOMEM;
} else {
errno = 0;
fprintf(stderr, "intercept: reallocarray: invalid error code in fail command: '%s'\n", buf + 5);
}
msg("return %p", NULL);
return NULL;
} else if (strcmp(buf, "ok") != 0) {
fprintf(stderr, "intercept: reallocarray: invalid command: '%s'\n", buf);
}
} }
void *ret = __real_reallocarray(ptr, nmemb, size); void *ret = __real_reallocarray(ptr, nmemb, size);
msg("return %p", ret); msg("return %p; errno %s", ret, strerrorname_np(errno));
return ret; return ret;
} }
@@ -444,24 +565,11 @@ void __sym(free)(void *ptr) {
init(); init();
msg("free(%p)", ptr); msg("free(%p)", ptr);
if (mode >= 4) { if (mode >= 4) {
char buf[256]; char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf)); rcv(buf, sizeof(buf));
if (strncmp(buf, "modify ", 7) == 0) { if_modify_int(free, void *, ptr)
// modify <ptr> else if_return
char *end_ptr = NULL; else if_invalid(free)
long val = strtol(buf + 7, &end_ptr, 0);
if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) {
ptr = (void *)val;
} else {
fprintf(stderr, "intercept: free: invalid args in modify command: '%s'\n", buf + 7);
}
} else if (strcmp(buf, "return") == 0) {
// return
msg("return");
return;
} else if (strcmp(buf, "ok") != 0) {
fprintf(stderr, "intercept: free: invalid command: '%s'\n", buf);
}
} }
__real_free(ptr); __real_free(ptr);
msg("return"); msg("return");
@@ -471,27 +579,307 @@ int __sym(getopt)(const int argc, char *const argv[], const char *shortopts) {
init(); init();
msg("getopt(%i, %as, %es)", argc, argv, argc, shortopts); msg("getopt(%i, %as, %es)", argc, argv, argc, shortopts);
if (mode >= 4) { if (mode >= 4) {
char buf[256]; char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf)); rcv(buf, sizeof(buf));
if (strncmp(buf, "modify ", 7) == 0) { if (strncmp(buf, "modify ", 7) == 0) {
// modify <argc>,<argv>,<shortopts> // modify <argc>,<argv>,<shortopts>
// TODO getopt modify // TODO getopt modify
fprintf(stderr, "intercept: getopt: modify command not implemented\n"); fprintf(stderr, "intercept: getopt: modify command not implemented\n");
} else if (strncmp(buf, "return ", 7) == 0) { } else if_return_int(getopt)
// return <chr> else if_invalid(getopt)
char *end_ptr = NULL;
long val = strtol(buf + 7, &end_ptr, 0);
if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) {
msg("return %i", val);
return (int)val;
} else {
fprintf(stderr, "intercept: getopt: invalid args in return command: '%s'\n", buf + 7);
}
} else if (strcmp(buf, "ok") != 0) {
fprintf(stderr, "intercept: getopt: invalid command: '%s'\n", buf);
}
} }
const int ret = __real_getopt(argc, argv, shortopts); const int ret = __real_getopt(argc, argv, shortopts);
msg("return %i", ret); msg("return %i", ret);
return ret; return ret;
} }
int __sym(close)(int fildes) {
init();
msg("close(%i)", fildes);
if (mode >= 4) {
char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf));
if_modify_int(close, int, fildes)
else if_return_int_errno(close)
else if_error_3_int_errno(close, EBADF, EINTR, EIO)
else if_invalid(close)
}
const int ret = __real_close(fildes);
msg("return %i; errno %s", ret, strerrorname_np(errno));
return ret;
}
int __sym(sem_init)(sem_t *sem, int pshared, unsigned int value) {
init();
msg("sem_init(%p, %i, %u)", sem, pshared, value);
if (mode >= 4) {
char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf));
if_modify_int_int_int(sem_init, sem_t *, sem, int, pshared, unsigned int, value)
else if_return_int_errno(sem_init)
else if_error_2_int_errno(sem_init, EINVAL, ENOSYS)
else if_invalid(sem_init)
}
const int ret = __real_sem_init(sem, pshared, value);
msg("return %i; errno %s", ret, strerrorname_np(errno));
return ret;
}
sem_t *__sym(sem_open)(const char *name, int oflag, ...) {
init();
char ostr[32] = "|";
if (oflag & O_CREAT) strcat(ostr, "O_CREAT|");
if (oflag & O_EXCL) strcat(ostr, "O_EXCL|");
if (oflag & ~(O_CREAT | O_EXCL)) strcat(ostr, "?|");
mode_t mode_arg = 0;
unsigned int value = 0;
if (oflag & O_CREAT) {
va_list args;
va_start(args, oflag);
mode_arg = va_arg(args, mode_t);
value = va_arg(args, unsigned int);
va_end(args);
msg("sem_open(%es, 0%o:|%s, 0%03o, %u)", name, oflag, ostr, mode_arg, value);
} else {
msg("sem_open(%es, 0%o:|%s)", name, oflag, ostr);
}
char overwrite[BUFFER_SIZE];
if (mode >= 4) {
char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf));
if (strncmp(buf, "modify ", 7) == 0) {
// modify <name>,<oflag>
// modify <name>,<oflag>,<mode>,<value>
char *val_1 = NULL, *end_ptr_1 = NULL, *end_ptr_2 = NULL, *end_ptr_3 = NULL, *end_ptr_4 = NULL;
long val_2 = 0, val_3 = 0, val_4 = 0;
if (buf[7] == '"') {
// modify "<name>",...
val_1 = strtostr(buf + 7, &end_ptr_1, overwrite);
if (val_1 == NULL) end_ptr_1 = NULL;
} else {
// modify <name_ptr>,...
val_1 = (char *)strtol(buf + 7, &end_ptr_1, 0);
}
if (end_ptr_1 != NULL && end_ptr_1[0] != 0) {
if (end_ptr_1[1] == '|') {
val_2 = 0;
end_ptr_2 = end_ptr_1 + 1;
if (strncmp(end_ptr_2, "O_CREAT|", 8) == 0) {
val_2 |= O_CREAT;
end_ptr_2 += 8;
}
if (strncmp(end_ptr_2, "O_EXCL|", 7) == 0) {
val_2 |= O_EXCL;
end_ptr_2 += 7;
}
} else {
val_2 = strtol(end_ptr_1 + 1, &end_ptr_2, 0);
}
}
if (end_ptr_2 != NULL && end_ptr_2[0] != 0) val_3 = strtol(end_ptr_2 + 1, &end_ptr_3, 0);
if (end_ptr_3 != NULL && end_ptr_3[0] != 0) val_4 = strtol(end_ptr_3 + 1, &end_ptr_4, 0);
if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != buf + 7 &&
end_ptr_2 != NULL && (end_ptr_2[0] == 0 || end_ptr_2[0] == ',') && end_ptr_2 != end_ptr_1 + 1 &&
(end_ptr_2[0] == 0 || (end_ptr_3 != NULL && end_ptr_3[0] == ',' && end_ptr_3 != end_ptr_2 + 1 &&
end_ptr_4 != NULL && end_ptr_4[0] == 0 && end_ptr_4 != end_ptr_3 + 1)))
{
name = val_1;
oflag = (int)val_2;
if (end_ptr_2[0] != 0) {
mode_arg = val_3;
value = val_4;
}
} else {
fprintf(stderr, "intercept: sem_open: invalid args in modify command: '%s'\n", buf + 7); \
}
fprintf(stderr, "intercept: sem_open: not implemented\n");
} else if_return_ptr_errno(sem_open)
else if_error_8_ptr_errno(sem_open, EACCES, EEXIST, EINVAL, EMFILE, ENAMETOOLONG, ENFILE, ENOENT, ENOMEM)
else if_invalid(sem_open)
}
sem_t *ret;
if (oflag & O_CREAT) {
ret = __real_sem_open(name, oflag, mode_arg, value);
} else {
ret = __real_sem_open(name, oflag);
}
msg("return %p; errno %s", ret, strerrorname_np(errno));
return ret;
}
int __sym(sem_post)(sem_t *sem) {
init();
msg("sem_post(%p)", sem);
if (mode >= 4) {
char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf));
if_modify_int(sem_post, sem_t *, sem)
else if_return_int_errno(sem_post)
else if_error_2_int_errno(sem_post, EINVAL, EOVERFLOW)
else if_invalid(sem_post)
}
const int ret = __real_sem_post(sem);
msg("return %i; errno %s", ret, strerrorname_np(errno));
return ret;
}
int __sym(sem_wait)(sem_t *sem) {
init();
msg("sem_wait(%p)", sem);
if (mode >= 4) {
char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf));
if_modify_int(sem_wait, sem_t *, sem)
else if_return_int_errno(sem_wait)
else if_error_2_int_errno(sem_wait, EINTR, EINVAL)
else if_invalid(sem_wait)
}
const int ret = __real_sem_wait(sem);
msg("return %i; errno %s", ret, strerrorname_np(errno));
return ret;
}
int __sym(sem_trywait)(sem_t *sem) {
init();
msg("sem_trywait(%p)", sem);
if (mode >= 4) {
char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf));
if_modify_int(sem_trywait, sem_t *, sem)
else if_return_int_errno(sem_trywait)
else if_error_3_int_errno(sem_trywait, EAGAIN, EINTR, EINVAL)
else if_invalid(sem_trywait)
}
const int ret = __real_sem_trywait(sem);
msg("return %i; errno %s", ret, strerrorname_np(errno));
return ret;
}
int __sym(sem_timedwait)(sem_t *restrict sem, const struct timespec *restrict abs_timeout) {
init();
msg("sem_timedwait(%p, %p:{tv_sec: %li, tv_nsec: %li})", sem, abs_timeout, abs_timeout->tv_sec, abs_timeout->tv_nsec);
struct timespec overwrite;
if (mode >= 4) {
char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf));
if (strncmp(buf, "modify ", 7) == 0) {
// modfiy <sem>,<abs_timeout_ptr>
// modify <sem>,{<tv_sec>,<tv_nsec>}
char *end_ptr_1 = NULL, *end_ptr_2 = NULL, *end_ptr_3 = NULL;
long val_1 = strtol(buf + 7, &end_ptr_1, 0);
struct timespec *val_2 = 0;
if (end_ptr_1 != NULL && end_ptr_1[0] != 0) {
if (end_ptr_1[1] == '{') {
long sec = 0, nsec = 0;
sec = strtol(end_ptr_1 + 2, &end_ptr_2, 0);
if (end_ptr_2 != NULL && end_ptr_2[0] == ',') nsec = strtol(end_ptr_2 + 1, &end_ptr_3, 0);
overwrite.tv_sec = sec;
overwrite.tv_nsec = nsec;
if (end_ptr_3 != NULL && end_ptr_3[0] == '}' && end_ptr_3[1] == 0) {
val_2 = &overwrite;
end_ptr_2 = end_ptr_3 + 1;
}
} else {
val_2 = (void *)strtol(end_ptr_1 + 1, &end_ptr_2, 0);
}
}
if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != buf + 7 &&
end_ptr_2 != NULL && end_ptr_2[0] == 0 && end_ptr_2 != end_ptr_1 + 1)
{
sem = (sem_t *)val_1;
abs_timeout = val_2;
} else {
fprintf(stderr, "intercept: sem_timedwait: invalid args in modify command: '%s'\n", buf + 7); \
}
} else if_return_int_errno(sem_timedwait)
else if_error_3_int_errno(sem_timedwait, EINTR, EINVAL, ETIMEDOUT)
else if_invalid(sem_timedwait)
}
const int ret = __real_sem_timedwait(sem, abs_timeout);
msg("return %i; errno %s", ret, strerrorname_np(errno));
return ret;
}
int __sym(sem_getvalue)(sem_t *restrict sem, int *restrict value) {
init();
msg("sem_getvalue(%p, %p)", sem, value);
if (mode >= 4) {
char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf));
if_modify_int_int(sem_getvalue, sem_t *, sem, int *, value)
else if_return_int_errno_int(sem_getvalue, int, *value, "value")
else if_error_1_int_errno(sem_getvalue, EINVAL)
else if_invalid(sem_getvalue)
}
const int ret = __real_sem_getvalue(sem, value);
msg("return %i; errno %s; value=%i", ret, strerrorname_np(errno), *value);
return ret;
}
int __sym(sem_close)(sem_t *sem) {
init();
msg("sem_close(%p)", sem);
if (mode >= 4) {
char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf));
if_modify_int(sem_close, sem_t *, sem)
else if_return_int_errno(sem_close)
else if_error_1_int_errno(sem_close, EINVAL)
else if_invalid(sem_close)
}
const int ret = __real_sem_close(sem);
msg("return %i; errno %s", ret, strerrorname_np(errno));
return ret;
}
int __sym(sem_unlink)(const char *name) {
init();
msg("sem_unlink(%es)", name);
char overwrite[BUFFER_SIZE];
if (mode >= 4) {
char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf));
if (strncmp(buf, "modify ", 7) == 0) {
char *end_ptr = NULL, *val = NULL;
if (buf[7] == '"') {
// modify "<name>"
val = strtostr(buf + 7, &end_ptr, overwrite);
if (val == NULL) end_ptr = NULL;
} else {
// modify <name_ptr>
val = (char *)strtol(buf + 7, &end_ptr, 0);
}
if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) {
name = val;
} else {
fprintf(stderr, "intercept: sem_unlink: invalid args in modify command: '%s'\n", buf + 7); \
}
} else if_return_int_errno(sem_unlink)
else if_error_3_int_errno(sem_unlink, EACCES, ENAMETOOLONG, ENOENT)
else if_invalid(sem_unlink)
}
const int ret = __real_sem_unlink(name);
msg("return %p; errno %s", ret, strerrorname_np(errno));
return ret;
}
int __sym(sem_destroy)(sem_t *sem) {
init();
msg("sem_destroy(%p)", sem);
if (mode >= 4) {
char buf[BUFFER_SIZE];
rcv(buf, sizeof(buf));
if_modify_int(sem_destroy, sem_t *, sem)
else if_return_int_errno(sem_destroy)
else if_error_1_int_errno(sem_destroy, EINVAL)
else if_invalid(sem_destroy)
}
const int ret = __real_sem_destroy(sem);
msg("return %p; errno %s", ret, strerrorname_np(errno));
return ret;
}