With this debugfs API I can create a file in /sys/kernel/debug/parent/name, but it's empty, no matter which data I put in void *data parameter
struct dentry *debugfs_create_file(const char *name, mode_t mode, struct dentry *parent, void *data, struct file_operations *fops);
According to documentation we need to implement file_operations ourself to handle file open and write.
A snippet of code from mine:
static ssize_t myreader(struct file *fp, char __user *user_buffer,
size_t count, loff_t *position)
{
return simple_read_from_buffer(user_buffer, count, position, ker_buf, len);
}
static ssize_t mywriter(struct file *fp, const char __user *user_buffer,
size_t count, loff_t *position)
{
if(count > len )
return -EINVAL;
return simple_write_to_buffer(ker_buf, len, position, user_buffer, count);
}
static const struct file_operations fops_debug = {
.read = myreader,
.write = mywriter,
};
static int __init init_debug(void)
{
dirret = debugfs_create_dir("dell", NULL);
fileret = debugfs_create_file("text", 0644, dirret, "HELLO WORLD", &fops_debug);
debugfs_create_u64("number", 0644, dirret, &intvalue);
return (0);
}
After installing this module to kernel, two files 'text' and 'number' will be created in the folder 'dell'. File 'number' contains the number I passed in as 'intvalue' as expected, but the other file 'text' is empty.
It's written in document that data will be stored in the i_private field of the resulting inode structure
My expectation: The string "HELLO WORLD" will be written in the file after module is loaded.
I think that the problem should be in the read and write operation functions. Is it possible to create a file with a particular content with the debugfs_create_file method?
To answer your question, whatever you are expecting from your code is correct but it is not going to produce the expected result. I believe there are other more efficient and correct ways of doing it, but to explain the current behavior:
You are initializing data as content of file text but you are reading from buffer ker_buf in user_buffer instead of file pointer using simple_read_from_buffer(user_buffer, count, position, ker_buf, len);
Similarly you are writing to kern_buf from user_buffer using simple_write_to_buffer(ker_buf, len, position, user_buffer, count);
With the existing code, if you want to achieve what you are trying to do, then you have to copy the string "HELLO WORLD" to kern_buf in init_debug()
Something like:
strscpy(kern_buf, "HELLO WORLD", strlen("HELLO WORLD") + 1);
or in form of complete function:
static int __init init_debug(void)
{
dirret = debugfs_create_dir("dell", NULL);
fileret = debugfs_create_file("text", 0644, dirret, NULL, &fops_debug);
debugfs_create_u64("number", 0644, dirret, &intvalue);
strscpy(kern_buf, "HELLO WORLD", strlen("HELLO WORLD") + 1);
return (0);
}
Edit:
Referred some online materials and found out that the void *data provided to debugfs_create_file() during initialization gets stored in the i_private field and can be later retrieved from the i_private field of the resulting inode structure.
The inode of the respective file can be fetched from struct file *fp which is the first argument of read() or write() operations.
The struct inode is a member of struct file and i_private is a member of struct inode
To fetch void *data provided during file creation via debugfs_create_file() in read() you can do something similar to as shown below:
static ssize_t myreader(struct file *fp, char __user *user_buffer,
size_t count, loff_t *position)
{
struct inode *l_inode = fp->f_inode;
strscpy(user_buffer, (char *)l_inode->i_private, PAGE_SIZE);
...
}
Related
Let's say I have a kernel module named "hello".
For example:
static struct file_operations hello_fops = {
.open = hello_open,
.read = hello_read,
.release = hello_release,
};
static ssize_t hello_read(struct file *f, char *buf, size_t len, loff_t *offset){
// some code here
}
When you read from the /dev/hello character device file, the hello_read function will be called, but where do the function's arguments come from?
I'm reading the De Los Rios book on Linux Kernel Driver development and hit the container_of macro.
I get the fact that if I want to keep context data:
struct myContextData_t {
... myData ...
struct miscdevice misc;
... more myData...
};
I can then:
myContextData = devm_kzalloc(&pdev->dev, sizeof(struct myContextData_t), GFP_KERNEL);
.. set data in misc ..
ret_val = misc_register(&myContextData->misc);
And when a read function gets called:
static ssize_t read(struct file *file, char __user *buff, size_t count, loff_t *ppos)
{
...
// file->private_data points to &myContextData->misc, not to &myContextData, so figure out
// where myContextData is
myContextData = container_of(file->private_data, struct myContextData_t, misc);
...
}
What I'm trying to figure out is why can't I just register my private data when I register my device?
I.E. Why not something like:
struct myContext_t {
... myPrivateData ...
};
struct myContext_t myContext;
struct miscdevice myMiscDevice {
.minor = ...,
.name = "mydevice",
.fops = &myfops,
.context = &myContext,
}
And then:
static ssize_t read(struct file *file, char __user *buff, size_t count, loff_t *ppos)
{
myContext_t myContext = (myContext_t *) file->privateData->context;
}
Rather than having to figure out where my miscdevice data belongs in my structure and 'backtrack'? I realize container_of is a macro evaluated at compile time which will probably boil down to one subtract at runtime. Usually things like that are either deliberate to save space/managed memory entries or relics of prior decisions which weren't futureproofed and ended up propagating to avoid requiring rewrites. It also, I gather, requires a GNU-specific which isn't necessarily available in other compilers, making porting the kernel difficult. I'm just curious what the reasoning was in this case.
I created the device file under /dev folder successfully, but writing to that device file makes kernel to throw following error messages.
kernel:[10090.943733] Internal error: : 1b [#3] PREEMPT SMP ARM
kernel:[10091.049020] Process echo (pid: 3728, stack limit = 0xdc40a218)
kernel:[10091.054880] Stack: (0xdc40be60 to 0xdc40c000)
kernel:[10091.059267] be60: c15491c6 00000022 dc5cb14c bf30430c dc40bedc dc40be88 c075312c c074fe5c
kernel:[10091.067488] be80: c0753018 ffffff04 ffff0a00 c140414c c0d407c8 bf30430c c140414c 40cfbcf3
kernel:[10091.075709] bea0: 00852878 ffffff04 ffff0a00 00040952 c01a7404 c140414c 00852878 00852878
Segmentation fault
I know very basic of Linux Device Drivers
can anyone help me regarding this??
I'm attaching the code for this character device driver
#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/uaccess.h>
#include<linux/device.h>
MODULE_AUTHOR("RUCHA");
MODULE_DESCRIPTION("Character Driver First test");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.0.1");
static int MajorNum;
static struct class* RetValOfClassRegistration = NULL;
static struct device* RetVal = NULL;
static char message[1024];
static int openDev(struct inode * , struct file *);
static int closeDev(struct inode * , struct file *);
static ssize_t readDev(struct file *, char *, size_t, loff_t *);
static ssize_t writeDev(struct file *, const char *, size_t, loff_t *);
static struct file_operations FileOps = {
.owner = THIS_MODULE,
.open = openDev,
.read = readDev,
.write = writeDev,
.release = closeDev,
};
static int registerCharDev(void){
return register_chrdev(0,"MyDev",&FileOps);
}
static int __init Loaded(void){
// registering device
MajorNum = registerCharDev();
if(MajorNum < 0){
printk("Can not register device\n");
return -1;
}
printk("Driver Loaded with %d \n",MajorNum);
// registering device class
RetValOfClassRegistration = class_create(THIS_MODULE,"MyCharacterDriver");
if(RetValOfClassRegistration < 0){
printk("can not register class for driver number : %d\n",MajorNum);
return 0;
}
// register the driver
RetVal = device_create(RetValOfClassRegistration,NULL,MKDEV(MajorNum,0),NULL,"MyDev");
return 0;
}
static void __exit Removed(void){
device_destroy(RetValOfClassRegistration,MKDEV(MajorNum,0));
class_unregister(RetValOfClassRegistration);
class_destroy(RetValOfClassRegistration);
unregister_chrdev(MajorNum,"MyDev");
printk("Driver Removed\n");
}
module_init(Loaded);
module_exit(Removed);
static int openDev(struct inode *inodep , struct file *filep){
printk("Device is now open to read write operations\n");
return 0;
}
static int closeDev(struct inode *inodep , struct file *filep){
printk("Device Closed\n");
return 0;
}
static ssize_t readDev(struct file *filep, char *c, size_t v, loff_t *lp){
printk("Read From the device\n");
return 0;
}
static ssize_t writeDev(struct file *file, const char __user *buf, size_t count, loff_t *offset)
{
sprintf(message, "%s(%zu letters)", buf, len);
return 0;
}
and the user input is
echo '1' > /dev/MyDev
You can't access a user data pointer (buf) directly. You need to use copy_from_user to copy the data into kernel memory first. Also, use snprintf instead of sprintf to avoid buffer overflows.
Also, compile with debugging enabled, especially CONFIG_DEBUG_INFO, to get more helpful error messages in the kernel log.
I want to set a jprobe hook on do_execve to catch every executed program.
My code is working on <= 3.2 linux kernel (debian). This is my output on linux kernel 3.2:
[ 628.534037] registered: do_execve, ret: 0
[ 723.995797] execve: /usr/bin/vi
[ 726.807025] execve: /bin/dmesg
on 4.1 kernel I the same result (everything is registered) but there is no "execve":
[ 8621.430568] registered: do_execve, ret: 0
And this is my code:
static struct jprobe jprobe_hooks[] = {
{
.entry = jdo_execve,
.kp = { .symbol_name = "do_execve" }
}};
static long jdo_execve(const char *filename, const char __user *const __user *argv, const char __user *const __user *envp, struct pt_regs *regs)
{
printk(KERN_INFO "execve: %s", filename );
}
//
// registration
//
int ret, x, reg_error;
reg_error = 0;
for (x = 0; x < sizeof(jprobe_hooks) / sizeof(jprobe_hooks[0]); x++)
{
ret = register_jprobe(&jprobe_hooks[x]);
if (ret < 0)
{
printk(KERN_INFO "register_jprobe failed, returned %d, item: %s\n", ret, jprobe_hooks[x].kp.symbol_name);
reg_error++;
}
else
{
printk(KERN_INFO "registered: %s, ret: %u\n", jprobe_hooks[x].kp.symbol_name, ret);
}
}
When I do a grep on kallsyms I get on 3.2:
grep do_execv /proc/kallsyms
ffffffff81100650 T do_execve
and on 4.2:
grep do_execv /proc/kallsyms
ffffffff811d2950 T do_execve
ffffffff811d2980 T do_execveat
I even tried to change the function (because do_execve prototype has changed) to this:
static int jdo_execve(struct filename *fname, const char __user *const __user *__argv, const char __user *const __user *__envp)
{
int i = 0;
printk(KERN_INFO "execve: %s ", fname->name );
}
and even that didn't help.
I can set hooks on other functions like do_fork or sys_open, but not on do_execve. Why? Anybody has ideas? Why is it not working anymore?
Edit:
I'm also hooking do_execveat:
static int jdo_execveat(int fd, struct filename *fname, const char __user *const __user *__argv, const char __user *const __user *__envp, int flags)
There are several problems that may prevent you jprobe messages:
You don't end print messages printk(KERN_INFO "execve: %s", filename ); with newline, thus you log buffer is not flushed.
API had changed. Now do_execve has filename parameter as struct filename.
Your jprobe code is silly: you don't have module entry, jprobe routine must end with jprobe_return() call and so on. Look at the samples in kernel source tree at "samples/kprobes"
Try to fix it - maybe it will help.
Anyway, I tried it by myself - here is the code - and things is, indeed, looks strange. When I load the module it registers 2 jprobes - one for do_execve, another for do_execveat. But I don't see any messages when I execute programs. BUT what I do see is periodical messages like this:
jprobe: execve: /usr/lib/systemd/systemd-cgroups-agent
It means that jprobe itself works, but not for every execve call.
So I wrote a simple C program to call execve just to be sure it's really called and I still nothing happens execpt systemd-cgroups-agent.
I have an exam question and I can't quite see how to solve it.
A driver that needs the ioctl method to be implemented and tested.
I have to write the ioctl() method, the associated test program as well as the common IOCTL definitions.
The ioctl() method should only handle one command. In this command, I need to transmit a data structure from user space to kernel space.
Below is the structure shown:
struct data
{
char label [10];
int value;
}
The driver must print the IOCTL command data, using printk();
Device name is "/dev/mydevice"
The test program must validate driver mode using an initialized data structure.
Hope there are some that can help
thanks in advance
My suggestion:
static int f_on_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
int ret;
switch (cmd)
{
case PASS_STRUCT:
struct data pass_data;
ret = copy_from_user(&pass_data, arg, sizeof(*pass_data));
if(ret < 0)
{
printk("PASS_STRUCT\n");
return -1;
}
printk(KERN ALERT "Message PASS_STRUCT : %d and %c\n",pass_data.value, pass_data.label);
break;
default:
return ENOTTY;
}
return 0;
}
Definitions:
Common.h
#define SYSLED_IOC_MAGIC 'k'
#define PASS_STRUCT _IOW(SYSLED_IOC_MAGIC, 1, struct data)
The test program:
int main()
{
int fd = open("/dev/mydevice", O_RDWR);
data data_pass;
data_pass.value = 2;
data_pass.label = "hej";
ioctl(fd, PASS_STRUCT, &data_pass);
close(fd);
return 0;
}
Is this completely wrong??