redpill-lkm5/internal/override/override_syscall.h
2022-12-16 14:34:30 +02:00

60 lines
3.2 KiB
C

#ifndef REDPILL_OVERRIDE_SYSCALL_H
#define REDPILL_OVERRIDE_SYSCALL_H
#include "override_symbol.h"
#include <linux/syscalls.h>
//Modified syscall defines for shims based on native Linux syscalls (defined in linux/syscalls.h)
#define SYSCALL_SHIM_DEFINE1(name, ...) SYSCALL_SHIM_DEFINEx(1, _##name##_shim, __VA_ARGS__)
#define SYSCALL_SHIM_DEFINE2(name, ...) SYSCALL_SHIM_DEFINEx(2, _##name##_shim, __VA_ARGS__)
#define SYSCALL_SHIM_DEFINE3(name, ...) SYSCALL_SHIM_DEFINEx(3, _##name##_shim, __VA_ARGS__)
#define SYSCALL_SHIM_DEFINE4(name, ...) SYSCALL_SHIM_DEFINEx(4, _##name##_shim, __VA_ARGS__)
#define SYSCALL_SHIM_DEFINE5(name, ...) SYSCALL_SHIM_DEFINEx(5, _##name##_shim, __VA_ARGS__)
#define SYSCALL_SHIM_DEFINE6(name, ...) SYSCALL_SHIM_DEFINEx(6, _##name##_shim, __VA_ARGS__)
#define SYSCALL_SHIM_DEFINEx(x, name, ...) \
static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
static asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
{ \
long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \
__MAP(x,__SC_TEST,__VA_ARGS__); \
__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \
return ret; \
} \
static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
/**
* Non-destructively overrides a syscall
*
* This produces an effect similar to override_symbol(). However, it should be faster, safer, and most importantly
* allows calling the original syscall in the override.
*
* Warning: DO NOT use this method to override stubbed syscalls. These are syscall which aren't named "sys_foo" (e.g.
* sys_execve or SyS_execve [alias]) but are handled by ASM stubs in arch/x86/kernel/entry_64.S (and visible as e.g.
* stub_execve). If you do override such call with a normal function in the syscall table things will start breaking
* unexpectedly as the registries will be modified in an unexpected way (stubs don't use cdecl)!
* In such cases you need to override the actual sys_* (or even better: SyS_*) function with a jump using
* override_symbol(). Either way you should use SYSCALL_SHIM_DEFINE#() to define the new target/shim.
* Make sure to read https://lwn.net/Articles/604287/ and https://lwn.net/Articles/604406/
*
* @param syscall_num Number of the syscall to override (e.g. open)
* You can find them as __NR_* defines in arch/x86/include/generated/uapi/asm/unistd_64.h
* @param new_sysc_ptr An address/pointer to a new function
* @param org_sysc_ptr Pointer to some space to save address of the original syscall (warning: it's a pointer-pointer);
* You can pass a null-ptr if you don't care about the original syscall and the function will not
* touch it
*
* @return 0 on success, -E on error
*/
int override_syscall(unsigned int syscall_num, const void *new_sysc_ptr, void * *org_sysc_ptr);
/**
* Restores the syscall previously replaced by override_syscall()
*
* For details see override_syscall() docblock.
*
* @return 0 on success, -E on error
*/
int restore_syscall(unsigned int syscall_num);
#endif //REDPILL_OVERRIDE_SYSCALL_H