做这个东西源自一次面试,当时面试官仰天斜视45度,自以为很牛逼的说出了这个想法,我此奥,看了后很不爽,回来埋头一个月,做出第一个版本。已经于开源于github。
需求:在某些情况下,系统需要升级,但是不能重启,此时需要动态替换内核函数,进行动态升级。
本功能是基于2.6.38版本进行开发。 patch:git@github.com:cooboos/kxchg.git
解决思想很简单,就是利用trap指令进行函数替换(目前只支持x86架构)。下面就代码进行分析:
+struct kxchg+{+ struct list_head list; //链表++ const char *symbol_name;//被替换的函数名+ unsigned long addr; //被替换的函数地址++ const char *symbol_name_rep;//替换函数的函数名+ unsigned long addr_rep; //替换函数的函数地址++ int ori_ins; //被替换的原始指令的第一个字节(目前只做了x86架构的支持,int3指令为)+};+/*
--- kernel/kxchg.c (revision 0)+++ kernel/kxchg.c (revision 0)@@ -0,0 +1,183 @@+/*+ * <hack.coo@gmail.com>, 2012+ *+ * Released under the terms of the GNU GPL v2.0+ *+ * version 1.0 for Linux-2.6.38+ */+/*+ * trap int3 instruction+ */+#include <linux/kprobes.h>+#include <linux/hash.h>+#include <linux/init.h>+#include <linux/slab.h>+#include <linux/stddef.h>+#include <linux/module.h>+#include <linux/moduleloader.h>+#include <linux/kallsyms.h>+#include <linux/freezer.h>+#include <linux/seq_file.h>+#include <linux/debugfs.h>+#include <linux/kdebug.h>+#include <linux/kxchg.h>+#include <linux/notifier.h>+#include <linux/ptrace.h>++unsigned long kallsyms_lookup_name(const char *name);+extern void arch_trap_kxchg(struct kxchg *p);+extern void arch_saveins(struct kxchg *p);+extern int kxchg_notifier_process(struct notifier_block *self, unsigned long val, void *data);+struct kxchg_list kxchg_head;+struct kxchg_list kxchg_old;++static int kxchg_addr(struct kxchg *p)+{+ if (p && p->symbol_name && p->symbol_name_rep) {++ p->addr = kallsyms_lookup_name(p->symbol_name);+ if(!p->addr)+ return 1;++ p->addr_rep = kallsyms_lookup_name(p->symbol_name_rep);+ if(!p->addr_rep)+ return 1;+ }++ return 0;+}++int get_kxchg(struct kxchg *kxchg)+{+ int found = 0;+ struct list_head *plist, *tmp;+ struct kxchg *pkxchg = NULL;