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