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