I'm writing a user space program and a kernel space device driver.
Goal: Once an interrupt occurs, user space program needs to do something quickly.
My naive method: User space program uses ioctl to call wait_event_interruptible(), kernel ISR calls wake_up_interruptible() to wake up user space program. It turns out that it takes too much time from interrupt to user space.
Is there any better way?
Thanks!
There is a similar question asked here:
Notify gpio interrupt to user space from a kernel module
Please check above question. However, i can provide my approach which i suggested there as well.
You can send a signal to user space thread from kernel API, which can help u run non-blocking:
send_sig(int sig, struct task_struct *p, int priv);
You need to be aware of pid of user thread in Kernel. You can over come this by writing pid of user process via /proc and then kernel reading the pid. With this arrangement, when there is an interrupt, kernel can send signal to user thread. In case your process restarts or gets killed, you will have to update the pid via proc. Just for status notification you can use this method; however if you like to transfer data along with status than Netlink or char driver mechanism is good way.
Related
One way to block a malicious process is tracing its behavior in kernel space eBPF program and then just simply kill it in user space program, but there is latency before user space program receiving data from kernel space. I wonder if there is a way to kill a malicious process in kernel space eBPF program as it is more efficient.
The BPF helper function bpf_send_signal() can be used to send a signal to the process of the monitored task, see its documentation:
long bpf_send_signal(u32 sig)
Description
Send signal sig to the process of the current task.
The signal may be delivered to any of this
process's threads.
Return
0 on success or successfully queued.
-EBUSY if work queue under nmi is full.
-EINVAL if sig is invalid.
-EPERM if no permission to send the sig.
-EAGAIN if bpf program can try again.
The signal to pass can be SIGKILL, for example.
Some projects use it already: Tetragon, a tool based on eBPF for “security observability and runtime enforcement”, can call it to terminate processes.
This helper is available starting with Linux 5.3.
If I write kernel code to handle interrupts, how can I inform user space code?
And how could user space code handle it? By a blocking read()?
Then the user space code can do nothing if the interrupt hasn't happened?
Or maybe a multi-threads user space code can be made: one thread is for the blocking read(), another thread can do things such as GUI update, etc, right?
How Linux scheduler identifies which process is from kernel space and which process is from user space?
Suppose I installed an application in the Linux. I started the application. Simultaneously there are other kernel space processes into the ready queue. Now how can the Linux scheduler identify that the which queued process is from kernel space and which one is from user space..?
I'm not expert but I started reading the kernel source 2 days ago and when it comes to processes you can almost always find all the data that you need from one struct. The struct is called task_struct and is defined in include/linux/sched.h file of the kernel source tree.
You can look it up here: https://github.com/torvalds/linux/blob/master/include/linux/sched.h#L1274
From what I understand, although I might be wrong, the kernel has no idea if the process/thread that it schedules is a user process or a kernel thread.
According to Robert Love's book on the Linux Kernel, the main difference from the system's point of view between a user process and a kernel thread is that kernel threads do not have an address space. Their mm pointer in their task_struct is NULL.
So from the above, I assume that if you really want to know whether a task is a kernel thread you could check this structure.
I have a Linux driver which allows userspace applications to register some application specific data which would effect how the driver functions. Typically, the userspace application would deregister its information before exiting. If the application were to crash however, then there would be no way to deregister the information, and there would be a memory leak. I'm wondering if it's possible to detect from kernel space, if a userspace application has exited unexpectedly.
struct task_struct *task = current; would give you the pointer to the current task. task->comm and task->pid will give the name and PID for the process. When the userspace application calls your driver for registering its data (Assuming you are using a character device interface, write) you can add the pid to the list. Run a timer and whenever the timer expires, in the callback, initialize the task pointer again to current and go through the circular linked list by task = task->next until task becomes current again and see if all the pids in the list still exist in the kernel task list. If you find anything missing,
Along with the method in my previous answer, instead of polling, you can use find_task_by_vpid(pid); to get the task structure for the task directly. Comment says this must be called under rcu_read_lock().
Another option would be to implement a generic netlink socket communication between application and kernel module. Here the application will have to respond to the kernel messages. That would be more work compared to the first approach where if find_task_by_vpid() returns NULL, you can conclude your userspace process is dead.
Can a user thread directly enter kernel w/o a kernel thread being called ? I mean, a user space enter kernel via an exception, w/o calling any kernel thread, but run in kernel code. Thanks !
Yes, they can. User threads enter the kernel all the time for system calls, interrupts and exceptions. While the kernel is handling one of these it is running in kernel mode in the context of the user thread (and uses that thread's kernel stack).
In fact, a "kernel thread" is defined as a scheduled task that never exits the kernel.