How to access Linux kernel data structures? - linux-kernel

I want to print the information of each process and what that process is doing at runtime. i.e. Which file is read/write by that process continuously.
For this I'm writing a kernel module.
Any one have idea to How to access this information in kernel module or how to access the process table data structures in my kernel module?
pseudo code for task will be like this:
1. get each process from /proc.
2. Access the data structure of that process i.e. process table and all
3. print what that process is doing i.e. which file it is accessing (i.e. reading or writing) at rutime.

Please take a look at this example.
It specifically shows how to create a kernel module which prints the open files of a process (and relies on the task_struct struct gained from the current macro I mentioned in my comment). This can be manipulated to far more complicated things which can be accessed through the process task_struct struct.

There is a macro called for_each_process declared in /include/linux/sched.h
http://lxr.free-electrons.com/source/include/linux/sched.h#L2621
By using this macro, it is possible to traverse all process's task_struct.
http://lxr.free-electrons.com/source/include/linux/sched.h#L1343

Related

Limitations on file append when using in multi-processed environment

My process creates a log file and appends a new line at the end of the file by using a, e.g:
fopen("log.txt", "a");
The order of the writes is not critical, but I need to ensure that fopen always succeeds. My question is, can the call above be executed from multiple processes at the same time on Windows, Linux and macOS without any race-condition?
If not, what is the most common and easy way to ensure I can write to the log file? There is file-lokcing, but also a file-lock (aka log.txt.lock) possible. Could anyone share some insights or resources which go more into detail?
If you do not use any synchronization between processes, you'll highly likely have moment when several processes will try to write to the file and the best you can get is mesh of input strings.
In order to synchronize any work in several processes (multiprocessing module). Use Lock. It will prevent several processes to do some work simultaneously.
It will look something like this:
import multiprocessing
# create lock in main process and "send" it to child processes.
lock = multiprocessing.Lock()
# ...
# in child Process
with lock:
do_some_work()
If you need more detailed example, feel free to ask.
Also you can check example in official docs

how to use get_user to copy data from user space to kernel space

I want to copy an integer variable from user space to kernel space.
Can anyone give me a simple example how to do this?
I came to know that we can use get_user but i am unable to know how..
Check man pages of copy_to_user and copy_from_user.
Write a simple kernel module, with read/write operations, and register and char device for them, something like /dev/sample.
Do an application write/read, on fd opened by this application.
Now you need to implement the mechanism for transferring this data to kernel space and read back whatever returned.
- In write you do a copy_from_user, before this check passed buffer is valid or not.
- In read you do a copy_to_user.
Make sure error conditions are taken care of, and open call implementation should keep track of how many opens are there, if you want to implement multiple open, and this count should be decremented, when application calls a close on opened FD.
Do you follow ?

Is there a reverse operation for the vmsplice() system call in Linux?

The vmsplice system call allows to implement zero-copy-send to a pipe from a set of user-level pages using the 'SPLICE_F_GIFT' flag. My question is whether there is a reverse operation, e.g., can I have a process at the other end of the pipe that does not simply read() or aio_read() the pipe, but instead does an operation that simply maps the piped data into its address space? This would in the end mean the transfer (move) of a memory mapping from the sender to the receiver process without any copying. Is this possible?
Edit: My use case looks as follows. I have two processes A and B. A generates data (>megabytes) and wants to pass it to B for further processing and then terminates. I'd like to avoid copying and just tell the kernel 'Look I have these pages here and don't need them anymore. Please attach them to B's address space and be done with it.'.
Simple shared-memory does not work for me, because the memory sent by A may be anywhere in its address space unless I restrict A to use a specific memory allocator that works on shared memory or temp files, which I'd like to avoid.
I think that you are looking for process_vm_readv and process_vm_writev.
These system calls transfer data between the address space of the
calling process ("the local process") and the process
identified by pid ("the remote process"). The data moves directly
between the address spaces of the two processes, without passing
through kernel space.
See the man page for details.
nope there is no reverse of vmsplice operation, there is a project going on now for putting DBUS in kernel you might want to take a look at it. I too have the same requirement and was investigating this whole vmsplice thing.

Appending data to a file from the Linux Kernel

I'm trying gather measurements of cycle counts for a particular sys call (sys_clone) in the linux kernel. That said, my process won't be the only one calling it and I can't know my pid ahead of time; so I'll have to record every invocation of it for every pid.
The problem that I've got is that the only ways I can figure out how to output this data (debugfs, sysfs, procfs) involve statically sized buffers, which will be quickly overwritten with irrelevant data from other processes calling sys_clone.
So, does anyone know how to append an arbitrary number of lines to a user space accessible file in linux?
You can take the printk()/klogd approach, and use a circular buffer that is exported via /proc. A user-space process blocks on reading your /proc file, and once it reads something that is removed from the buffer. In fact, you could take a look whether klogd/syslogd can be modified to also read your /proc file, thus you wouldn't need to implement the userspace part.
If you are good with something simpler, just printk() your information in a normalized form with some prefix, and then just filter it out from your syslog using this prefix.
There are a few more possibilities (e.g. using netlink to send messages to userspace), but writing to a file from the kernel is not something I'd recommend.
You could stash the counts in the right task_struct, and make it visible through a per-process file in /proc/<pid>/.

Saving information in the IO System

I need to write a kernel module that simulate a "multicaster" Using the /proc file system.
Basically it need to support the following scenarios:
1) allow one write access to the /proc file and many read accesses to the /proc file.
2) The module should have a buffer of the contents last successful write.
Each write should be matched by a read from all reader.
Consider scenario 2, a writer wrote something and there are two readers (A and B), A read the content of the buffer, and then A tried to read again, in this case it should go into a wait_queue and wait for the next message, it should not get the same buffer again.
I need to keep a map of all the pid's that already read the current buffer, and in case they try to read again and the buffer was not changed, they should be blocked until there is a new buffer. I'm trying to figure it there is a way i can save that info without a map.
I heard there are some redundant fields inside the I/O system the I can use to flag a process if it already read the current buffer.
Can someone give me a tip where should i look for that field ? how can i save info on the current process without keeping a "map" of pid's and buffers ?
Thanks!
Don't try and keep it based on the PID - that's simply the wrong level of abstraction.
Each time the file is opened there will be a new struct file created that references that instance of the open file. Store the information (the most recent buffer that was read by a given struct file) within the struct file itself.
You can use the private_data pointer within struct file to store the information you need. That's what it's there for.

Resources