proj: Implement fork/exec/pipe
This commit is contained in:
@@ -19,10 +19,12 @@ intercept.so: bin/intercept_preload.o
|
|||||||
$(CC) -shared -o $@ $^ $(CFLAGS) -lc -ldl
|
$(CC) -shared -o $@ $^ $(CFLAGS) -lc -ldl
|
||||||
|
|
||||||
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,--wrap=exit,--wrap=close,--wrap=sigaction,\
|
$(CC) -o $@ $^ $(CFLAGS) -lc -Wl,--wrap=malloc,--wrap=free,--wrap=calloc,--wrap=realloc,--wrap=reallocarray,--wrap=getopt,--wrap=exit,\
|
||||||
|
--wrap=read,--wrap=pread,--wrap=write,--wrap=pwrite,--wrap=close,--wrap=sigaction,\
|
||||||
--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,\
|
--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,\
|
||||||
--wrap=shm_open,--wrap=shm_unlink,--wrap=mmap,--wrap=munmap,\
|
--wrap=shm_open,--wrap=shm_unlink,--wrap=mmap,--wrap=munmap,\
|
||||||
--wrap=ftruncate
|
--wrap=ftruncate,--wrap=fork,--wrap=wait,--wrap=waitpid,--wrap=pipe,--wrap=dup,--wrap=dup2,--wrap=dup3,\
|
||||||
|
--wrap=execl,--wrap=execlp,--wrap=execle,--wrap=execv,--wrap=execvp,--wrap=execvpe,--wrap=execve,--wrap=fexecve
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf main_intercept bin/* *.so *.ko *.o
|
rm -rf main_intercept bin/* *.so *.ko *.o
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -90,7 +90,7 @@ class Handler(StreamRequestHandler):
|
|||||||
def parse_arg(argument: str) -> tuple[any, int]:
|
def parse_arg(argument: str) -> tuple[any, int]:
|
||||||
if argument == '':
|
if argument == '':
|
||||||
return None, 0
|
return None, 0
|
||||||
m = re.match(r'^\s*\(nil\)\s*(,|$)', argument)
|
m = re.match(r'^\s*(\(nil\)|NULL|null|nullptr)\s*(,|$)', argument)
|
||||||
if m:
|
if m:
|
||||||
return 0, len(m.group(0))
|
return 0, len(m.group(0))
|
||||||
m = re.match(r'^\s*(.*?)([,:]|$)', argument)
|
m = re.match(r'^\s*(.*?)([,:]|$)', argument)
|
||||||
@@ -232,6 +232,30 @@ class Handler(StreamRequestHandler):
|
|||||||
def after_getopt(self, argc: int, argv: PointerTo[list[PointerTo[bytes]]], optstring: PointerTo[bytes],
|
def after_getopt(self, argc: int, argv: PointerTo[list[PointerTo[bytes]]], optstring: PointerTo[bytes],
|
||||||
ret_value: int) -> None:
|
ret_value: int) -> None:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
def before_exit(self, status: int) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_exit(self, status: int) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_read(self, fildes: int, buf_ptr: Pointer, nbyte: int) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_read(self, fildes: int, buf_ptr: Pointer, nbyte: int,
|
||||||
|
ret_value: int, errno: str = None, buf: PointerTo[bytes] = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_pread(self, fildes: int, buf_ptr: Pointer, nbyte: int, offset: int) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_pread(self, fildes: int, buf_ptr: Pointer, nbyte: int, offset: int,
|
||||||
|
ret_value: int, errno: str = None, buf: PointerTo[bytes] = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_write(self, fildes: int, buf: PointerTo[bytes], nbyte: int) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_write(self, fildes: int, buf: PointerTo[bytes], nbyte: int,
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_pwrite(self, fildes: int, buf: PointerTo[bytes], nbyte: int, offste: int) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_pwrite(self, fildes: int, buf: PointerTo[bytes], nbyte: int, offste: int,
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
def before_close(self, fildes: int) -> str:
|
def before_close(self, fildes: int) -> str:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
def after_close(self, fildes: int,
|
def after_close(self, fildes: int,
|
||||||
@@ -317,6 +341,81 @@ class Handler(StreamRequestHandler):
|
|||||||
def after_ftruncate(self, fildes: int, length: int,
|
def after_ftruncate(self, fildes: int, length: int,
|
||||||
ret_value: int, errno: str = None) -> None:
|
ret_value: int, errno: str = None) -> None:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
def before_fork(self) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_fork(self,
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_wait(self, stat_loc: Pointer) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_wait(self, stat_loc: Pointer,
|
||||||
|
ret_value: int, errno: str = None, stat: int = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_waitpid(self, pid: int, stat_loc: Pointer, options: Flags) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_waitpid(self, pid: int, stat_loc: Pointer, options: Flags,
|
||||||
|
ret_value: int, errno: str = None, stat: int = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_execl(self, pathname: PointerTo[bytes], *args: list[PointerTo[bytes]]) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_execl(self, pathname: PointerTo[bytes], *args: list[PointerTo[bytes]],
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_execlp(self, file: PointerTo[bytes], *args: list[PointerTo[bytes]]) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_execlp(self, file: PointerTo[bytes], *args: list[PointerTo[bytes]],
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_execle(self, pathname: PointerTo[bytes], *args: list[PointerTo[bytes]], envp: PointerTo[list[PointerTo[bytes]]]) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_execle(self, pathname: PointerTo[bytes], *args: list[PointerTo[bytes]], envp: PointerTo[list[PointerTo[bytes]]],
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_execv(self, pathname: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]]) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_execv(self, pathname: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]],
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_execvp(self, file: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]]) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_execvp(self, file: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]],
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_execvpe(self, file: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]], envp: PointerTo[list[PointerTo[bytes]]]) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_execvpe(self, file: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]], envp: PointerTo[list[PointerTo[bytes]]],
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_execve(self, pathname: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]], envp: PointerTo[list[PointerTo[bytes]]]) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_execve(self, pathname: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]], envp: PointerTo[list[PointerTo[bytes]]],
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_fexecve(self, fd: int, argv: PointerTo[list[PointerTo[bytes]]], envp: PointerTo[list[PointerTo[bytes]]]) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_fexecve(self, fd: int, argv: PointerTo[list[PointerTo[bytes]]], envp: PointerTo[list[PointerTo[bytes]]],
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_pipe(self, fildes: PointerTo[list[int]]) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_pipe(self, fildes: PointerTo[list[int]],
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_dup(self, oldfd: int) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_dup(self, oldfd: int,
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_dup2(self, oldfd: int, newfd: int) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_dup2(self, oldfd: int, newfd: int,
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def before_dup3(self, oldfd: int, newfd: int, flags: Flags) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
def after_dup3(self, oldfd: int, newfd: int, flags: Flags,
|
||||||
|
ret_value: int, errno: str = None) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
def intercept(socket: str, handler: type[Handler]) -> None:
|
def intercept(socket: str, handler: type[Handler]) -> None:
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ FUNCTION_ERRORS: dict[str, list[str]] = {
|
|||||||
'calloc': ['ENOMEM'],
|
'calloc': ['ENOMEM'],
|
||||||
'realloc': ['ENOMEM'],
|
'realloc': ['ENOMEM'],
|
||||||
'reallocarray': ['ENOMEM'],
|
'reallocarray': ['ENOMEM'],
|
||||||
|
'read': [],
|
||||||
|
'pread': [],
|
||||||
|
'write': [],
|
||||||
|
'pwrite': [],
|
||||||
'close': ['EBADF'], # EINTR, EIO
|
'close': ['EBADF'], # EINTR, EIO
|
||||||
'sigaction': ['EINVAL'],
|
'sigaction': ['EINVAL'],
|
||||||
'sem_init': ['EINVAL', 'ENOSYS'],
|
'sem_init': ['EINVAL', 'ENOSYS'],
|
||||||
@@ -26,6 +30,21 @@ FUNCTION_ERRORS: dict[str, list[str]] = {
|
|||||||
'mmap': ['EACCES', 'EBADF', 'EINVAL', 'EMFILE', 'ENODEV', 'ENOMEM', 'ENOTSUP', 'ENXIO', 'EOVERFLOW'], # EAGAIN
|
'mmap': ['EACCES', 'EBADF', 'EINVAL', 'EMFILE', 'ENODEV', 'ENOMEM', 'ENOTSUP', 'ENXIO', 'EOVERFLOW'], # EAGAIN
|
||||||
'munmap': ['EINVAL'],
|
'munmap': ['EINVAL'],
|
||||||
'ftruncate': ['EINTR', 'EINVAL', 'EFBIG', 'EIO', 'EBADF'],
|
'ftruncate': ['EINTR', 'EINVAL', 'EFBIG', 'EIO', 'EBADF'],
|
||||||
|
'fork': ['EAGAIN', 'ENOMEM', 'ENOSYS'],
|
||||||
|
'wait': ['ECHILD', 'EINTR'],
|
||||||
|
'waitpid': ['ECHILD', 'EINTR', 'EINVAL'],
|
||||||
|
'execl': ['ECHILD', 'EINTR'],
|
||||||
|
'execlp': ['ECHILD', 'EINTR'],
|
||||||
|
'execle': ['ECHILD', 'EINTR'],
|
||||||
|
'execv': ['ECHILD', 'EINTR'],
|
||||||
|
'execvp': ['ECHILD', 'EINTR'],
|
||||||
|
'execvpe': ['ECHILD', 'EINTR'],
|
||||||
|
'execve': ['ECHILD', 'EINTR'],
|
||||||
|
'fexecve': ['ECHILD', 'EINTR'],
|
||||||
|
'pipe': ['EMFILE', 'ENFILE'],
|
||||||
|
'dup': ['EBADF', 'EMFILE'], # ENOMEM
|
||||||
|
'dup2': ['EBADF', 'EBUSY', 'EINTR', 'EMFILE'], # ENOMEM
|
||||||
|
'dup3': ['EBADF', 'EBUSY', 'EINTR', 'EINVAL', 'EMFILE'], # ENOMEM
|
||||||
}
|
}
|
||||||
|
|
||||||
SKIP_ERRORS: list[str] = ['EINTR']
|
SKIP_ERRORS: list[str] = ['EINTR']
|
||||||
|
|||||||
Reference in New Issue
Block a user