-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCRThreeModule.c
181 lines (149 loc) · 5.1 KB
/
CRThreeModule.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include <asm/desc.h>
#include <asm/io.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/pid.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
// Info
#define DRIVER_AUTHOR "Robert Marciniak <robmarci@student.pg.edu.pl>"
#define DRIVER_DESC "Character driver that stores CR3 physical address of provided PID"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Robert Marciniak");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION("0.1");
// User defines
#define DEVICE_NAME "CRThree_char"
#define CLASS_NAME "CRThree_class"
#define MESSAGE_BUFFER_LENGTH 256
static struct class* CRThreeClass = NULL;
static struct device* CRThreeDevice = NULL;
static int deviceMajorNumber;
static short size_of_message;
static char messageBuffer[MESSAGE_BUFFER_LENGTH];
// Mutex
static DEFINE_MUTEX(CRThree_mutex);
// Prototypes for contracts
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
static unsigned long pid_to_cr3(int);
static struct file_operations file_ops = {
.owner = THIS_MODULE,
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
static int __init CRThree_init(void)
{
mutex_init(&CRThree_mutex);
printk(KERN_INFO "[init] CRThree_init\n");
deviceMajorNumber= register_chrdev(0, DEVICE_NAME, &file_ops);
if(deviceMajorNumber < 0) {
printk(KERN_WARNING "[init] alloc_chrdev_region failed\n");
return deviceMajorNumber;
}
else {
printk(KERN_INFO "[init] Registered device with major number %d\n",deviceMajorNumber);
}
CRThreeClass = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(CRThreeClass)) {
unregister_chrdev(deviceMajorNumber,DEVICE_NAME);
printk(KERN_ALERT "[init] Failed to register device class\n");
return PTR_ERR(CRThreeClass);
}
else {
printk(KERN_INFO "[init] Correctly registered device class\n");
}
CRThreeDevice = device_create(CRThreeClass, NULL, MKDEV(deviceMajorNumber,0), NULL, DEVICE_NAME);
if(IS_ERR(CRThreeDevice)) {
class_destroy(CRThreeClass);
unregister_chrdev(deviceMajorNumber,DEVICE_NAME);
printk(KERN_ALERT "[init] Failed to create device\n");
return PTR_ERR(CRThreeDevice);
}
else {
printk(KERN_INFO "[init] Device created\n");
}
return 0;
}
static void __exit CRThree_exit(void)
{
printk(KERN_INFO "[exit] CRThree_exit\n");
printk(KERN_INFO "[exit] destroying device\n");
device_destroy(CRThreeClass, MKDEV(deviceMajorNumber, 0));
printk(KERN_INFO "[exit] unregistering class\n");
class_unregister(CRThreeClass);
printk(KERN_INFO "[exit] destroying class\n");
class_destroy(CRThreeClass);
printk(KERN_INFO "[exit] unregistering character device\n");
unregister_chrdev(deviceMajorNumber, DEVICE_NAME);
printk(KERN_INFO "[exit] unregistered class and device\n");
mutex_destroy(&CRThree_mutex);
}
static int device_open(struct inode *inode_ptr, struct file *file_ptr){
if(!mutex_trylock(&CRThree_mutex)){
printk(KERN_ALERT "[device_open] "DEVICE_NAME" is busy");
return -EBUSY;
}
return 0;
}
static int device_release(struct inode *inode_ptr, struct file *file_ptr){
mutex_unlock(&CRThree_mutex);
return 0;
}
static ssize_t device_read(struct file *file_ptr, char *buffer, size_t length, loff_t *offset) {
int errorCount = 0;
errorCount = copy_to_user(buffer, messageBuffer, size_of_message);
if(errorCount == 0) {
printk(KERN_INFO "[device_read] sent buffer with %d characters\n", size_of_message);
return (size_of_message=0);
}
else {
printk(KERN_NOTICE "[device_read] Failed to send %d characters to user\n",errorCount);
return -EFAULT;
}
}
static ssize_t device_write(struct file *file_ptr, const char *buffer, size_t length, loff_t *offset){
long pid;
int returnValue;
returnValue = kstrtoul(buffer, 0, &pid);
if(returnValue == 0){
printk(KERN_INFO "[device_write] received %zu characters. Parsed as %lu\n", length, pid);
sprintf(messageBuffer, "Content of CR3 register: %lu\n", pid_to_cr3(pid));
size_of_message = strlen(messageBuffer);
}
else {
printk(KERN_NOTICE "[device_write] Failed to parse input. Value %d\n", returnValue);
return returnValue;
}
return length;
}
static unsigned long pid_to_cr3(int pid)
{
struct task_struct *task;
struct mm_struct *mm;
void *cr3_virt;
unsigned long cr3_phys;
task = pid_task(find_vpid(pid), PIDTYPE_PID);
if (task == NULL)
return 0;
mm = task->mm;
if (mm == NULL) {
mm = task->active_mm;
}
if (mm == NULL)
return 0;
cr3_virt = (void *) mm->pgd;
cr3_phys = virt_to_phys(cr3_virt);
return cr3_phys;
}
module_init(CRThree_init);
module_exit(CRThree_exit);