Created
April 28, 2014 14:29
-
-
Save bojieli/11373858 to your computer and use it in GitHub Desktop.
detect link up/down and its initiator with kprobe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <linux/kernel.h> | |
#include <linux/module.h> | |
#include <linux/kprobes.h> | |
#include <linux/netdevice.h> | |
#include <linux/fs.h> | |
#include <linux/fs_struct.h> | |
/* For each probe you need to allocate a kprobe structure */ | |
static struct kprobe kp = { | |
.symbol_name = "dev_change_flags", | |
}; | |
#define BUFLEN 256 | |
/* kprobe pre_handler: called just before the probed instruction is executed */ | |
static int handler_pre(struct kprobe *p, struct pt_regs *regs) | |
{ | |
printk(KERN_INFO "pre_handler: dev_change_flags called with rdi=%p rsi=%p rdx=%p rcx=%p\n", | |
(void *)regs->di, (void *)regs->si, (void *)regs->dx, (void *)regs->cx); | |
if (regs->di) { | |
char name[IFNAMSIZ + 1] = {0}; | |
memcpy(name, ((struct net_device *)regs->di)->name, IFNAMSIZ); | |
printk(KERN_INFO "pre_handler: interface [%s] %s\n", | |
name, (regs->si & IFF_UP ? "up" : "down")); | |
if (current && current->fs) { | |
char buf[BUFLEN] = {0}; | |
char *path = d_path(¤t->fs->pwd, buf, BUFLEN); | |
if (path && path >= buf && path < buf + BUFLEN) | |
printk(KERN_INFO "pre_handler: process working dir: %s\n", path); | |
} | |
if (current && current->mm && current->mm->exe_file) { | |
char buf[BUFLEN] = {0}; | |
char *path; | |
struct file *exe_file = current->mm->exe_file; | |
path_get(&exe_file->f_path); | |
path = d_path(&exe_file->f_path, buf, BUFLEN); | |
if (path && path >= buf && path < buf + BUFLEN) | |
printk(KERN_INFO "pre_handler: process exe path: %s\n", path); | |
} | |
printk(KERN_INFO "pre_handler: stack dump: "); | |
dump_stack(); | |
} else { | |
printk(KERN_INFO "pre_handler: unexpected: rdi=0\n"); | |
} | |
return 0; | |
} | |
/* kprobe post_handler: called after the probed instruction is executed */ | |
static void handler_post(struct kprobe *p, struct pt_regs *regs, | |
unsigned long flags) | |
{ | |
} | |
/* | |
* fault_handler: this is called if an exception is generated for any | |
* instruction within the pre- or post-handler, or when Kprobes | |
* single-steps the probed instruction. | |
*/ | |
static int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr) | |
{ | |
printk(KERN_INFO "fault_handler: p->addr = 0x%p, trap #%dn", | |
p->addr, trapnr); | |
/* Return 0 because we don't handle the fault. */ | |
return 0; | |
} | |
static int __init kprobe_init(void) | |
{ | |
int ret; | |
kp.pre_handler = handler_pre; | |
kp.post_handler = handler_post; | |
kp.fault_handler = handler_fault; | |
ret = register_kprobe(&kp); | |
if (ret < 0) { | |
printk(KERN_INFO "register_kprobe failed, returned %d\n", ret); | |
return ret; | |
} | |
printk(KERN_INFO "Planted kprobe at %p\n", kp.addr); | |
return 0; | |
} | |
static void __exit kprobe_exit(void) | |
{ | |
unregister_kprobe(&kp); | |
printk(KERN_INFO "kprobe at %p unregistered\n", kp.addr); | |
} | |
module_init(kprobe_init) | |
module_exit(kprobe_exit) | |
MODULE_LICENSE("GPL"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment