Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

driver v1.7.0.22 released #718

Merged
merged 3 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions driver/LKM/include/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ int execve_argv_check(char *data, int len);

size_t filter_process_allowlist(const __user char *buff, size_t len);

/* opened-instances tracing for trace proc entry and filter device */
void filter_show_instances(void);
void trace_show_instances(void);

#endif /* FILTER_H */
132 changes: 99 additions & 33 deletions driver/LKM/src/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/rbtree.h>
#include <linux/namei.h>
#include <linux/utsname.h>

#include "../include/util.h"
#include "../include/filter.h"
Expand All @@ -30,14 +31,16 @@
#define DEL_EXECVE_ARGV_ALLOWLIST 74 /* J */
#define DEL_ALL_EXECVE_ARGV_ALLOWLIST 117 /* u */
#define EXECVE_ARGV_CHECK 122 /* z */
#define OPEN_INSTANCES_LIST_ALL 79 /* O */
#define OPEN_INSTANCES_LIST_TRACE 116 /* t */
#define OPEN_INSTANCES_LIST_FILTER 102 /* f */

#define ALLOWLIST_NODE_MIN 5
#define ALLOWLIST_NODE_MAX 4090
#define ALLOWLIST_LIMIT 128

static struct class *filter_class;
static int filter_major;
static char *sh_mem = NULL;

static struct rb_root execve_exe_allowlist = RB_ROOT;
static struct rb_root execve_argv_allowlist = RB_ROOT;
Expand All @@ -49,17 +52,6 @@ static int execve_argv_allowlist_limit = 0;
static DEFINE_RWLOCK(exe_allowlist_lock);
static DEFINE_RWLOCK(argv_allowlist_lock);

static int device_mmap(struct file *filp, struct vm_area_struct *vma);

static ssize_t device_write(struct file *filp, const __user char *buff,
size_t len, loff_t * off);

static const struct file_operations mchar_fops = {
.owner = THIS_MODULE,
.mmap = device_mmap,
.write = device_write,
};

struct allowlist_node {
struct rb_node node;
char *data;
Expand Down Expand Up @@ -347,11 +339,24 @@ size_t filter_process_allowlist(const __user char *buff, size_t len)
{
char *data_main;
int res;
char flag;
char flag = 0;

if (smith_get_user(flag, buff))
return len;

/* diagnosis cases: enmerate opened instances */
if (flag == OPEN_INSTANCES_LIST_ALL) {
trace_show_instances();
filter_show_instances();
return len;
} else if (flag == OPEN_INSTANCES_LIST_FILTER) {
filter_show_instances();
return len;
} else if (flag == OPEN_INSTANCES_LIST_TRACE) {
trace_show_instances();
return len;
}

/* check whether length is valid */
if (len < ALLOWLIST_NODE_MIN || len > ALLOWLIST_NODE_MAX)
return len;
Expand Down Expand Up @@ -436,28 +441,93 @@ static ssize_t device_write(struct file *filp, const __user char *buff,
return filter_process_allowlist(buff, len);
}

static int device_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct page *page;
unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start);
struct filter_instance {
struct list_head next;
char comm[TASK_COMM_LEN];
char node[__NEW_UTS_LEN];
pid_t owner;
};

if ((vma_pages(vma) + vma->vm_pgoff) > (SHMEM_MAX_SIZE >> PAGE_SHIFT)) {
return -EINVAL;
static LIST_HEAD(filter_list);
static struct mutex filter_lock;
static int filter_n_instances;

void filter_show_instances(void)
{
struct filter_instance *iter;
int niters = 0;

mutex_lock(&filter_lock);
printk("filter device opened %d times:\n", filter_n_instances);
list_for_each_entry(iter, &filter_list, next) {
niters++;
printk("%6d: %u %16s %s\n", niters, iter->owner, iter->comm, iter->node);
}
if (niters != filter_n_instances)
printk("inconsistent values: %d %d\n", niters, filter_n_instances);
mutex_unlock(&filter_lock);
}

/* handling device open */
static int device_open(struct inode *inode, struct file *filp)
{
struct filter_instance *iter;

iter = kzalloc(sizeof(*iter), GFP_KERNEL);
if (!iter)
return -ENOMEM;

page = virt_to_page((unsigned long)sh_mem + (vma->vm_pgoff << PAGE_SHIFT));
/* tracing current task for this opened instance */
iter->owner = current->pid;
memcpy(iter->comm, current->comm, TASK_COMM_LEN);
memcpy(iter->node, current->nsproxy->uts_ns->name.nodename, __NEW_UTS_LEN),

return remap_pfn_range(vma, vma->vm_start, page_to_pfn(page), size,
vma->vm_page_prot);
mutex_lock(&filter_lock);
filter_n_instances++;
list_add_tail(&iter->next, &filter_list);
mutex_unlock(&filter_lock);

filp->private_data = iter;
nonseekable_open(inode, filp);
__module_get(THIS_MODULE);

return 0;
}

/* handling deivce close */
static int device_release(struct inode *inode, struct file *filp)
{
struct filter_instance *iter = filp->private_data;

if (!iter)
return 0;

/* removing iter from trace_list */
mutex_lock(&filter_lock);
list_del(&iter->next);
filter_n_instances--;
mutex_unlock(&filter_lock);

kfree(iter);
module_put(THIS_MODULE);

return 0;
}

static const struct file_operations mchar_fops = {
.owner = THIS_MODULE,
.write = device_write,
.open = device_open,
.release = device_release
};

int filter_init(void)
{
int ret;
struct device *dev;

mutex_init(&filter_lock);
filter_major = register_chrdev(0, FILTER_DEVICE_NAME, &mchar_fops);

if (filter_major < 0) {
pr_err("[ELKEID FILTER] REGISTER_CHRDEV_ERROR\n");
return filter_major;
Expand All @@ -476,27 +546,19 @@ int filter_init(void)

dev = device_create(filter_class, NULL, MKDEV(filter_major, 0),
NULL, FILTER_DEVICE_NAME);

if (IS_ERR(dev)) {
pr_err("[ELKEID FILTER] DEVICE_CREATE_ERROR");
ret = PTR_ERR(dev);
goto class_destroy;
}

sh_mem = smith_kzalloc(SHMEM_MAX_SIZE, GFP_KERNEL);
if (sh_mem == NULL) {
pr_err("[ELKEID FILTER] SHMEM_INIT_ERROR\n");
ret = -ENOMEM;
goto device_destroy;
}
return 0;

device_destroy:
device_destroy(filter_class, MKDEV(filter_major, 0));
class_destroy:
class_destroy(filter_class);
chrdev_unregister:
unregister_chrdev(filter_major, FILTER_DEVICE_NAME);
mutex_destroy(&filter_lock);

return ret;
}
Expand All @@ -506,7 +568,11 @@ void filter_cleanup(void)
device_destroy(filter_class, MKDEV(filter_major, 0));
class_destroy(filter_class);
unregister_chrdev(filter_major, FILTER_DEVICE_NAME);

if (filter_n_instances)
filter_show_instances();
mutex_destroy(&filter_lock);

del_all_execve_exe_allowlist();
del_all_execve_argv_allowlist();
smith_kfree(sh_mem);
}
2 changes: 1 addition & 1 deletion driver/LKM/src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ static void __exit kprobes_exit(void)
module_init(kprobes_init);
module_exit(kprobes_exit);

MODULE_VERSION("1.7.0.21");
MODULE_VERSION("1.7.0.22");
MODULE_LICENSE("GPL");

MODULE_INFO(homepage, "https://github.com/bytedance/Elkeid/tree/main/driver");
Expand Down
68 changes: 34 additions & 34 deletions driver/LKM/src/smith_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,41 @@ SMITH_HOOK(SETSID, 1);
SMITH_HOOK(PRCTL, 1);
SMITH_HOOK(MEMFD_CREATE, 1);
SMITH_HOOK(MOUNT, 1);
SMITH_HOOK(DNS, 1);
SMITH_HOOK(USERMODEHELPER, 1);
SMITH_HOOK(UDEV, 1);
SMITH_HOOK(CHMOD, 1);

SMITH_HOOK(WRITE, 0);
SMITH_HOOK(ACCEPT, 0);
SMITH_HOOK(OPEN, 0);
SMITH_HOOK(MPROTECT, 0);
SMITH_HOOK(NANOSLEEP, 0);
SMITH_HOOK(KILL, 0);
SMITH_HOOK(RM, 0);
SMITH_HOOK(EXIT, 0);

static int FAKE_SLEEP = 0;
static int FAKE_RM = 0;
SMITH_HOOK(WRITE, SANDBOX);
SMITH_HOOK(ACCEPT, SANDBOX);
SMITH_HOOK(OPEN, SANDBOX);
SMITH_HOOK(MPROTECT, SANDBOX);
SMITH_HOOK(KILL, SANDBOX);
SMITH_HOOK(RM, SANDBOX);
SMITH_HOOK(EXIT, SANDBOX);

/*
*
* raw tracepoint brings severe performance penalty for syscall-intensive ops.
* so disabled by default, and enabled only for SANDBOX or kernels >= 5.4.210
*
*/
SMITH_HOOK(RAWTP, SANDBOX || (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 210)));
SMITH_HOOK(DNS, SANDBOX || (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 210)));

static int FAKE_RM = SANDBOX;

#if SANDBOX
static int PID_TREE_LIMIT = 100;
static int PID_TREE_LIMIT_LOW = 100;
static int EXECVE_GET_SOCK_PID_LIMIT = 100;
static int EXECVE_GET_SOCK_FD_LIMIT = 100;
#else
static int PID_TREE_LIMIT = 12;
static int PID_TREE_LIMIT_LOW = 8;
static int EXECVE_GET_SOCK_PID_LIMIT = 4;
static int EXECVE_GET_SOCK_FD_LIMIT = 12; /* maximum fd numbers to be queried */
#endif

static char connect_syscall_kprobe_state = 0x0;
static char execve_kretprobe_state = 0x0;
Expand Down Expand Up @@ -2702,6 +2716,10 @@ static int __init smith_sysret_init(void)
{
int i, rc;

/* skip raw tracepoint registration */
if (!RAWTP_HOOK)
return 0;

/* check the tracepoints of our interest */
rc = smith_assert_tracepoints();
if (rc) {
Expand Down Expand Up @@ -2732,6 +2750,10 @@ static void smith_sysret_fini(void)
{
int i;

/* skip raw tracepoint unregistration */
if (!RAWTP_HOOK)
return;

/* register callbacks for the tracepoints of our interest */
for (i = NUM_TRACE_POINTS; i > 0; i--)
smith_unregister_tracepoint(&g_smith_tracepoints[i - 1]);
Expand Down Expand Up @@ -4804,28 +4826,6 @@ static void __init install_kprobe(void)
{
int ret;

if (SANDBOX == 1) {
DNS_HOOK = 1;
USERMODEHELPER_HOOK = 1;
//MPROTECT_HOOK = 1;
ACCEPT_HOOK = 1;
OPEN_HOOK = 1;
MPROTECT_HOOK = 1;
//NANOSLEEP_HOOK = 1;
KILL_HOOK = 1;
RM_HOOK = 1;
EXIT_HOOK = 1;
WRITE_HOOK = 1;

PID_TREE_LIMIT = 100;
PID_TREE_LIMIT_LOW = 100;
EXECVE_GET_SOCK_PID_LIMIT = 100;
EXECVE_GET_SOCK_FD_LIMIT = 100;

FAKE_SLEEP = 1;
FAKE_RM = 1;
}

if (UDEV_HOOK == 1) {
static void (*smith_usb_register_notify) (struct notifier_block * nb);
smith_usb_register_notify = __symbol_get("usb_register_notify");
Expand Down Expand Up @@ -5036,7 +5036,7 @@ static void __init install_kprobe(void)
module_param(sid_##name, charp, S_IRUSR|S_IRGRP|S_IROTH)

/* latest commit id */
static char *smith_srcid = SMITH_SRCID(6b3b480a0c12ef8c24cb3417a109d2082b72cfd9);
static char *smith_srcid = SMITH_SRCID(d2effe977bb0090128d7bfcfb725d3a997fff2ca);

static int __init kprobe_hook_init(void)
{
Expand Down
Loading
Loading