Sindbad~EG File Manager
/**
@file
@brief syscall utils
@details Copyright (c) 2022 Acronis International GmbH
@author Mikhail Krivtsov (mikhail.krivtsov@acronis.com)
@since $Id: $
*/
#pragma once
#include <linux/syscalls.h>
// Syscall hook may either decide to call to the original function 'fn' or return value 'ret'.
// If 'fn' is not NULL, syscall hook trampoline will jump to this function.
// If 'fn' is NULL, syscall hook trampoline will return 'ret'.
typedef struct {
long fn;
long ret;
} syscall_hook_ret_t;
#define MAP0(m,...)
#define MAP1(m,t,a,...) m(t,a)
#define MAP2(m,t,a,...) m(t,a), MAP1(m,__VA_ARGS__)
#define MAP3(m,t,a,...) m(t,a), MAP2(m,__VA_ARGS__)
#define MAP4(m,t,a,...) m(t,a), MAP3(m,__VA_ARGS__)
#define MAP5(m,t,a,...) m(t,a), MAP4(m,__VA_ARGS__)
#define MAP6(m,t,a,...) m(t,a), MAP5(m,__VA_ARGS__)
#define MAP7(m,t,a,...) m(t,a), MAP6(m,__VA_ARGS__)
#define MAP8(m,t,a,...) m(t,a), MAP7(m,__VA_ARGS__)
#define MAP9(m,t,a,...) m(t,a), MAP8(m,__VA_ARGS__)
#define MAP10(m,t,a,...) m(t,a), MAP9(m,__VA_ARGS__)
#define MAP11(m,t,a,...) m(t,a), MAP10(m,__VA_ARGS__)
#define MAP(n,...) MAP##n(__VA_ARGS__)
#define SC_DECL(t, a) t a
#define TYPE_AS(t, v) __same_type((__force t)0, v)
#define TYPE_IS_L(t) (TYPE_AS(t, 0L))
#define TYPE_IS_UL(t) (TYPE_AS(t, 0UL))
#define TYPE_IS_LL(t) (TYPE_AS(t, 0LL) || TYPE_AS(t, 0ULL))
#define SC_LONG(t, a) __typeof(__builtin_choose_expr(TYPE_IS_LL(t), 0LL, 0L)) a
#define SC_CAST(t, a) (__force t) a
#define SC_ARGS(t, a) a
#define SC_DELOUSE(t,v) ((__force t)(unsigned long)(v))
#define SYSCALL_HOOK_ID(abi, tag) abi##_##tag##_hook_id
#define COMPAT_SYSCALL_HOOK_ID SYSCALL_HOOK_ID
#define SYSCALL_HOOK_TRAMPOLINE(abi, tag) abi##_##tag##_trampoline
#define SYSCALL_HOOK_NAME(abi, tag) abi##_##tag##_hook
#define COMPAT_SYSCALL_HOOK_NAME SYSCALL_HOOK_NAME
#define SYSCALL_HOOK_TYPE_NAME(abi, tag) abi##_##tag##_hook_func_t
#define SYSCALL_ORIG_TYPE_NAME(abi, tag) abi##_##tag##_orig_func_t
#if defined CONFIG_ARCH_HAS_SYSCALL_WRAPPER
#define SYSCALL_HOOK_IMPL_NAME(abi, tag) \
sc_##abi##_##tag##_hook_impl
#define COMPAT_SYSCALL_HOOK_IMPL_NAME SYSCALL_HOOK_IMPL_NAME
#define SYSCALL_HOOK_SE_NAME(abi, tag) \
sc_##abi##_##tag##_hook_se
#define COMPAT_SYSCALL_HOOK_SE_NAME SYSCALL_HOOK_SE_NAME
/* Mapping of registers to parameters for syscalls on x86-64 and x32 */
// #define SC_X86_64_REGS_TO_ARGS(x, ...)
#define SC_sys_REGS_TO_ARGS SC_X86_64_REGS_TO_ARGS
/* Mapping of registers to parameters for syscalls on i386 */
// #define SC_IA32_REGS_TO_ARGS(x, ...)
#define SC_ia32_sys_REGS_TO_ARGS SC_IA32_REGS_TO_ARGS
#define SC_compat_sys_REGS_TO_ARGS SC_IA32_REGS_TO_ARGS
#define DEFINE_SYSCALL_HOOK_TYPE(abi, tag, args_cnt, ...) \
typedef asmlinkage syscall_hook_ret_t (*SYSCALL_HOOK_TYPE_NAME(abi, tag))(const struct pt_regs *regs)
#define DEFINE_SYSCALL_ORIG_TYPE(abi, tag, args_cnt, ...) \
typedef asmlinkage long (*SYSCALL_ORIG_TYPE_NAME(abi, tag))(const struct pt_regs *regs)
#define DECLARE_SYSCALL_HOOK(abi, tag, args_cnt, ...) \
asmlinkage syscall_hook_ret_t SYSCALL_HOOK_NAME(abi, tag)(const struct pt_regs *regs)
#define DEFINE_SYSCALL_HOOK(abi, tag, args_cnt, ...) \
static inline \
asmlinkage syscall_hook_ret_t SYSCALL_HOOK_SE_NAME(abi, tag)(const struct pt_regs *regs, MAP(args_cnt, SC_LONG,__VA_ARGS__)); \
\
asmlinkage syscall_hook_ret_t SYSCALL_HOOK_NAME(abi, tag)(const struct pt_regs *regs) \
{ \
return SYSCALL_HOOK_SE_NAME(abi, tag)(regs, SC_##abi##_REGS_TO_ARGS(args_cnt, SYSCALL_ARG)); \
} \
\
static inline \
asmlinkage syscall_hook_ret_t SYSCALL_HOOK_IMPL_NAME(abi, tag)(const struct pt_regs *regs, MAP(args_cnt, SC_DECL, __VA_ARGS__)); \
\
static inline \
asmlinkage syscall_hook_ret_t SYSCALL_HOOK_SE_NAME(abi, tag)(const struct pt_regs *regs, MAP(args_cnt, SC_LONG,__VA_ARGS__)) \
{ \
return SYSCALL_HOOK_IMPL_NAME(abi, tag)(regs, MAP(args_cnt, SC_CAST,__VA_ARGS__)); \
} \
static inline \
asmlinkage syscall_hook_ret_t SYSCALL_HOOK_IMPL_NAME(abi, tag)(const struct pt_regs *regs, MAP(args_cnt, SC_DECL, __VA_ARGS__))
#define DECLARE_COMPAT_SYSCALL_HOOK(abi, tag, args_cnt, ...) \
asmlinkage syscall_hook_ret_t COMPAT_SYSCALL_HOOK_NAME(abi, tag)(const struct pt_regs *regs)
#define DEFINE_COMPAT_SYSCALL_HOOK(abi, tag, args_cnt, ...) \
static inline \
asmlinkage syscall_hook_ret_t COMPAT_SYSCALL_HOOK_SE_NAME(abi, tag)(const struct pt_regs *regs, MAP(args_cnt, SC_LONG,__VA_ARGS__)); \
\
asmlinkage syscall_hook_ret_t COMPAT_SYSCALL_HOOK_NAME(abi, tag)(const struct pt_regs *regs) \
{ \
return COMPAT_SYSCALL_HOOK_SE_NAME(abi, tag)(regs, SC_##abi##_REGS_TO_ARGS(args_cnt, SYSCALL_ARG)); \
} \
\
static inline \
asmlinkage syscall_hook_ret_t COMPAT_SYSCALL_HOOK_IMPL_NAME(abi, tag)(const struct pt_regs *regs, MAP(args_cnt, SC_DECL, __VA_ARGS__)); \
\
static inline \
asmlinkage syscall_hook_ret_t COMPAT_SYSCALL_HOOK_SE_NAME(abi, tag)(const struct pt_regs *regs, MAP(args_cnt, SC_LONG,__VA_ARGS__)) \
{ \
return COMPAT_SYSCALL_HOOK_IMPL_NAME(abi, tag)(regs, MAP(args_cnt, SC_DELOUSE,__VA_ARGS__)); \
} \
static inline \
asmlinkage syscall_hook_ret_t COMPAT_SYSCALL_HOOK_IMPL_NAME(abi, tag)(const struct pt_regs *regs, MAP(args_cnt, SC_DECL, __VA_ARGS__))
#else
#define DEFINE_SYSCALL_HOOK_TYPE(abi, tag, args_cnt, ...) \
typedef asmlinkage syscall_hook_ret_t (*SYSCALL_HOOK_TYPE_NAME(abi, tag))(MAP(args_cnt, SC_DECL, __VA_ARGS__))
#define DEFINE_SYSCALL_ORIG_TYPE(abi, tag, args_cnt, ...) \
typedef asmlinkage long (*SYSCALL_ORIG_TYPE_NAME(abi, tag))(MAP(args_cnt, SC_DECL, __VA_ARGS__))
#define DECLARE_SYSCALL_HOOK(abi, tag, args_cnt, ...) \
asmlinkage syscall_hook_ret_t SYSCALL_HOOK_NAME(abi, tag)(MAP(args_cnt, SC_DECL, __VA_ARGS__))
#define DEFINE_SYSCALL_HOOK DECLARE_SYSCALL_HOOK
#define DEFINE_COMPAT_SYSCALL_HOOK DEFINE_SYSCALL_HOOK
#define DECLARE_COMPAT_SYSCALL_HOOK DECLARE_SYSCALL_HOOK
#endif
#define DEFINE_COMPAT_SYSCALL_HOOK_TYPE DEFINE_SYSCALL_HOOK_TYPE
#define DEFINE_COMPAT_SYSCALL_ORIG_TYPE DEFINE_SYSCALL_ORIG_TYPE
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#if 0
For example, the following:
DEFINE_SYSCALL_HOOK(sys, creat, 2, const char __user *, pathname, umode_t, mode)
{
...
}
will expand into:
static inline __attribute__((unused)) __attribute__((no_instrument_function))
syscall_hook_ret_t sc_sys_creat_hook_se(
const struct pt_regs *regs,
typeof(0LL) pathname,
typeof(0L) mode);
syscall_hook_ret_t sys_creat_hook(const struct pt_regs *regs)
{
return sc_sys_creat_hook_se(regs, regs->di, regs->si);
}
static inline __attribute__((unused)) __attribute__((no_instrument_function))
syscall_hook_ret_t sc_sys_creat_hook_impl(const struct pt_regs *regs, const char * pathname, umode_t mode);
static inline __attribute__((unused)) __attribute__((no_instrument_function))
syscall_hook_ret_t sc_sys_creat_hook_se(
const struct pt_regs *regs,
typeof(0LL) pathname,
typeof(0L) mode)
{
return sc_sys_creat_hook_impl(regs, ( const char *) pathname, ( umode_t) mode);
}
static inline __attribute__((unused)) __attribute__((no_instrument_function))
syscall_hook_ret_t sc_sys_creat_hook_impl(const struct pt_regs *regs, const char * pathname, umode_t mode)
{
...
}
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#if defined CONFIG_ARCH_HAS_SYSCALL_WRAPPER
#define DEFINE_CALL_ORIGINAL_SYSCALL_HANDLER(tag, args_cnt, ...) \
static \
inline \
long call_original_sc_##tag##_handler( \
const enum tag##_hook_type hook_type, \
const struct pt_regs *regs \
)
#else
#define DEFINE_CALL_ORIGINAL_SYSCALL_HANDLER(tag, args_cnt, ...) \
static \
inline \
long call_original_sc_##tag##_handler( \
const enum tag##_hook_type hook_type, \
MAP(args_cnt, SC_DECL, __VA_ARGS__) \
)
#endif
#define DEFINE_GET_ORIGINAL_SYSCALL_HANDLER(tag) \
static \
inline \
long get_original_sc_##tag##_handler( \
const enum tag##_hook_type hook_type \
)
#if defined CONFIG_ARCH_HAS_SYSCALL_WRAPPER
#define CALL_ORIGINAL_SYSCALL_HANDLER_PTR(original_syscall_ptr, ...) \
original_syscall_ptr(regs)
#else
#define CALL_ORIGINAL_SYSCALL_HANDLER_PTR(original_syscall_ptr, ...) \
original_syscall_ptr(__VA_ARGS__)
#endif
#define SET_ORIGINAL_SYSCALL_HANDLER(tag, hook_type) \
do{ syscall_hook_ret.fn = get_original_sc_##tag##_handler(hook_type); syscall_hook_ret.ret = 0; }while(0)
#define SET_HOOK_RETURN(err) do{ syscall_hook_ret.fn = 0; syscall_hook_ret.ret = err; }while(0)
#if defined CONFIG_ARCH_HAS_SYSCALL_WRAPPER
#define CALL_ORIGINAL_SYSCALL_HANDLER(tag, hook_type, ...) \
do{ ret = call_original_sc_##tag##_handler( \
hook_type, \
regs \
); SET_HOOK_RETURN(ret); }while(0)
#else
#define CALL_ORIGINAL_SYSCALL_HANDLER(tag, hook_type, ...) \
do{ ret = call_original_sc_##tag##_handler( \
hook_type, \
__VA_ARGS__ \
); SET_HOOK_RETURN(ret); }while(0)
#endif
#if defined CONFIG_ARCH_HAS_SYSCALL_WRAPPER
#define DEFINE_SYSCALL_HANDLER(tag, args_cnt, ...) \
static \
inline \
syscall_hook_ret_t sc_##tag##_handler( \
const struct pt_regs *regs, \
const enum tag##_hook_type hook_type, \
MAP(args_cnt, SC_DECL, __VA_ARGS__) \
)
#else
#define DEFINE_SYSCALL_HANDLER(tag, args_cnt, ...) \
static \
inline \
syscall_hook_ret_t sc_##tag##_handler( \
const enum tag##_hook_type hook_type, \
MAP(args_cnt, SC_DECL, __VA_ARGS__) \
)
#endif
#if defined CONFIG_ARCH_HAS_SYSCALL_WRAPPER
#define CALL_SYSCALL_HANDLER(tag, hook_type, ...) \
sc_##tag##_handler( \
regs, \
hook_type, \
__VA_ARGS__ \
)
#else
#define CALL_SYSCALL_HANDLER(tag, hook_type, ...) \
sc_##tag##_handler( \
hook_type, \
__VA_ARGS__ \
)
#endif
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists