Linux server.thearyasamaj.org 4.18.0-553.56.1.el8_10.x86_64 #1 SMP Tue Jun 10 05:00:59 EDT 2025 x86_64
Apache
: 103.90.241.146 | : 216.73.216.222
Cant Read [ /etc/named.conf ]
5.6.40
ftpuser@mantra.thearyasamaj.org
www.github.com/MadExploits
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
CPANEL RESET
CREATE WP USER
README
+ Create Folder
+ Create File
/
usr /
src /
file_protector-1.1-1549 /
lsm_hooks /
[ HOME SHELL ]
Name
Size
Permission
Action
lsm_common.c
6.1
KB
-rw-r--r--
lsm_common.h
1.53
KB
-rw-r--r--
lsm_pre_events.c
27.48
KB
-rw-r--r--
Delete
Unzip
Zip
${this.title}
Close
Code Editor : lsm_pre_events.c
/** @file lsm_pre_events.c @brief LSM based hooks @details Copyright (c) 2024 Acronis International GmbH @author Bruce Wang (bruce.wang@acronis.com) @since $Id: $ */ #ifdef CONFIG_SECURITY #include <linux/list.h> #include <linux/mman.h> #include <linux/types.h> #include "compat.h" #include "file_handle_tools.h" #include "ftrace_hooks/fsnotify_listener.h" #include "ftrace_hooks/ftrace_events.h" #include "fs_event.h" #include "lsm_common.h" #include "memory.h" #include "path_tools.h" #include "si_templates.h" #include "si_writer_common.h" #include "subtype.h" #include "syscall_common.h" #include "task_info_map.h" #include "task_tools.h" #include "transport.h" #include "transport_protocol.h" #include "write_protection.h" static int _lsm_file_open(struct file *file) { long ret = 0; const struct path *path; task_info_t *task_info; transport_ids_t transport_ids; file_context_info_t file_context_info = {0}; const uint64_t generatedEventsMask = MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_SYNC_FILE_PRE_OPEN) | MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_NOTIFY_FILE_PRE_OPEN); uint8_t subtype_mask; uint64_t generatedEventsSubTypeMask = 0; if (!file) { return 0; } #ifdef FMODE_NONOTIFY if (file->f_mode & FMODE_NONOTIFY) return 0; #endif if (!HOOK_PROLOG()) { return 0; } path = &file->f_path; if (path->mnt && sb_ok(path->mnt->mnt_sb)) fsnotify_events_listen_sb(path->mnt->mnt_sb); if (!(transport_global_get_combined_mask() & (generatedEventsMask | MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_NOTIFY_PROCESS_EXEC))) || transport_is_control_tgid(current->tgid)) { goto out; } subtype_mask = open_flags_to_subtype_fmode(file->f_flags); if (subtype_mask & SUBTYPE_FMODE_WRITE) { generatedEventsSubTypeMask |= MSG_TYPE_TO_EVENT_MASK(FP_SI_ST_SYNC_OPEN_MODIFY) | MSG_TYPE_TO_EVENT_MASK(FP_SI_ST_NOTIFY_OPEN_MODIFY); } if (subtype_mask & SUBTYPE_FMODE_READ) { generatedEventsSubTypeMask |= MSG_TYPE_TO_EVENT_MASK(FP_SI_ST_SYNC_OPEN_READ) | MSG_TYPE_TO_EVENT_MASK(FP_SI_ST_NOTIFY_OPEN_READ); } if (file->f_flags & O_CREAT) { generatedEventsSubTypeMask |= MSG_TYPE_TO_EVENT_MASK(FP_SI_ST_SYNC_OPEN_MAY_CREATE) | MSG_TYPE_TO_EVENT_MASK(FP_SI_ST_NOTIFY_OPEN_MAY_CREATE); } if (!(transport_global_get_combined_subtype_mask() & generatedEventsSubTypeMask)) { goto out; } task_info = task_info_map_get(current); if (!task_info) { goto out; } transport_global_get_ids(&transport_ids); refresh_task(task_info, &transport_ids); if (!path_is_valid(path)) { DPRINTF("path is not valid"); goto err_exit; } if (make_file_context_info(&file_context_info, path, file->f_flags, 0, 0, READ_ONCE(task_info->pid_version)) && check_open_cache(&transport_ids, &file_context_info)) { goto err_exit; } if (!task_info_can_skip(task_info, &transport_ids, generatedEventsMask)) { long block = fs_event_pre_open(task_info, file->f_flags, path, &file_context_info.msg_info); // TODO: Why is block changed to EACCES? ret = block ? -EACCES : 0; DPRINTF("finished 'fs_event_pre_open(flags=0o%o/0x%x)", file->f_flags, file->f_flags); } err_exit: task_info_put(task_info); out: HOOK_EPILOG(); return ret; } #ifdef HAVE_FILE_OPEN #pragma message("HAVE_FILE_OPEN") #ifdef FILE_OPEN_WITH_CRED #pragma message("FILE_OPEN_WITH_CRED") static int lsm_file_open(struct file *file, const struct cred *cred) { (void) cred; return _lsm_file_open(file); } #else static int lsm_file_open(struct file *file) { return _lsm_file_open(file); } #endif #else static int lsm_dentry_open(struct file *file, const struct cred *cred) { (void) cred; return _lsm_file_open(file); } #endif #ifdef HAVE_MMAP_FILE static int lsm_mmap_file(struct file *file, unsigned long reqprot, unsigned long prot, unsigned long flags) { long ret = 0; const struct path *path; task_info_t *task_info; transport_ids_t transport_ids; const uint64_t generatedEventsMask = MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_SYNC_FILE_PRE_MMAP) | MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_NOTIFY_FILE_PRE_MMAP); bool writable = (flags & MAP_SHARED) && (prot & PROT_WRITE); const uint64_t generatedEventsSubTypeMask = writable ? MSG_TYPE_TO_EVENT_MASK(FP_SI_ST_SYNC_MMAP_WRITE) | MSG_TYPE_TO_EVENT_MASK(FP_SI_ST_NOTIFY_MMAP_WRITE) : MSG_TYPE_TO_EVENT_MASK(FP_SI_ST_SYNC_MMAP_NON_WRITE) | MSG_TYPE_TO_EVENT_MASK(FP_SI_ST_NOTIFY_MMAP_NON_WRITE); if (!file) { return 0; } #ifdef FMODE_NONOTIFY if (file->f_mode & FMODE_NONOTIFY) return 0; #endif if (!HOOK_PROLOG()) { return 0; } if (!(transport_global_get_combined_mask() & generatedEventsMask) || transport_is_control_tgid(current->tgid)) { goto out; } if (!(transport_global_get_combined_subtype_mask() & generatedEventsSubTypeMask)) { goto out; } task_info = task_info_map_get(current); if (!task_info) { goto out; } transport_global_get_ids(&transport_ids); refresh_task(task_info, &transport_ids); path = &file->f_path; if (!path_is_valid(path)) { DPRINTF("path is not valid"); goto err_exit; } if (!task_info_can_skip(task_info, &transport_ids, generatedEventsMask)) { long block = fs_event_pre_mmap(task_info, file->f_flags, path, reqprot, prot, flags); // TODO: Why is block changed to EACCES? ret = block ? -EACCES : 0; DPRINTF("finished 'fs_event_pre_mmap(flags=0o%o/0x%x)", file->f_flags, file->f_flags); } err_exit: task_info_put(task_info); out: HOOK_EPILOG(); return ret; } #endif #ifdef CONFIG_SECURITY_PATH static int _lsm_path_rename(const struct path *old_dir, struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry, unsigned int flags) { long ret = 0; struct path oldpath = (struct path){}; struct path newpath = (struct path){}; task_info_t *task_info; transport_ids_t transport_ids; bool new_path_is_valid = false; const uint64_t generatedEventsMask = MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_SYNC_FILE_PRE_RENAME) | MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_NOTIFY_FILE_PRE_RENAME); if (!old_dir || !old_dentry || !new_dir || !new_dentry) { return 0; } if (!HOOK_PROLOG()) { return 0; } if (!(transport_global_get_combined_mask() & generatedEventsMask) || transport_is_control_tgid(current->tgid)) { goto out; } task_info = task_info_map_get(current); if (!task_info) { goto out; } transport_global_get_ids(&transport_ids); refresh_task(task_info, &transport_ids); oldpath.mnt = old_dir->mnt; oldpath.dentry = old_dentry; if (!path_is_valid(&oldpath)) { DPRINTF("path is invalid"); goto err_exit; } // TODO: There should be a check for negative dentry newpath.mnt = new_dir->mnt; newpath.dentry = new_dentry; new_path_is_valid = path_is_valid(&newpath); fsnotify_events_listen_sb(oldpath.mnt->mnt_sb); DPRINTF("calling fs_event_pre_rename(flags=%u)", flags); if (!task_info_can_skip(task_info, &transport_ids, generatedEventsMask)) { long block = fs_event_pre_rename(task_info, flags, &oldpath, &newpath, new_path_is_valid); ret = block ? -EACCES : 0; } DPRINTF("finished 'fs_event_pre_rename(flags=%u)", flags); err_exit: task_info_put(task_info); out: HOOK_EPILOG(); return ret; } #ifdef RENAME_HAS_FLAGS static int lsm_path_rename(const struct path *old_dir, struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry, unsigned int flags) { return _lsm_path_rename(old_dir, old_dentry, new_dir, new_dentry, flags); } #else static int lsm_path_rename(const struct path *old_dir, struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry) { return _lsm_path_rename(old_dir, old_dentry, new_dir, new_dentry, 0); } #endif static int handle_unlink(const struct path *dir, struct dentry *dentry, int flag) { long ret = 0; struct path path = (struct path){}; task_info_t *task_info; transport_ids_t transport_ids; const uint64_t generatedEventsMask = MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_SYNC_FILE_PRE_UNLINK) | MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_NOTIFY_FILE_PRE_UNLINK); if (!dir || !dentry) { return 0; } if (!HOOK_PROLOG()) { return 0; } if (!(transport_global_get_combined_mask() & generatedEventsMask) || transport_is_control_tgid(current->tgid)) { goto out; } task_info = task_info_map_get(current); if (!task_info) { goto out; } transport_global_get_ids(&transport_ids); refresh_task(task_info, &transport_ids); path.mnt = dir->mnt; path.dentry = dentry; if (!path_is_valid(&path)) { DPRINTF("path is invalid"); goto err_exit; } fsnotify_events_listen_sb(path.mnt->mnt_sb); DPRINTF("calling fs_event_pre_unlink(flag=%d)", flag); if (!task_info_can_skip(task_info, &transport_ids, generatedEventsMask)) { long block = fs_event_pre_unlink(task_info, &path); ret = block ? -EACCES : 0; } DPRINTF("finished 'fs_event_pre_unlink(flag=%d)", flag); err_exit: task_info_put(task_info); out: HOOK_EPILOG(); return ret; } static int lsm_path_unlink(const struct path *dir, struct dentry *dentry) { return handle_unlink(dir, dentry, 0); } static int lsm_path_rmdir(const struct path *dir, struct dentry *dentry) { return handle_unlink(dir, dentry, AT_REMOVEDIR); } static int lsm_path_link(struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry) { long ret = 0; struct path oldpath = (struct path){}; struct path newpath = (struct path){}; task_info_t *task_info; transport_ids_t transport_ids; const uint64_t generatedEventsMask = MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_SYNC_FILE_PRE_LINK) | MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_NOTIFY_FILE_PRE_LINK); if (!old_dentry || !new_dir || !new_dentry) { return 0; } if (!HOOK_PROLOG()) { return 0; } if (!(transport_global_get_combined_mask() & generatedEventsMask) || transport_is_control_tgid(current->tgid)) { goto out; } task_info = task_info_map_get(current); if (!task_info) { goto out; } transport_global_get_ids(&transport_ids); refresh_task(task_info, &transport_ids); oldpath.mnt = new_dir->mnt; oldpath.dentry = old_dentry; if (!path_is_valid(&oldpath)) { DPRINTF("path is invalid"); goto err_exit; } newpath.mnt = new_dir->mnt; newpath.dentry = new_dentry; DPRINTF("calling fs_event_pre_link()"); if (!task_info_can_skip(task_info, &transport_ids, generatedEventsMask)) { long block = fs_event_pre_link(task_info, &oldpath, &newpath); ret = block ? -EACCES : 0; } DPRINTF("finished 'fs_event_pre_link()"); err_exit: task_info_put(task_info); out: HOOK_EPILOG(); return ret; } #endif #if defined(CONFIG_SECURITY_PATH) || defined(HAVE_FILE_TRUNCATE) static int lsm_path_truncate(const struct path *path) { long ret = 0; task_info_t *task_info; transport_ids_t transport_ids; const uint64_t generatedEventsMask = MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_SYNC_FILE_PRE_TRUNCATE) | MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_NOTIFY_FILE_PRE_TRUNCATE); if (!path) { return 0; } if (!HOOK_PROLOG()) { return 0; } if (!(transport_global_get_combined_mask() & generatedEventsMask) || transport_is_control_tgid(current->tgid)) { goto out; } task_info = task_info_map_get(current); if (!task_info) { goto out; } transport_global_get_ids(&transport_ids); refresh_task(task_info, &transport_ids); if (!path_is_valid(path)) { goto err_exit; } DPRINTF("calling fs_event_pre_truncate()"); if (!task_info_can_skip(task_info, &transport_ids, generatedEventsMask)) { long block = fs_event_pre_truncate(task_info, path); ret = block ? -EACCES : 0; } DPRINTF("finished 'fs_event_pre_truncate()"); err_exit: task_info_put(task_info); out: HOOK_EPILOG(); return ret; } #endif #ifdef HAVE_FILE_TRUNCATE static int lsm_file_truncate(struct file *file) { if (!file) return 0; #ifdef FMODE_NONOTIFY if (file->f_mode & FMODE_NONOTIFY) return 0; #endif return lsm_path_truncate(&file->f_path); } #endif static const uint8_t k_set_time_fields[] = { SI_COMMON_FIELDS, FP_SI_PI_SYSTEM_TIME_OLD_TIMESTAMP, FP_SI_PI_SYSTEM_TIME_NEW_TIMESTAMP }; static int lsm_settime(const TIMESPEC *ts, const struct timezone *tz) { transport_ids_t transport_ids; task_info_t *task_info; const uint64_t generatedEventsMask = MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_NOTIFY_SETTIME); (void) tz; if (!ts) { return 0; } if (!HOOK_PROLOG()) { return 0; } if (!(transport_global_get_combined_mask() & generatedEventsMask) || transport_is_control_tgid(current->tgid)) { goto out; } task_info = task_info_map_get(current); if (!task_info) { goto out; } transport_global_get_ids(&transport_ids); if (!task_info_can_skip(task_info, &transport_ids, generatedEventsMask)) { uint64_t unique_pid = make_unique_pid(current); uint64_t event_uid; uint32_t event_size; msg_t *msg = NULL; event_size = SI_ESTIMATE_SIZE_CONST_PARAMS(k_set_time_fields); msg = msg_new(FP_SI_OT_NOTIFY_SETTIME, 0, SI_CT_PRE_CALLBACK, unique_pid, event_size); if (!msg) goto err_exit; event_uid = transport_global_sequence_next(); { SiTimeMicroseconds us; si_property_writer_t writer; si_event_writer_init(&writer, &msg->event, event_size); si_property_writer_write_common(&writer, event_uid, current->pid, current->tgid, task_info); us.microseconds = ktime_to_us(ktime_get_real()); si_property_writer_write_system_time_old_timestamp(&writer, us); us.microseconds = ts->tv_sec * 1000000 + ts->tv_nsec / 1000; si_property_writer_write_system_time_new_timestamp(&writer, us); si_event_writer_finalize(&msg->event, &writer); } msg->task_info = task_info_get(task_info); msg->id = event_uid; send_msg_async_unref_unchecked(msg); } err_exit: task_info_put(task_info); out: HOOK_EPILOG(); return 0; } #ifdef HAVE_FSNOTIFY_PUBLIC_API static int lsm_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode) { (void) mode; if (!HOOK_PROLOG()) return 0; if (dir && sb_ok(dir->i_sb)) fsnotify_events_listen_sb(dir->i_sb); if (dentry && sb_ok(dentry->d_sb)) fsnotify_events_listen_sb(dentry->d_sb); HOOK_EPILOG(); return 0; } #endif #ifdef HAVE_SECURITY_HOOK_LIST #include <linux/lsm_hooks.h> #include <linux/rcupdate.h> typedef struct { struct security_hook_list file_open; struct security_hook_list mmap_file; struct security_hook_list settime; struct security_hook_list path_rename; struct security_hook_list path_unlink; struct security_hook_list path_rmdir; struct security_hook_list path_link; struct security_hook_list path_truncate; #ifdef HAVE_FILE_TRUNCATE struct security_hook_list file_truncate; #endif #ifdef HAVE_FSNOTIFY_PUBLIC_API struct security_hook_list inode_create; #endif } lsm_hook_list_t; static lsm_hook_list_t lsm_hook_list = { .file_open = { .hook.file_open = lsm_file_open, }, .mmap_file = { .hook.mmap_file = lsm_mmap_file, }, .settime = { .hook.settime = lsm_settime, }, #ifdef CONFIG_SECURITY_PATH .path_rename = { .hook.path_rename = lsm_path_rename, }, .path_unlink = { .hook.path_unlink = lsm_path_unlink, }, .path_rmdir = { .hook.path_rmdir = lsm_path_rmdir, }, .path_link = { .hook.path_link = lsm_path_link, }, .path_truncate = { .hook.path_truncate = lsm_path_truncate, }, #endif #ifdef HAVE_FILE_TRUNCATE .file_truncate = { .hook.file_truncate = lsm_file_truncate, }, #endif #ifdef HAVE_FSNOTIFY_PUBLIC_API .inode_create = { .hook.inode_create = lsm_inode_create, } #endif }; /* The original func to add lsm hooks, the lsm name and lsm_append() is not mandatory void __init security_add_hooks(struct security_hook_list *hooks, int count, const char *lsm) { int i; for (i = 0; i < count; i++) { hooks[i].lsm = lsm; hlist_add_tail_rcu(&hooks[i].list, hooks[i].head); } if (slab_is_available()) { if (lsm_append(lsm, &lsm_names) < 0) panic("%s - Cannot get early memory.\n", __func__); } } */ #ifdef HOOK_LIST_USE_HLIST #define add_hook_to_list_head(hook_list, security_hook_heads_addr, hook_name) \ hlist_add_tail_rcu(&hook_list.hook_name.list, &security_hook_heads_addr->hook_name); \ print_hooks(security_hook_heads_addr, hook_name); #define remove_hook(hook_list, hook_name) hlist_del_rcu(&hook_list.hook_name.list) #else #define add_hook_to_list_head(hook_list, security_hook_heads_addr, hook_name) \ list_add_tail_rcu(&hook_list.hook_name.list, &security_hook_heads_addr->hook_name); \ print_hooks(security_hook_heads_addr, hook_name); #define remove_hook(hook_list, hook_name) list_del_rcu(&hook_list.hook_name.list) #endif static int _register_lsm_pre_events(void) { struct security_hook_heads *security_hook_heads_addr = (struct security_hook_heads *)compat_kallsyms_lookup_name("security_hook_heads"); if (security_hook_heads_addr == NULL) { return -1; } print_address_symbol(security_hook_heads_addr); { unsigned long flags; local_irq_save(flags); { unsigned long cr0 = disable_write_protect(); if (ftrace_post_event_have(FTRACE_POST_EVENT_FSNOTIFY)) { add_hook_to_list_head(lsm_hook_list, security_hook_heads_addr, file_open); IPRINTF("LSM %s was planted!", "open"); } add_hook_to_list_head(lsm_hook_list, security_hook_heads_addr, mmap_file); IPRINTF("LSM %s was planted!", "mmap"); add_hook_to_list_head(lsm_hook_list, security_hook_heads_addr, settime); IPRINTF("LSM %s was planted!", "settime"); #ifdef CONFIG_SECURITY_PATH if (ftrace_post_event_have(FTRACE_POST_EVENT_FSNOTIFY)) { add_hook_to_list_head(lsm_hook_list, security_hook_heads_addr, path_rename); IPRINTF("LSM %s was planted!", "rename"); add_hook_to_list_head(lsm_hook_list, security_hook_heads_addr, path_unlink); IPRINTF("LSM %s was planted!", "unlink"); add_hook_to_list_head(lsm_hook_list, security_hook_heads_addr, path_rmdir); IPRINTF("LSM %s was planted!", "rmdir"); } add_hook_to_list_head(lsm_hook_list, security_hook_heads_addr, path_link); IPRINTF("LSM %s was planted!", "link"); add_hook_to_list_head(lsm_hook_list, security_hook_heads_addr, path_truncate); IPRINTF("LSM %s was planted!", "truncate"); #endif #ifdef HAVE_FILE_TRUNCATE add_hook_to_list_head(lsm_hook_list, security_hook_heads_addr, file_truncate); IPRINTF("LSM %s was planted!", "file_truncate"); #endif #ifdef HAVE_FSNOTIFY_PUBLIC_API add_hook_to_list_head(lsm_hook_list, security_hook_heads_addr, inode_create); IPRINTF("LSM %s was planted!", "inode_create"); #endif restore_write_protect(cr0); } local_irq_restore(flags); } return 0; } static void _unregister_lsm_pre_events(void) { unsigned long flags; local_irq_save(flags); { unsigned long cr0 = disable_write_protect(); if (ftrace_post_event_have(FTRACE_POST_EVENT_FSNOTIFY)) { remove_hook(lsm_hook_list, file_open); IPRINTF("LSM %s was removed!", "open"); } remove_hook(lsm_hook_list, mmap_file); IPRINTF("LSM %s was removed!", "mmap"); remove_hook(lsm_hook_list, settime); IPRINTF("LSM %s was removed!", "settime"); #ifdef CONFIG_SECURITY_PATH if (ftrace_post_event_have(FTRACE_POST_EVENT_FSNOTIFY)) { remove_hook(lsm_hook_list, path_rename); IPRINTF("LSM %s was removed!", "rename"); remove_hook(lsm_hook_list, path_unlink); IPRINTF("LSM %s was removed!", "unlink"); remove_hook(lsm_hook_list, path_rmdir); IPRINTF("LSM %s was removed!", "rmdir"); } remove_hook(lsm_hook_list, path_link); IPRINTF("LSM %s was removed!", "link"); remove_hook(lsm_hook_list, path_truncate); IPRINTF("LSM %s was removed!", "truncate"); #endif #ifdef HAVE_FILE_TRUNCATE remove_hook(lsm_hook_list, file_truncate); IPRINTF("LSM %s was removed!", "file_truncate"); #endif #ifdef HAVE_FSNOTIFY_PUBLIC_API remove_hook(lsm_hook_list, inode_create); IPRINTF("LSM %s was removed!", "inode_create"); #endif restore_write_protect(cr0); } local_irq_restore(flags); synchronize_rcu(); } #else #include <linux/security.h> static struct security_operations lsm_security_ops; struct security_operations **security_ops_addr; static struct security_operations * ori_security_ops; #include "hook_trampoline_common.h" #define LSM_HOOK_TRAMPOLINE(name) lsm_##name##_trampoline #define LSM_HOOK_NAME(name) lsm_##name##_enter #define HOOK_TRAMPOLINE(name, ...) HOOK_TRAMPOLINE_ASM(LSM_HOOK_TRAMPOLINE(name), LSM_HOOK_NAME(name)) \ int LSM_HOOK_TRAMPOLINE(name) (__VA_ARGS__); #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 SC_ARGS(t, a) a #define LSM_HOOK_ENTER(name, args_cnt, ...) \ hook_ret_t lsm_##name##_enter(MAP(args_cnt, SC_DECL, __VA_ARGS__)) \ { \ hook_ret_t ret; \ ret.ret = lsm_##name(MAP(args_cnt, SC_ARGS, __VA_ARGS__)); \ if (0 == ret.ret) \ ret.fn = (long) ori_security_ops->name; \ else \ ret.fn = 0; \ return ret; \ } \ HOOK_TRAMPOLINE(name, MAP(args_cnt, SC_DECL, __VA_ARGS__)) #ifdef HAVE_FILE_OPEN #ifdef FILE_OPEN_WITH_CRED LSM_HOOK_ENTER(file_open, 2, struct file *, file, const struct cred *, cred) #else LSM_HOOK_ENTER(file_open, 1, struct file *, file) #endif #else LSM_HOOK_ENTER(dentry_open, 2, struct file *, file, const struct cred *, cred) #endif #ifdef HAVE_MMAP_FILE LSM_HOOK_ENTER(mmap_file, 4, struct file *, file, unsigned long, reqprot, unsigned long, prot, unsigned long, flags) #endif #ifdef CONFIG_SECURITY_PATH LSM_HOOK_ENTER(path_rename, 4, const struct path *, old_dir, struct dentry *, old_dentry, const struct path *, new_dir, struct dentry *, new_dentry) LSM_HOOK_ENTER(path_unlink, 2, const struct path *, dir, struct dentry *, dentry) LSM_HOOK_ENTER(path_rmdir, 2, const struct path *, dir, struct dentry *, dentry) LSM_HOOK_ENTER(path_truncate, 1, const struct path *, path) LSM_HOOK_ENTER(path_link, 3, struct dentry *, old_dentry, const struct path *, new_dir, struct dentry *, new_dentry) #endif LSM_HOOK_ENTER(settime, 2, const TIMESPEC *, ts, const struct timezone *, tz) #ifdef HAVE_FSNOTIFY_PUBLIC_API LSM_HOOK_ENTER(inode_create, 3, struct inode *, dir, struct dentry *, dentry, umode_t, mode) #endif static void fixup_lsm_ops(struct security_operations *security_ops) { lsm_security_ops = *security_ops; // TODO: If we use LSM inotify_create, fsnotify restriction can be lifted if (ftrace_post_event_have(FTRACE_POST_EVENT_FSNOTIFY)) { #ifdef HAVE_FILE_OPEN lsm_security_ops.file_open = lsm_file_open_trampoline; #else lsm_security_ops.dentry_open = lsm_dentry_open_trampoline; #endif IPRINTF("LSM %s was planted!", "open"); } #ifdef HAVE_MMAP_FILE lsm_security_ops.mmap_file = lsm_mmap_file_trampoline; IPRINTF("LSM %s was planted!", "mmap"); #endif lsm_security_ops.settime = lsm_settime_trampoline; IPRINTF("LSM %s was planted!", "settime"); #ifdef CONFIG_SECURITY_PATH if (ftrace_post_event_have(FTRACE_POST_EVENT_FSNOTIFY)) { lsm_security_ops.path_rename = lsm_path_rename_trampoline; IPRINTF("LSM %s was planted!", "rename"); lsm_security_ops.path_unlink = lsm_path_unlink_trampoline; IPRINTF("LSM %s was planted!", "unlink"); lsm_security_ops.path_rmdir = lsm_path_rmdir_trampoline; IPRINTF("LSM %s was planted!", "rmdir"); } lsm_security_ops.path_truncate = lsm_path_truncate_trampoline; IPRINTF("LSM %s was planted!", "truncate"); lsm_security_ops.path_link = lsm_path_link_trampoline; IPRINTF("LSM %s was planted!", "link"); #endif #ifdef HAVE_FSNOTIFY_PUBLIC_API lsm_security_ops.inode_create = lsm_inode_create_trampoline; IPRINTF("LSM %s was planted!", "inode_create"); #endif } static int _register_lsm_pre_events(void) { security_ops_addr = (struct security_operations **)compat_kallsyms_lookup_name("security_ops"); ori_security_ops = *security_ops_addr; if (security_ops_addr == NULL || ori_security_ops == NULL) { EPRINTF("%p %p", security_ops_addr, ori_security_ops); return -1; } print_address_symbol(security_ops_addr); print_address_symbol(ori_security_ops); fixup_lsm_ops(*security_ops_addr); { unsigned long flags; local_irq_save(flags); { unsigned long cr0 = disable_write_protect(); *security_ops_addr = &lsm_security_ops; restore_write_protect(cr0); } local_irq_restore(flags); } return 0; } static void _unregister_lsm_pre_events(void) { if (security_ops_addr == NULL || ori_security_ops == NULL) { EPRINTF("%p %p", security_ops_addr, ori_security_ops); return; } { unsigned long flags; local_irq_save(flags); { unsigned long cr0 = disable_write_protect(); *security_ops_addr = ori_security_ops; restore_write_protect(cr0); } local_irq_restore(flags); } IPRINTF("LSM was unregistered"); } #endif int register_lsm_pre_events(void) { if (_register_lsm_pre_events() == 0) { return 0; } return -1; } void unregister_lsm_pre_events(void) { _unregister_lsm_pre_events(); } #else int register_lsm_pre_events(void) { return -1; } void unregister_lsm_pre_events(void) { } #endif
Close