#ifndef _FEATURES_DATA_H
#define _FEATURES_DATA_H
-#include <linux/types.h>
#include "syscall_list.h"
-#define X(x) #x
-static const char *const syscall_name[] = {
- SYSCALL_LIST
-};
-#undef X
-
-enum {
- syscall_name_cnt = sizeof(syscall_name) / sizeof(char *)
-};
-
#define X(x) id_##x
enum syscall_id {
SYSCALL_LIST
};
#undef X
-static char sys_counter[syscall_name_cnt] = { 0 };
-
static enum syscall_id id_file[] = {
id_sys_acct,
id_sys_mount,
id_sys_umount,
id_sys_truncate,
- id_sys_stat,
+/* TODO:
+ * id_sys_stat,
+ */
id_sys_statfs,
id_sys_statfs64,
- id_sys_lstat,
+/* TODO:
+ * id_sys_lstat,
+ */
id_sys_stat64,
id_sys_fstat64,
id_sys_lstat64,
id_sys_fchmodat,
id_sys_fchownat,
id_sys_openat,
- id_sys_newfstatat,
+/* TODO:
+ * id_sys_newfstatat,
+ */
id_sys_readlinkat,
id_sys_utimensat,
id_sys_fanotify_mark,
id_sys_exit_group,
id_sys_wait4,
id_sys_waitid,
- id_sys_waitpid,
+/* TODO:
+ * id_sys_waitpid,
+ */
id_sys_rt_tgsigqueueinfo,
id_sys_unshare,
id_sys_fork,
static enum syscall_id id_signal[] = {
id_sys_sigpending,
id_sys_sigprocmask,
- id_sys_sigaltstack,
+/* TODO:
+ * id_sys_sigaltstack,
+ */
/* TODO: add support CONFIG_OLD_SIGSUSPEND and CONFIG_OLD_SIGSUSPEND3
* id_sys_sigsuspend,
* id_sys_sigsuspend,
id_sys_rt_tgsigqueueinfo,
id_sys_kill,
id_sys_tgkill,
- id_sys_signal,
+/* TODO:
+ * id_sys_signal,
+ */
id_sys_pause,
id_sys_signalfd,
id_sys_signalfd4
id_sys_fchmodat,
id_sys_fchownat,
id_sys_openat,
- id_sys_newfstatat,
+/* TODO:
+ * id_sys_newfstatat,
+ */
id_sys_readlinkat,
id_sys_utimensat,
id_sys_splice,
id_sys_setns
};
-struct feature {
- size_t cnt;
- enum syscall_id *feature_list;
-};
-
-#define CREATE_FEATURE(x) \
-{ \
- .cnt = sizeof(x) / sizeof(enum syscall_id), \
- .feature_list = x \
-}
-
-static struct feature features[] = {
- CREATE_FEATURE(id_file),
- CREATE_FEATURE(id_irq),
- CREATE_FEATURE(id_net),
- CREATE_FEATURE(id_process),
- CREATE_FEATURE(id_signal),
- CREATE_FEATURE(id_desc)
-};
-
-#undef CREATE_FEATURE
-
-enum {
- feature_cnt = sizeof(features) / sizeof(struct feature)
-};
-
#endif /* _FEATURES_DATA_H */
+#include <linux/module.h>
+#include <asm/errno.h>
+#include <ksyms.h>
+#include <dbi_kprobes.h>
#include "ks_features.h"
#include "features_data.h"
-#include <asm/errno.h>
-#include <linux/module.h>
+#include "syscall_list.h"
+
+
+struct feature {
+ size_t cnt;
+ enum syscall_id *feature_list;
+};
+
+struct ks_probe {
+ struct jprobe jp;
+ struct kretprobe rp;
+ int counter;
+};
+
+
+#define CREATE_JP(name) \
+{ \
+ .entry = NULL, \
+ .pre_entry = NULL \
+}
+
+#define CREATE_RP(name) \
+{ \
+ .entry_handler = NULL, \
+ .handler = NULL \
+}
+
+#define CREATE_FEATURE(x) \
+{ \
+ .cnt = sizeof(x) / sizeof(enum syscall_id), \
+ .feature_list = x \
+}
+
+
+#define X(x) #x
+static const char *const syscall_name[] = {
+ SYSCALL_LIST
+};
+#undef X
+
+enum {
+ syscall_name_cnt = sizeof(syscall_name) / sizeof(char *)
+};
+
+
+#define X(x) \
+{ \
+ .jp = CREATE_JP(x), \
+ .rp = CREATE_RP(x), \
+ .counter = 0 \
+}
+
+static struct ks_probe ksp[] = {
+ SYSCALL_LIST
+};
+#undef X
+
+
+static struct feature features[] = {
+ CREATE_FEATURE(id_file),
+ CREATE_FEATURE(id_irq),
+ CREATE_FEATURE(id_net),
+ CREATE_FEATURE(id_process),
+ CREATE_FEATURE(id_signal),
+ CREATE_FEATURE(id_desc)
+};
+
+enum {
+ feature_cnt = sizeof(features) / sizeof(struct feature)
+};
+
+
+static char *get_sys_name(size_t id)
+{
+ return syscall_name[id];
+}
+
+static int get_counter(size_t id)
+{
+ return ksp[id].counter;
+}
+
+static void inc_counter(size_t id)
+{
+ ++ksp[id].counter;
+}
+
+static void dec_counter(size_t id)
+{
+ --ksp[id].counter;
+}
static int register_syscall(size_t id)
{
- printk("register_syscall: %s\n", syscall_name[id]);
- return 0;
+ int ret;
+ printk("register_syscall: %s\n", get_sys_name(id));
+
+ ret = dbi_register_jprobe(&ksp[id].jp);
+ if (ret)
+ return ret;
+
+ ret = dbi_register_kretprobe(&ksp[id].rp);
+ if (ret)
+ dbi_unregister_jprobe(&ksp[id].jp);
+
+ return ret;
}
static int unregister_syscall(size_t id)
{
- printk("unregister_syscall: %s\n", syscall_name[id]);
+ printk("unregister_syscall: %s\n", get_sys_name(id));
+
+ dbi_unregister_kretprobe(&ksp[id].rp);
+ dbi_unregister_jprobe(&ksp[id].jp);
+
return 0;
}
static int install_features(struct feature *f)
{
- size_t i, num;
+ size_t i, id;
for (i = 0; i < f->cnt; ++i) {
- num = f->feature_list[i];
+ id = f->feature_list[i];
- if (sys_counter[num] == 0) {
- int ret = register_syscall(num);
+ if (get_counter(id) == 0) {
+ int ret = register_syscall(id);
if (ret) {
/* TODO: error */
return ret;
}
}
- ++sys_counter[num];
+ inc_counter(id);
}
return 0;
static int uninstall_features(struct feature *f)
{
- size_t i, num;
+ size_t i, id;
for (i = 0; i < f->cnt; ++i) {
- num = f->feature_list[i];
+ id = f->feature_list[i];
- if (sys_counter[num] == 0) {
+ if (get_counter(id) == 0) {
/* TODO: error */
return -EINVAL;
}
- --sys_counter[num];
+ dec_counter(id);
- if (sys_counter[num] == 0) {
- int ret = unregister_syscall(num);
+ if (get_counter(id) == 0) {
+ int ret = unregister_syscall(id);
if (ret) {
/* TODO: error */
return ret;
return &features[id];
}
-int set_features(enum feature_id id)
+int set_feature(enum feature_id id)
{
struct feature *f = get_feature(id);
return install_features(f);
}
+EXPORT_SYMBOL_GPL(set_feature);
-int unset_features(enum feature_id id)
+int unset_feature(enum feature_id id)
{
struct feature *f = get_feature(id);
return uninstall_features(f);
}
+EXPORT_SYMBOL_GPL(unset_feature);
static int __init init_ks_feature(void)
{
- return 0;
+ int i;
+ unsigned long addr;
+ char *name;
+
+ for (i = 0; i < syscall_name_cnt; ++i) {
+ name = get_sys_name(i);
+ addr = swap_ksyms(name);
+ if (addr == 0) {
+ printk("%s() not found\n", name);
+ return -EFAULT;
+ }
+
+ ksp[i].jp.kp.addr = ksp[i].rp.kp.addr = addr;
+ }
+
+ return 0;
}
static void __exit exit_ks_feature(void)
module_init(init_ks_feature);
module_exit(exit_ks_feature);
+MODULE_LICENSE("GPL");
+
/* debug */
static void print_feature(struct feature *f)
{
size_t i;
for (i = 0; i < f->cnt; ++i) {
- printk(" feature[%3u]: %s\n", i, syscall_name[f->feature_list[i]]);
+ printk(" feature[%3u]: %s\n", i, get_sys_name(f->feature_list[i]));
}
}
printk("SYSCALL:\n");
for (i = 0; i < syscall_name_cnt; ++i) {
- printk(" [%2d] %s\n", sys_counter[i], syscall_name[i]);
+ printk(" [%2d] %s\n", get_counter(i), get_sys_name(i));
}
}
/* debug */