opt
/
kaspersky
/
kav4fs
/
src
/
kernel
/
module.linux
➕ New
📤 Upload
✎ Editing:
operations.c
← Back
#include "module.h" #include "interceptor.h" #include <linux/sched.h> #include <linux/seq_file.h> int Process_trusted(struct task_struct *tsk); //---- mounts iterator ---- #define MOUNTS_FILENAME "/proc/mounts" struct file* mounts = NULL; const struct seq_operations* nsops = NULL; static atomic_t has_binfmt = ATOMIC_INIT(0); int use_binfmt = 1; int open_proc_mounts(void) { mounts = filp_open(MOUNTS_FILENAME, O_RDONLY, 0); if (!IS_ERR(mounts)) { struct seq_file* p = mounts ? mounts->private_data : NULL; const struct seq_operations* op = nsops = p ? p->op : NULL; mounts = (op && op->start && op->next && op->stop) ? mounts : ERR_PTR(-ENOSYS); } if (IS_ERR(mounts)) return PTR_ERR(mounts); return 0; } int drop_proc_mounts(void) { nsops = NULL; filp_close(mounts, NULL); mounts = NULL; return 0; } //---- exec handler ---- #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) static int binary_handler_exec(struct linux_binprm* bprm, struct pt_regs* regs) #else static int binary_handler_exec(struct linux_binprm* bprm) #endif { return kavoas_exec(bprm->file); } static int binary_handler_ulib(struct file* file) { return kavoas_ulib(file); } static struct linux_binfmt kavoas_binfmt = { .module = THIS_MODULE, .load_binary = binary_handler_exec, .load_shlib = binary_handler_ulib, }; int binary_handler_init(void) { /* * This call puts kavoas_binfmt on top of formats list. * Thus it should be called before all other binary loaders * and able to spoof binary parameters data before actual * loader take place. * * For more confidence module should periodically check * whether it's binfmt_operations are on top and has not * been supressed by newly loaded binary formats. But now * only need for binfmt is to spoof binaries for elf-loader. * Elf-loader is permanently in-kernel and therefore could * be get on top of formats. */ if (use_binfmt && !atomic_read(&has_binfmt)) atomic_xchg(&has_binfmt, insert_binfmt_(&kavoas_binfmt) == 0); return atomic_read(&has_binfmt); } int binary_handler_exit(void) { if (use_binfmt && atomic_read(&has_binfmt)) { remove_binfmt(&kavoas_binfmt); atomic_xchg(&has_binfmt, 0); } return 0; } //---- file operations ---- #ifndef LINUX_KERNEL26 #define real_parent p_pptr #elif defined(CONFIG_UTRACE) && defined(remove_parent) && defined(add_parent) #define real_parent parent #endif int Process_trusted(struct task_struct *tsk) { file_info f_info; if (0 != get_exec_info((struct task_struct __rcu*)tsk, &f_info)) { if (NULL == tsk->real_parent) return 0; if (0 != get_current_euid()) return 0; if (0 != get_exec_info(tsk->real_parent, &f_info)) return 0; } return Monitor_kernel_trusted_proc(current->pid, &f_info); } static int req_queue_add_notification_vfsmnt(enum FileNotifyType file_type, struct inode* dir, struct dentry* dentry, struct vfsmount* vfsmnt) { check_req_data_t* reqd; reqd = (check_req_data_t*)MEM_ALLOC(sizeof(*reqd)); if (!reqd) return -ENOMEM; fill_check_req_common_fields(reqd, NOTIFY_FILE, get_current_euid(), get_current_egid(), vfsmnt, dget_parent(dentry), dentry->d_name.name); reqd->file_op_type = file_type; reqd->dev = kdev_t_to_nr(dir->i_sb->s_dev); reqd->ino = dir->i_ino; check_req_queue_add(reqd); check_req_queue_put(reqd); return 0; } static void req_queue_add_notification(enum FileNotifyType file_type, struct inode* dir, struct dentry* dentry) { struct seq_file* m = mounts->private_data; loff_t pos = 0; void* p = NULL; BUG_ON(nsops == NULL); p = nsops->start(m, &pos); while (p && !IS_ERR(p)) { struct vfsmount* vfs = GET_VFSMNT(p); struct dentry* mnt_root = dentry; do { mnt_root = mnt_root->d_parent; if (mnt_root == vfs->mnt_root) { req_queue_add_notification_vfsmnt(file_type, dir, dentry, vfs); break; } } while (!IS_ROOT(mnt_root)); p = nsops->next(m, p, &pos); } nsops->stop(m, p); } static void fill_check_file_req_fields(check_req_data_t* reqd, u_int32_t pid, u_int8_t file_op_type, int32_t flags, struct inode* inode) { reqd->pid = pid; reqd->file_op_type = file_op_type; reqd->flags = flags; reqd->dev = kdev_t_to_nr(inode->i_sb->s_dev); reqd->ino = inode->i_ino; #ifndef LINUX_KERNEL26 reqd->mtime = inode->i_mtime; #else reqd->mtime = inode->i_mtime.tv_sec; #endif reqd->size = inode->i_size; reqd->owner_uid = i_uid_read(inode); reqd->file_mode = inode->i_mode; reqd->f_type = inode->i_sb->s_magic; } int kavoas_before_open(struct inode* inode, struct file* file) { file_info f_info; int err = 0; check_req_data_t* reqd; if (!atomic_read(&monitor_started) || Process_trusted(current) || !file_need_check(file->f_dentry)) return 0; if (file_unlinked(file->f_dentry)) return -ENOENT; if (!file->f_dentry->d_inode->i_size) return 0; reqd = (check_req_data_t*)MEM_ALLOC(sizeof(*reqd)); if (!reqd) return -ENOMEM; fill_file_info(file->f_dentry, &f_info); fill_check_req_common_fields( reqd, CHECK_FILE, get_current_euid(), get_current_egid(), file->f_vfsmnt, dget_parent(file->f_dentry), file->f_dentry->d_name.name); fill_check_file_req_fields(reqd, current->pid, FILE_OPEN_OPER, 0, file->f_dentry->d_inode); err = Monitor_kernel_check_file(&f_info, reqd, &err); check_req_queue_put(reqd); return err; } int kavoas_after_close(struct inode* inode, struct file* file) { file_info f_info; int err = 0; check_req_data_t* reqd; if (!KAVMON_IS_WRITTEN(file->f_flags) || !atomic_read(&file->f_dentry->d_inode->i_writecount)) return 0; if (!atomic_read(&monitor_started) || Process_trusted(current) || !file_need_check(file->f_dentry) || !file->f_dentry->d_inode->i_size) return 0; /* cifs file systems leaves dentry unhashed for newly created files during file * close */ if (file_unlinked(file->f_dentry) && strcmp(inode->i_sb->s_type->name, "cifs")) return 0; reqd = (check_req_data_t*)MEM_ALLOC(sizeof(*reqd)); if (!reqd) return -ENOMEM; fill_file_info(file->f_dentry, &f_info); fill_check_req_common_fields( reqd, CHECK_FILE, get_current_euid(), get_current_egid(), file->f_vfsmnt, dget_parent(file->f_dentry), file->f_dentry->d_name.name); fill_check_file_req_fields(reqd, current->pid, FILE_CLOSE_OPER, 0, file->f_dentry->d_inode); err = Monitor_kernel_check_file(&f_info, reqd, &err); check_req_queue_put(reqd); return err; } void kavoas_unlink(struct inode* dir, struct dentry* dentry) { struct inode* inode; if (!atomic_read(&monitor_started) || Process_trusted(current)) return; inode = (dentry->d_inode) ? dentry->d_inode : dir; if (inode_need_notify(inode)) { req_queue_add_notification(FILE_UNLINK_OPER, inode, dentry); Monitor_cache_del(kdev_t_to_nr(inode->i_sb->s_dev), inode->i_ino); } } void kavoas_rename(struct inode* old_dir, struct dentry* old_dentry, struct inode* new_dir, struct dentry* new_dentry) { struct inode *i_old, *i_new; if (!atomic_read(&monitor_started) || Process_trusted(current)) return; i_old = (old_dentry->d_inode) ? old_dentry->d_inode : old_dir; if (inode_need_notify(i_old)) { req_queue_add_notification(FILE_UNLINK_OPER, i_old, old_dentry); Monitor_cache_del(kdev_t_to_nr(i_old->i_sb->s_dev), i_old->i_ino); } i_new = (new_dentry->d_inode) ? new_dentry->d_inode : new_dir; if (inode_need_notify(i_new)) { req_queue_add_notification(FILE_RENAME_OPER, i_new, new_dentry); Monitor_cache_del(kdev_t_to_nr(i_new->i_sb->s_dev), i_new->i_ino); } }
💾 Save Changes
Cancel
📤 Upload File
×
Select File
Upload
Cancel
➕ Create New
×
Type
📄 File
📁 Folder
Name
Create
Cancel
✎ Rename Item
×
Current Name
New Name
Rename
Cancel
🔐 Change Permissions
×
Target File
Permission (e.g., 0755, 0644)
0755
0644
0777
Apply
Cancel