xref: /linux-tools/drivers/mremap/module/ptracexx.c (revision 74ce4ce33d5b8318cee71b38976a25818e666ff3)
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