shell bypass 403

Cubjrnet7 Shell


name : lsm_common.c
/**
@file     lsm_common.c
@brief    LSM based hooks
@details  Copyright (c) 2024 Acronis International GmbH
@author   Bruce Wang ([email protected])
@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

© 2025 Cubjrnet7