This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
zhangyang-variable-monitor/source/module/monitor_kernel.c

167 lines
4.7 KiB
C
Raw Normal View History

#include "monitor_kernel.h"
#include <linux/cdev.h> // for cdev
2023-11-16 13:17:49 +08:00
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/slab.h> // for kmalloc
2023-11-16 13:17:49 +08:00
#define DEVICE_NAME "variable_monitor"
// for character device
static dev_t dev_num;
static struct cdev *watch_cdev;
static struct class *watch_class;
struct my_device_data {
pid_t pid;
};
static int device_open(struct inode *inode, struct file *file) {
struct my_device_data *data;
printk(KERN_INFO "variable_monitor fun: %s with pid %d\n", __FUNCTION__,
current->pid);
2023-11-16 13:17:49 +08:00
// save pid
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data) return -ENOMEM;
2023-11-16 13:17:49 +08:00
data->pid = current->pid;
file->private_data = data;
return 0;
}
static int device_release(struct inode *inode, struct file *file) {
// load pid
struct my_device_data *data = file->private_data;
printk(KERN_INFO "variable_monitor fun: %s with pid %d\n", __FUNCTION__,
data->pid);
2023-11-16 13:17:49 +08:00
// clear watch with pid
clear_watch(data->pid);
kfree(data); // free data memory
2023-11-16 13:17:49 +08:00
return 0;
}
2023-11-23 04:45:35 -05:00
typedef struct {
int pid;
} ioctl_pid;
2023-11-16 13:17:49 +08:00
static long device_ioctl(struct file *file, unsigned int ioctl_num,
unsigned long ioctl_param) {
int ret = 0;
2023-11-23 18:12:57 +08:00
watch_arg warg;
ioctl_dump_param dump_param;
2023-11-26 22:52:56 -05:00
// ioctl_pid wpid;
2023-11-19 20:30:48 -05:00
printk(KERN_INFO "variable_monitor fun: %s with ioctl_num %d\n", __FUNCTION__,
ioctl_num);
switch (ioctl_num) {
2023-11-23 18:12:57 +08:00
case 0:
// copy watch_arg
if (copy_from_user(&warg, (watch_arg *)ioctl_param, sizeof(warg))) {
return -EACCES;
}
printk(KERN_INFO
"Watch_arg: task_id=%d, name=%s, ptr=%p, length_byte=%d, "
"time_ns=%ld, threshold=%lld\n",
warg.task_id, warg.name, warg.ptr, warg.length_byte, warg.time_ns,
warg.threshold);
// start watch variable
start_watch_variable(warg);
break;
case 1:
2023-11-26 22:52:56 -05:00
printk(KERN_INFO "variable_monitor ioctl_num 1\n");
2023-11-19 20:30:48 -05:00
ret = copy_from_user(&dump_param, (ioctl_dump_param *)ioctl_param,
sizeof(ioctl_dump_param));
2023-11-20 05:31:10 -05:00
printk(KERN_INFO "dump_param: %p %lu %p\n", dump_param.user_ptr_len, dump_param.user_buf_len, dump_param.user_buf);
if (!ret) {
2023-11-26 22:52:56 -05:00
// printk(KERN_INFO "ret\n");
ret = copy_to_user_variant_buffer(
&load_monitor_variant_buffer, dump_param.user_ptr_len,
dump_param.user_buf, dump_param.user_buf_len);
2023-11-19 20:30:48 -05:00
// printk(KERN_INFO "ret %d, %lu\n", ret, dump_param.user_buf_len);
}
2023-11-26 22:52:56 -05:00
printk(KERN_INFO "copy_to_user_variant_buffer \n");
2023-11-23 00:29:21 -05:00
break;
2023-11-23 18:12:57 +08:00
// case 0:
// printk(KERN_INFO "variable_monitor test 2\n");
// ret = copy_from_user(&wpid, (ioctl_pid *)ioctl_param, sizeof(ioctl_pid));
// diag_test(wpid.pid);
// /* code */
// break;
default:
2023-11-23 18:12:57 +08:00
// printk(KERN_INFO "variable_monitor test default\n");
// ret = copy_from_user(&wpid, (ioctl_pid *)ioctl_param, sizeof(ioctl_pid));
// diag_test(wpid.pid);
break;
2023-11-16 13:17:49 +08:00
}
return 0;
}
static struct file_operations fops = {
.open = device_open,
.release = device_release,
.unlocked_ioctl = device_ioctl,
};
int init_module(void) {
2023-11-16 21:08:27 -05:00
printk(KERN_INFO "variable_monitor fun: %s\n", __FUNCTION__);
2023-11-16 13:17:49 +08:00
if (alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME) < 0) {
printk(KERN_ALERT "Failed to register device number\n");
return -1;
}
2023-11-23 04:45:35 -05:00
if ((watch_class = class_create(THIS_MODULE, DEVICE_NAME)) == NULL) {
printk(KERN_ALERT "Failed to create class\n");
cdev_del(watch_cdev);
2023-11-16 13:17:49 +08:00
unregister_chrdev_region(dev_num, 1);
return -1;
}
2023-11-23 04:45:35 -05:00
if (device_create(watch_class, NULL, dev_num, NULL, DEVICE_NAME) == NULL) {
printk(KERN_ALERT "Failed to create device\n");
2023-11-16 13:17:49 +08:00
class_destroy(watch_class);
2023-11-23 04:45:35 -05:00
cdev_del(watch_cdev);
2023-11-16 13:17:49 +08:00
unregister_chrdev_region(dev_num, 1);
return -1;
}
2023-11-23 04:45:35 -05:00
if ((watch_cdev = cdev_alloc()) == NULL) {
printk(KERN_ALERT "Failed to allocate cdev structure\n");
2023-11-16 13:17:49 +08:00
unregister_chrdev_region(dev_num, 1);
return -1;
}
2023-11-23 04:45:35 -05:00
cdev_init(watch_cdev, &fops);
if (cdev_add(watch_cdev, dev_num, 1) == -1) {
printk(KERN_ALERT "Failed to add cdev structure\n");
device_destroy(watch_class, dev_num);
2023-11-16 13:17:49 +08:00
class_destroy(watch_class);
unregister_chrdev_region(dev_num, 1);
return -1;
}
printk(KERN_INFO "dev number: %d\n", dev_num);
printk(KERN_INFO "path: /dev/%s %d\n", DEVICE_NAME, dev_num);
2023-11-16 17:39:26 +08:00
// orig_X | buffer
2023-11-16 14:07:26 +08:00
monitor_init();
2023-11-16 13:17:49 +08:00
return 0;
}
void cleanup_module(void) {
2023-11-16 21:08:27 -05:00
printk(KERN_INFO "variable_monitor fun: %s\n", __FUNCTION__);
2023-11-16 17:39:26 +08:00
// clear all watch | free buffer
monitor_exit();
2023-11-16 13:17:49 +08:00
// unmount
device_destroy(watch_class, dev_num);
class_destroy(watch_class);
cdev_del(watch_cdev);
unregister_chrdev_region(dev_num, 1);
}
2023-11-16 14:07:26 +08:00
MODULE_LICENSE("GPL");