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
Choose File :

Url:
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