I have a reduced Linux Kernel Module that fires an error:
$ uname -a
Linux raspberrypi 6.1.21-v8+ #1642 SMP PREEMPT Mon Apr 3 17:24:16 BST 2023 aarch64 GNU/Linux
$ gcc --version
gcc (Debian 10.2.1-6) 10.2.1 20210110
$ cat dummy_driver.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h> /* kmalloc, kzalloc */
#include <linux/proc_fs.h> /* procfs */
/* Meta Information */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dark VADOR");
MODULE_DESCRIPTION("Dummy driver");
/* Module name to associate to each printk */
static char mod_name[32] = "dummy driver";
/* Buffer of data (allocated in kernel space) */
static char * kernel_buffer;
static unsigned int kernel_buffer_size = 255;
/* Variables for procfs file */
static struct proc_dir_entry *proc_file;
/**
* @brief Read data from kernel buffer to user buffer.
*/
static ssize_t mod_read(struct file *file, char *user_buffer, size_t user_buffer_size, loff_t *offs) {
size_t to_copy, not_copied, delta;
/* Get amount of data to copy */
to_copy = min(user_buffer_size, (size_t) kernel_buffer_size);
/* Copy data from kernel space to user space */
not_copied = copy_to_user(user_buffer, kernel_buffer, to_copy);
/* Calculate chunk of data that has been read */
delta = to_copy - not_copied;
printk("%s: %zu bytes have been read from kernel to user buffer.n", mod_name, delta);
return delta;
}
/**
* @brief Write data from user buffer to kernel buffer.
*/
static ssize_t mod_write(struct file *file, const char *user_buffer, size_t user_buffer_size, loff_t *offs) {
size_t to_copy, not_copied, delta;
/* Get amount of data to copy */
to_copy = min(user_buffer_size, (size_t) kernel_buffer_size);
/* Copy data from user space to kernel space */
not_copied = copy_from_user(kernel_buffer, user_buffer, to_copy);
/* Calculate chunk of data that has been written */
delta = to_copy - not_copied;
printk("%s: %zu bytes have been written from user to kernel buffer.n", mod_name, delta);
return delta;
}
static loff_t mod_lseek(struct file *filp, loff_t off, int whence)
{
filp->f_pos = off;
return off;
}
/* Gather procfs file operations */
static struct proc_ops procfs_fops = {
.proc_read = mod_read,
.proc_write = mod_write,
.proc_lseek = mod_lseek,
};
/**
* @brief Called when the module is loaded into the kernel.
*/
static int __init mod_init(void) {
/* Allocate LKM buffer */
kernel_buffer = kzalloc(kernel_buffer_size, GFP_KERNEL);
if(kernel_buffer == NULL) {
printk("%s: allocating kernel buffer failed.n", mod_name);
return -1;
}
printk("%s: kernel buffer of size %u created.n", mod_name, kernel_buffer_size);
/*
* Create procfs file
* Note: to access the file, user does not need to be root.
*/
proc_file = proc_create("dummy_driver", 0666, NULL, &procfs_fops);
if(proc_file == NULL) {
printk("%s: creating procfs file failed.n", mod_name);
return -1;
}
printk("%s: module is loaded into the kernel.n", mod_name);
return 0;
}
/**
* @brief Called when the module is removed from the kernel.
*/
static void __exit mod_exit(void) {
proc_remove(proc_file);
kfree(kernel_buffer);
printk("%s: module is removed from the kernel.n", mod_name);
}
module_init(mod_init);
module_exit(mod_exit);
$ cat Makefile
obj-m += dummy_driver.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
$ make
Note that in the code I added a mod_lseek
callback.
But when using the procfs file I get this kind of cannot seek to relative offset
error:
$ sudo insmod dummy_driver.ko
$ echo "procfs test" > /proc/dummy_driver
$ head -n 3 /proc/dummy_driver
procfs test
procfs test
head: /proc/dummy_driver: cannot seek to relative offset -243: Unknown error 243
procfs test
Note that this error does not show up when I do something equivalent like:
$ cat /proc/dummy_driver | head -n 3
procfs test
procfs test
procfs test
Why do I get this cannot seek to relative offset
error?
How to fix it?
For what purpose .proc_lseek
is supposed to be used for, and, is my implementation correct?