PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
| Dir : /usr/src/file_protector-1.1-1584/lsm_hooks/ |
| Server: Linux ituca148.hostpapavps.net 4.18.0-553.141.2.el8_10.x86_64 #1 SMP Wed Jul 8 10:28:18 EDT 2026 x86_64 IP: 216.7.89.187 |
| Dir : //usr/src/file_protector-1.1-1584/lsm_hooks/lsm_common.c |
/**
@file lsm_common.c
@brief LSM based hooks
@details Copyright (c) 2024 Acronis International GmbH
@author Bruce Wang (bruce.wang@acronis.com)
@since $Id: $
*/
#include "debug.h"
#include "ftrace_hooks/ftrace_events.h"
#include "lsm_common.h"
#include "syscall_common.h"
#include "transport_protocol.h"
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0)
#include <asm/ia32_unistd.h> // for ia32_sys_call_table '__NR_ia32_*' system call function indices
#endif
#include <linux/fsnotify.h>
#ifdef KERNEL_MOCK
#include <stdlib.h>
#endif
static bool lsm_available(void)
{
#ifndef CONFIG_SECURITY
return false;
#endif
#ifdef KERNEL_MOCK
if (getenv("KERNEL_MOCK_BLOCK_LSM"))
return false;
#endif
return true;
}
static bool security_path_available(void)
{
#ifdef KERNEL_MOCK
if (getenv("KERNEL_MOCK_BLOCK_LSM_PATH"))
return false;
#endif
#ifdef CONFIG_SECURITY_PATH
return true;
#else
return false;
#endif
}
static bool g_lsm_hooks_registered = false;
int lsm_hooks_init(void)
{
if (lsm_available())
{
if (register_lsm_pre_events())
{
return -1;
}
else
{
g_lsm_hooks_registered = true;
}
}
else
{
WPRINTF("lsm is not available");
}
IPRINTF("");
return 0;
}
void lsm_hooks_exit(void)
{
if (lsm_available() && g_lsm_hooks_registered)
{
unregister_lsm_pre_events();
g_lsm_hooks_registered = false;
IPRINTF("");
}
}
bool lsm_registered(void)
{
return g_lsm_hooks_registered;
}
bool lsm_has_open(void)
{
return lsm_registered() && ftrace_post_event_have(FTRACE_POST_EVENT_FSNOTIFY);
}
bool lsm_has_security_path(void)
{
return lsm_registered() && security_path_available();
}
bool lsm_has_complex_post(void)
{
return lsm_registered() && security_path_available() && ftrace_post_event_have(FTRACE_POST_EVENT_FSNOTIFY);
}
uint64_t wanted_fsnotify_events(void)
{
uint64_t common_flags = FS_DELETE_SELF | FS_DELETE | FS_OPEN | FS_MODIFY;
if (!g_lsm_hooks_registered)
{
return common_flags;
}
if (lsm_has_complex_post())
{
return FS_CREATE | FS_MOVE_SELF | common_flags;
}
else
{
return FS_CREATE | common_flags;
}
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0)
#define SYS_CALL_NR(syscall) __NR_##syscall
#define IA32_SYS_CALL_NR(syscall) __NR_ia32_##syscall
static const int k_syscalls_fs_replaced[] = {
SYS_CALL_NR(open),
SYS_CALL_NR(openat),
SYS_CALL_NR(creat),
SYS_CALL_NR(close),
};
static const int k_syscalls_fs_ia32_replaced[] = {
IA32_SYS_CALL_NR(open),
IA32_SYS_CALL_NR(openat),
IA32_SYS_CALL_NR(creat),
IA32_SYS_CALL_NR(close),
};
#ifdef CONFIG_SECURITY_PATH
static const int k_syscalls_fs_path_replaced[] = {
SYS_CALL_NR(rename),
SYS_CALL_NR(renameat),
SYS_CALL_NR(renameat2),
SYS_CALL_NR(unlink),
SYS_CALL_NR(unlinkat),
};
static const int k_syscalls_fs_path_ia32_replaced[] = {
IA32_SYS_CALL_NR(rename),
IA32_SYS_CALL_NR(renameat),
IA32_SYS_CALL_NR(renameat2),
IA32_SYS_CALL_NR(unlink),
IA32_SYS_CALL_NR(unlinkat),
};
#endif
static const int k_syscalls_rw_replaced[] = {
SYS_CALL_NR(read),
SYS_CALL_NR(pread64),
SYS_CALL_NR(readv),
SYS_CALL_NR(preadv),
SYS_CALL_NR(preadv2),
SYS_CALL_NR(write),
SYS_CALL_NR(pwrite64),
SYS_CALL_NR(writev),
SYS_CALL_NR(pwritev),
SYS_CALL_NR(pwritev2),
};
static const int k_syscalls_ia32_rw_replaced[] = {
IA32_SYS_CALL_NR(read),
IA32_SYS_CALL_NR(pread64),
IA32_SYS_CALL_NR(readv),
IA32_SYS_CALL_NR(preadv),
IA32_SYS_CALL_NR(preadv2),
IA32_SYS_CALL_NR(write),
IA32_SYS_CALL_NR(pwrite64),
IA32_SYS_CALL_NR(writev),
IA32_SYS_CALL_NR(pwritev),
IA32_SYS_CALL_NR(pwritev2),
};
static bool syscall_listed_in(const int *syscalls, size_t size, int syscall_nr)
{
size_t i;
for (i = 0; i < size; i++)
{
if (syscalls[i] == syscall_nr)
{
return true;
}
}
return false;
}
bool syscall_replaced_by_lsm(int syscall_nr, bool ia32)
{
{
bool fs_syscall;
if (ia32)
{
fs_syscall = syscall_listed_in(k_syscalls_fs_ia32_replaced, ARRAY_SIZE(k_syscalls_fs_ia32_replaced), syscall_nr);
}
else
{
fs_syscall = syscall_listed_in(k_syscalls_fs_replaced, ARRAY_SIZE(k_syscalls_fs_replaced), syscall_nr);
}
if (fs_syscall)
{
// fs syscalls are replaced by LSM hooks + fsnotify
if (!g_lsm_hooks_registered)
{
return false;
}
if (!ftrace_post_event_have(FTRACE_POST_EVENT_FSNOTIFY))
{
return false;
}
return true;
}
}
#ifdef CONFIG_SECURITY_PATH
if (lsm_has_security_path())
{
bool fs_path_syscall;
if (ia32)
{
fs_path_syscall = syscall_listed_in(k_syscalls_fs_path_ia32_replaced, ARRAY_SIZE(k_syscalls_fs_path_ia32_replaced), syscall_nr);
}
else
{
fs_path_syscall = syscall_listed_in(k_syscalls_fs_path_replaced, ARRAY_SIZE(k_syscalls_fs_path_replaced), syscall_nr);
}
if (fs_path_syscall)
{
// fs syscalls are replaced by LSM hooks + fsnotify
if (!g_lsm_hooks_registered)
{
return false;
}
if (!ftrace_post_event_have(FTRACE_POST_EVENT_FSNOTIFY))
{
return false;
}
return true;
}
}
#endif
{
bool rw_syscall;
if (ia32)
{
rw_syscall = syscall_listed_in(k_syscalls_ia32_rw_replaced, ARRAY_SIZE(k_syscalls_ia32_rw_replaced), syscall_nr);
}
else
{
rw_syscall = syscall_listed_in(k_syscalls_rw_replaced, ARRAY_SIZE(k_syscalls_rw_replaced), syscall_nr);
}
if (rw_syscall)
{
// rw syscall hooks are replaced by rw_verify_area (and maybe clone hooks in the future)
if (!ftrace_post_event_have(FTRACE_PRE_EVENT_RW_VERIFY_AREA))
{
return false;
}
return true;
}
}
// Unknown syscall, assuming not replaced
return false;
}
#endif