1*74ce4ce3SDavid Wang #include <linux/module.h>
2*74ce4ce3SDavid Wang #include <linux/device.h>
3*74ce4ce3SDavid Wang #include <linux/kernel.h>
4*74ce4ce3SDavid Wang #include <linux/pid.h>
5*74ce4ce3SDavid Wang #include <linux/mm.h>
6*74ce4ce3SDavid Wang #include <linux/uaccess.h>
7*74ce4ce3SDavid Wang #include <linux/fs.h>
8*74ce4ce3SDavid Wang #include <linux/mman.h>
9*74ce4ce3SDavid Wang
10*74ce4ce3SDavid Wang
11*74ce4ce3SDavid Wang MODULE_LICENSE("GPL");
12*74ce4ce3SDavid Wang MODULE_AUTHOR("lddlinan <00107082@163.com>");
13*74ce4ce3SDavid Wang MODULE_DESCRIPTION("ptrace extensions");
14*74ce4ce3SDavid Wang
15*74ce4ce3SDavid Wang
16*74ce4ce3SDavid Wang #define DEVICE_NAME "ptracexx"
17*74ce4ce3SDavid Wang #define CLASS_NAME "ptracexx"
18*74ce4ce3SDavid Wang static int major_number;
19*74ce4ce3SDavid Wang static struct class* mClass = NULL;
20*74ce4ce3SDavid Wang static struct device* mDevice = NULL;
21*74ce4ce3SDavid Wang
22*74ce4ce3SDavid Wang enum {
23*74ce4ce3SDavid Wang PTRACEXX_REMAP = 1,
24*74ce4ce3SDavid Wang };
25*74ce4ce3SDavid Wang
26*74ce4ce3SDavid Wang typedef struct {
27*74ce4ce3SDavid Wang int pid;
28*74ce4ce3SDavid Wang unsigned long old_start, old_end;
29*74ce4ce3SDavid Wang unsigned long new_start, new_end;
30*74ce4ce3SDavid Wang } RemapDataT;
31*74ce4ce3SDavid Wang
32*74ce4ce3SDavid Wang typedef union {
33*74ce4ce3SDavid Wang RemapDataT remap;
34*74ce4ce3SDavid Wang } IoctlDataT;
35*74ce4ce3SDavid Wang
ptracexx_ioctl(struct file * _f,unsigned int cmd,unsigned long val)36*74ce4ce3SDavid Wang static long ptracexx_ioctl(struct file *_f, unsigned int cmd, unsigned long val) {
37*74ce4ce3SDavid Wang struct task_struct *task;
38*74ce4ce3SDavid Wang struct pid *pid;
39*74ce4ce3SDavid Wang IoctlDataT data;
40*74ce4ce3SDavid Wang unsigned long rc;
41*74ce4ce3SDavid Wang int k;
42*74ce4ce3SDavid Wang const char *user_ptr = (const char*) val;
43*74ce4ce3SDavid Wang switch(cmd) {
44*74ce4ce3SDavid Wang case PTRACEXX_REMAP:
45*74ce4ce3SDavid Wang k = copy_from_user(&data, user_ptr, sizeof(data));
46*74ce4ce3SDavid Wang if (k != 0) {
47*74ce4ce3SDavid Wang printk("fail to copy from user, left %d/%ld\n", k, sizeof(data));
48*74ce4ce3SDavid Wang return -1;
49*74ce4ce3SDavid Wang }
50*74ce4ce3SDavid Wang printk("ioctl remap for pid %d, [%lx->%lx) ==> [%lx->%lx)\n", data.remap.pid, data.remap.old_start, data.remap.old_end, data.remap.new_start, data.remap.new_end);
51*74ce4ce3SDavid Wang pid = find_pid_ns(data.remap.pid, &init_pid_ns);
52*74ce4ce3SDavid Wang if (pid == NULL) {
53*74ce4ce3SDavid Wang printk("pid not found\n");
54*74ce4ce3SDavid Wang return -1;
55*74ce4ce3SDavid Wang }
56*74ce4ce3SDavid Wang task = get_pid_task(pid, PIDTYPE_PID);
57*74ce4ce3SDavid Wang if (task == NULL) {
58*74ce4ce3SDavid Wang printk("task not found\n");
59*74ce4ce3SDavid Wang return -1;
60*74ce4ce3SDavid Wang }
61*74ce4ce3SDavid Wang rc = mremap_task(task,
62*74ce4ce3SDavid Wang data.remap.old_start, data.remap.old_end-data.remap.old_start,
63*74ce4ce3SDavid Wang data.remap.new_end-data.remap.new_start,
64*74ce4ce3SDavid Wang MREMAP_FIXED|MREMAP_MAYMOVE, data.remap.new_start);
65*74ce4ce3SDavid Wang if (IS_ERR((void*)rc)) {
66*74ce4ce3SDavid Wang printk("remap failed: %ld\n", rc);
67*74ce4ce3SDavid Wang return -1;
68*74ce4ce3SDavid Wang }
69*74ce4ce3SDavid Wang break;
70*74ce4ce3SDavid Wang default:
71*74ce4ce3SDavid Wang return -1;
72*74ce4ce3SDavid Wang }
73*74ce4ce3SDavid Wang return 0;
74*74ce4ce3SDavid Wang }
75*74ce4ce3SDavid Wang struct file_operations fops = {
76*74ce4ce3SDavid Wang .unlocked_ioctl = ptracexx_ioctl,
77*74ce4ce3SDavid Wang .compat_ioctl = ptracexx_ioctl
78*74ce4ce3SDavid Wang };
79*74ce4ce3SDavid Wang
ptracexx_module_init(void)80*74ce4ce3SDavid Wang static int __init ptracexx_module_init(void) {
81*74ce4ce3SDavid Wang major_number = register_chrdev(0, DEVICE_NAME, &fops);
82*74ce4ce3SDavid Wang if (major_number<0) return major_number;
83*74ce4ce3SDavid Wang mClass = class_create(THIS_MODULE, CLASS_NAME);
84*74ce4ce3SDavid Wang if (IS_ERR(mClass)) {
85*74ce4ce3SDavid Wang unregister_chrdev(major_number, DEVICE_NAME);
86*74ce4ce3SDavid Wang return PTR_ERR(mClass);
87*74ce4ce3SDavid Wang }
88*74ce4ce3SDavid Wang mDevice = device_create(mClass, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME);
89*74ce4ce3SDavid Wang if (IS_ERR(mDevice)) {
90*74ce4ce3SDavid Wang class_destroy(mClass);
91*74ce4ce3SDavid Wang unregister_chrdev(major_number, DEVICE_NAME);
92*74ce4ce3SDavid Wang return PTR_ERR(mDevice);
93*74ce4ce3SDavid Wang }
94*74ce4ce3SDavid Wang return 0;
95*74ce4ce3SDavid Wang }
96*74ce4ce3SDavid Wang
ptracexx_module_exit(void)97*74ce4ce3SDavid Wang static void __exit ptracexx_module_exit(void) {
98*74ce4ce3SDavid Wang device_destroy(mClass, MKDEV(major_number, 0));
99*74ce4ce3SDavid Wang class_unregister(mClass);
100*74ce4ce3SDavid Wang class_destroy(mClass);
101*74ce4ce3SDavid Wang unregister_chrdev(major_number, DEVICE_NAME);
102*74ce4ce3SDavid Wang }
103*74ce4ce3SDavid Wang
104*74ce4ce3SDavid Wang
105*74ce4ce3SDavid Wang module_init(ptracexx_module_init);
106*74ce4ce3SDavid Wang module_exit(ptracexx_module_exit);
107