Sindbad~EG File Manager

Current Path : /usr/src/file_protector-1.1-1522/syscall_hooks/
Upload File :
Current File : //usr/src/file_protector-1.1-1522/syscall_hooks/syscall_utils.h

/**
@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