Check /proc file from C kernel module - c

I'd like to share a variable between kernel and user space and I've found that it's possible with procfs.
The kernel module must act in certain way if given value is set. The user space program is responsible for changing this value, but the kernel module must read it when necessary.
I know that I must create the /proc file in the kernel module.
My question is, how to read the file from the kernel module?

Source : linux.die.net/lkmpg/x769.html
/**
* This function is called with the /proc file is written
*
*/
int procfile_write(struct file *file, const char *buffer, unsigned long count,
void *data)
{
/* get buffer size */
procfs_buffer_size = count;
if (procfs_buffer_size > PROCFS_MAX_SIZE ) {
procfs_buffer_size = PROCFS_MAX_SIZE;
}
/* write data to the buffer */
if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {
return -EFAULT;
}
return procfs_buffer_size;
}
To clarify, in Your module whenever user writes to Your file in procfs, this example shows how to handle such write.

In kernel >= 3.10 proc_write is moved to structure file_operations where declaration of write is different, so in newest your solution won't work.
You can implement typical file_operations.write(struct file *, const char __user *, size_t, loff_t *) and reference this to:
struct proc_dir_entry your_proc_dir_entry{
.proc_fops = &your_fops,
}

Related

Linux kernel module : my variable lost its value when it's used in thread function

I am developing a Linux kernel module which read my embedded board button code and use it in order to turn on/off the board led.
When I push button, the module is sending correctly the button code, which is 260, to user-space.
Now, from user-space, I am using the write function in order to re-send this code kernel module :
write(fd, buf_wr, strlen(buf_wr));
Where fd is the file descriptor of my module, and buf_wr is the buffer which will be written to the file.
In kernel space, I am using the write_pid function in this way :
static ssize_t write_pid(struct file *pfile, const char __user *buffer,
size_t length, loff_t *offset)
{
char cod_buf[12];
printk("WE ARE IN WRITE_PID FUNCTION\n");
copy_from_user(cod_buf, buffer, length);
sscanf(cod_buf, "%i", &lcode);
printk("lcode = %i\n", lcode);
return 0;
}
I defined lcode in my kernel module as a global variable :
int lcode = 0;
and I can see that it is receiving the correct button code which is 260.
Now, I created a thread in the module, I want this thread to run some instructions basing on the button code :
int write_in_thread(void *data) {
printk("Under write_in_thread, lcode = %i\n", lcode);
switch (lcode) {
case 260:
//instructions....
//instructions....
//instructions....
break;
default :
//instructions....
break;
}
return 0;
}
The problem here, I can see that, Under write_in_thread, lcode = 0. It's not 260. So the case statement is running the default one which I don't need here.
How can I fix the lcode variable in order to keep it's value in the thread function?
Thank you!

Writing to proc file / give parameter by calling kernel module

I'm supposed to change a configuration parameter of the kernel by using a kernel module. The kernel module should create a proc file and then I should be able to change the parameter by using the cat command, e.g. cat "foobar" > /proc/prompt is supposed to set the parameter to "foobar", where prompt is the name of the proc file that was created in the module.
Furthermore I should be able to initialize the parameter by passing it as an argument when calling the module.
These two articles were basically the only relevant sources that I have found:
http://www.tldp.org/LDP/lkmpg/2.6/html/x769.html for writing to a proc file and http://www.tldp.org/LDP/lkmpg/2.6/html/x323.html for initializing the parameter from the command line.
Now I have a couple of questions, first of all this is the module thus far:
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include "sar_main.h"
#define PROCFS_NAME "sarlkm"
char procfs_buffer[PROCFS_MAX_SIZE];
static unsigned long procfs_buffer_size = 0
struct proc_dir_entry *proc_file_entry;
int procfile_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data){
int ret;
printk(KERN_INFO "procfile_read (/proc/%s) aufgerufen \n", PROCFS_NAME);
if (offset > 0){
ret = 0;
}
else{
memcpy(buffer, procfs_buffer, procfs_buffer_size);
ret = procfs_buffer_size;
}
return ret;
}
int procfile_write(struct file *file, const char *buffer, unsigned long count, void *data){
procfs_buffer_size = count;
if (procfs_buffer_size > PROCFS_MAX_SIZE){
procfs_buffer_size = PROCFS_MAX_SIZE;
}
if ( copy_from_user(procfs_buffer, buffer, procfs_buffer)){
return -EFAULT;
}
return procfs_buffer_size;
}
static int __init sar_init(void)
{
prompt_proc = create_proc_entry(PROCFS_NAME, 0644, NULL);
if (prompt_proc = NULL){
remove_proc_entry(PROCFS_NAME, &proc_root);
printk(KERN_ALERT "Error: Konnte proc file nicht kreieren")
return -ENOMEM;
}
prompt_proc->read_proc = procfile_read;
prompt_proc->write_proc = procfile_write;
printk(KERN_INFO "proc/%s wurde erfolgreich kreiert", PROCFS_NAME);
return 0;
}
static void __exit sar_cleanup(void)
{
remove_proc_entry(PROCFS_NAME, &proc_root);
printk(KERN_INFO "proc/%s gelöscht", PROCFS_NAME);
}
module_init(sar_init);
module_exit(sar_cleanup);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
I think I should say that I don't really understand why the read and write functions are supposed to work when using the cat command.
My main question is where exactly is the configuration parameter stored in the proc file? If I would write "foobar" to the proc file using cat and then use cat proc/prompt to read the parameter, how does the read function actually get the new value of the parameter, i.e. where is "foobar" stored in the procfile?
If I would try to initialize the parameter using a command line argument I would have to use a global variable in which to store the value of the parameter, but then how could I use that global variable in the read function, so that cat proc/prompt actually gives out the value that was given to the module from the command line?
The cat command internally calls the read() system call to read data from a file (see man strace).
read() passes the arguments to the VFS and the VFS finally calls your custom procfile_read() routine with the passed arguments (and some additional ones passed by the VFS code). If you want to know more about this, look at the fs directory in kernel sources, especially file read_write.c.
Your particular reading function copies, if some conditions are met, the parameter value (which is stored in procfs_buffer to answer one of your questions) into the user-supplied buffer allocated by cat, which is called buffer in your particular code. It is the same one as passed by the read() system call like in:
read(proc_fd, userspace_buf, 10); /* userspace_buf is buffer! */
Error checking omitted for clearness's sake.
To pass the value to the proc file you have two options:
Use module_param() and write it to your buffer; can only be done once because the module is only loadable once (or unload/reload it every time you want to change the parameter but that sounds inconvenient)
Invoke write() from userspace (like in cat) and modify the buffer as often as you want to (this is currently used by your code)
BTW, I really think your reading function should check the pointer to the user data, i.e. use copy_to_user(), not memcpy().
For further information, read Linux Device Drivers. There's only an old edition available at the moment but an updated one is being written.
you can treat xxx_write or xxx_read in driver just as a interface implement,
when you call write or read in user space,
the kernel will invoke xxx_write or xxx_read in kernel space.
so you need to store it yourself when write call,
and fetch them back when read call,
in xxx_write xxx_read

How to get the "file name" from struct file* in the kernel?

I want to know on what file in /sys/* the functionstatic ssize_t
sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos) were called. the question is how to get the file name/path by having struct file *file ?
struct file {
mode_t f_mode;
loff_t f_pos;
unsigned short f_flags;
unsigned short f_count;
unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;
struct file *f_next, *f_prev;
int f_owner; /* pid or -pgrp where SIGIO should be sent */
struct inode * f_inode;
struct file_operations * f_op;
unsigned long f_version;
void *private_data; /* needed for tty driver, and maybe others */
};
EDIT:
I understand there is no one-to-one mapping between inode to a name, but I must know the major/minor/file descriptor and can search for some of the inode's name in the file system.
Actuall you can retrieve the file path used to open the file. In linux struct file represents an opened file and has the path used to open that file associate with the structure. Before 2.6.20 it was a member called f_dentry and from 2.6.20 it is a new member called f_path. You can use function d_path() to retrieve the full path of your file directly.
Refer to the following Linux source code:
http://lxr.free-electrons.com/source/include/linux/fs.h?v=3.10#L763
http://lxr.free-electrons.com/source/fs/dcache.c?v=3.0#L2626
And also answer:
How can I get a filename from a file descriptor inside a kernel module?
In Linux and other Unix-like OSs, a file object can be pointed to by any number of names, and the file object itself has no pointers back to any of them. Names are not a feature of the file, they are just an external index.

Casting to a File Pointer

I'm setting up the FUSE filesystem, and I need to get a file pointer to any open files so that I can encrypt them as they get written. The FUSE system uses a special struct. One of the components of the struct is called fh and is of type uint64_t. When a file is opened, it is captured in an int variable as you can see in the following code:
/* File open operation */
int bb_open(const char *path, struct fuse_file_info *fi)
{
int fd;
fd = open(path, fi->flags);
fi->fh = fd;
return fd;
}
This fi struct is available to me in the write function, and I'm hoping that I can use it to create a file pointer that I can pass to my encryption function. Here is the code for the write function as I have it set up at the moment:
/* Write data to an open file */
int bb_write(const char *path, const char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
char* password;
FILE* fp;
//malloc and instantiate password
fp = (FILE*) fi->fh; //my lame attempt to get a file pointer
return encrypt(<inpFilePtr>, <outFilePtr>, 1, password);
}
Finally, the signature of my encryption function looks like this:
extern int encrypt(FILE* in, FILE* out, int action, char* key_str);
I'd like to take that fi->fh variable and turn it into a file pointer so that I can use it as my input file pointer argument. Since it was originally created by an "open" operation, it seems like there should be a way to do this, but I can't make it work.
Can anyone help? Thanks!
File descriptors and FILE * pointers aren't the same thing. A FILE * pointer is a pointer to an opaque type provided by your C implementation - the APIs that deal with FILE * (fopen, fread, fwrite, fclose, etc.) are part of standard C. File descriptors, on the other hand, are operated on using the POSIX system calls (open, read, write, close, etc.) that are often used to implement the C-level abstractions.
Luckily there are functions that let you get one from the other. In your case, you'll want to use fdopen(3) to get a FILE * from the file descriptor. If you wanted to go the other way, you'd want to look into fileno(3).

How can I get a filename from a file descriptor inside a kernel module?

I need to get the name of a file from a given file descriptor, inside a small linux kernel module that I wrote. I tried the solution given at Getting Filename from file descriptor in C, but for some reason, it prints out garbage values (on using readlink on /proc/self/fd/NNN as mentioned in the solution). How can I do it?
Don't call SYS_readlink - use the same method that procfs does when one of those links is read. Start with the code in proc_pid_readlink() and proc_fd_link() in fs/proc/base.c.
Broadly, given an int fd and a struct files_struct *files from the task you're interested in (which you have taken a reference to), you want to do:
char *tmp;
char *pathname;
struct file *file;
struct path *path;
spin_lock(&files->file_lock);
file = fcheck_files(files, fd);
if (!file) {
spin_unlock(&files->file_lock);
return -ENOENT;
}
path = &file->f_path;
path_get(path);
spin_unlock(&files->file_lock);
tmp = (char *)__get_free_page(GFP_KERNEL);
if (!tmp) {
path_put(path);
return -ENOMEM;
}
pathname = d_path(path, tmp, PAGE_SIZE);
path_put(path);
if (IS_ERR(pathname)) {
free_page((unsigned long)tmp);
return PTR_ERR(pathname);
}
/* do something here with pathname */
free_page((unsigned long)tmp);
If your code is running in process-context (eg. invoked through a syscall) and the file descriptor is from the current process, then you can use current->files for the current task's struct files_struct *.

Resources