kernel module compilation error of macro for_each_process - c

I am trying to compile a kernel module program to list tasks linearly, such that if you run the command ps -el should have the same or similar output. my textbook says:
"In the Linux kernel, the for_each_process() macro easily allows iteration over all current tasks in the system:
#include <linux/sched.h>
struct task_struct *task;
for_each_process(task) {
/* on each iteration task points to the next task */
}
so I have the following:
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
int tasks_lister_linear_init(void)
{
printk(KERN_INFO "Loading module...\n");
struct task_struct *task;
for_each_process(task)
{
printk(KERN_INFO "pid: %d | pname: %s | state: %ld\n", task->pid, task-
>comm, task->state);
}
printk(KERN_INFO "Module loaded.\n");
return 0;
}
void tasks_lister_linear_exit(void)
{
printk(KERN_INFO "Module removed.\n");
}
module_init(tasks_lister_linear_init);
module_exit(tasks_lister_linear_exit);
and when I go to make, I get an error saying
implicit declaration of function ‘for_each_process’; did you mean ‘for_each_node’?
expected ‘;’ before ‘{’ token
| for_each_process(task) {
| ^~
| ;
yet every call to this I have seen has not had a semicolon following. any advice on these errors would be greatly appreciated

You are probably using a newer kernel version. In later kernels, the macro for_each_process has been moved to the
#include <linux/sched/signal.h>
instead of
#include <linux/sched.h>

Related

local_irq_disable does not work as expected

local_irq_disable()is used to disable all interrupts on the current processor
i wrote a basic code to test local_irq_disable().
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irqflags.h>
static int __init my_init(void)
{
pr_info("module is loaded on processor:%d\n", smp_processor_id());
local_irq_disable();
ssleep(10);
local_irq_enable();
return 0;
}
static void __exit my_exit(void)
{
}
MODULE_LICENSE("GPL");
module_init(my_init);
module_exit(my_exit);
When i load this on my system, it prints the following message:
[10478.930188] module is loaded on processor:5
And when i run "watch -d -n 0.2 'cat /proc/interrupts'", it still shows interrupts on those processor, what i am missing here?

Kernel module is removed successfully although warning message 'not found"

Yesterday I installed a very simple kernel module in my embedded Linux system. "hello.ko".
When I install this module to our system, it's normally:
#insmod hello.ko
Initing kernel module
#
#lsmod
hello 638 0 - Live 0xf628f000
But when I remove this kernel module, It can be removed normally but rmmod notice 'hello.ko' not found
# rmmod hello
Cleaning kernel module
rmmod: module 'hello' not found
#lsmod <------------------- already be removed
#
# uname -a
# Linux SWITCH 2.6.32 #8 Thu Jun 23 20:34:48 KST 2016 ppc GNU/Linux
It's very strange. Could anyone explain for me why 'hello.ko' is removed but there's log 'rmmod module not found'?
The following are source code of hello.ko
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/config.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/string.h>
int init_module(void)
{
printk (KERN_EMERG "Initing kernel module\n");
return 0;
}
void cleanup_module(void)
{
printk (KERN_EMERG "Cleaning kernel module\n");
}
MODULE_DESCRIPTION ("Kernel function replacement module");
MODULE_AUTHOR ("DASAN Networks Inc.");
MODULE_LICENSE ("GPL");
You need to add few things in my opinion __init and __exit macros and module_init and module_exit macros, try with:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/string.h>
static int __init init_example(void)
{
printk (KERN_EMERG "Initing kernel module\n");
return 0;
}
static void __exit cleanup_example(void)
{
printk (KERN_EMERG "Cleaning kernel module\n");
}
module_init(init_example);
module_exit(cleanup_example);
MODULE_DESCRIPTION ("Kernel function replacement module");
MODULE_AUTHOR ("DASAN Networks Inc.");
MODULE_LICENSE ("GPL");

Naming a variable `current` in a kernel module leads to "function declaration isn’t a prototype" error

I'm learning to write kernel modules for linux as a beginner. What I'm trying to do is to write every task and its child process into the kernel log using DFS algorithm. But when I compile the code using Makefile, it shows the above error:
function declaration isn’t a prototype [-Werror=strict-prototypes]
struct task_struct *current;
It points out the task_struct keyword at the function DFS.
Here's my code:
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/sched.h>
# include <linux/list.h>
void DFS (struct task_struct *task)
{
struct task_struct *current;
struct list_head *list;
list_for_each (list, &task->children)
{
current = list_entry(list, struct task_struct, sibling);
printk(KERN_INFO "%d\t%d\t%s \n", (int)current->state, current->pid, current->comm);
if (current != NULL)
{
DFS(current);
}
}
}
int DFS_init(void)
{
printk(KERN_INFO "Loading the Second Module...\n");
printk(KERN_INFO "State\tPID\tName\n");
DFS(&init_task);
return 0;
}
void DFS_exit(void)
{
printk(KERN_INFO "Removing the Second Module...\n");
}
Anyone knows how to fix this ??
The kernel has a macro called current which is pointing to users currently executing process. As this book states,
The current pointer refers to the user process currently executing. During the execution of a system call, such as open or read, the current process is the one that invoked the call.
In other words, as #GilHamilton mentioned in the comments, current is #defined to the function get_current() in the kernel. Using current as a variable name will give a compile-time error!

warning: passing argument 1 from incompatible pointer type

I'm doing some work with structs for a kernel module on Linux with c, and I can't seem to get a pointer to an object within a struct. My code is as follows:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
struct list_head *list;
/* performs a depth-first traversal of the list of tasks in the system. */
void print_task_info(struct task_struct *task) {
for_each_process(task){
printk("%s, %d, %d \n", task->comm, (int)task->state, task->pid);
}
list_for_each(list, &init_task.children){
print_task_info(&task->children);
task = list_entry(list, struct task_struct, sibling);
}
}
The problem arises when I make a recursive call to print_task_info(). I've tried adding a lot of different things, using the unary *, having no symbols, casting, none of it worked for me. Do you have any advice? I searched but I can't find any resources about this in any C language documentation about structs, how to make this a pointer, so I came here when I ran out of other options.

Cannot accessing the vm_list and mm_struct from a kernel module

I am trying to access the vm_list and the mm_struct from a kernel module, but for some reason, my output is always null, even though I have up to 3 VMs running.
In case it matters, the whole thing is running inside a VM because I don't want to mess with the real kernel.
#undef __KERNEL__
#define __KERNEL__
#undef MODULE
#define MODULE
// Linux Kernel/LKM headers: module.h is needed by all modules and kernel.h is needed for KERN_INFO.
#include <linux/module.h> // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/kallsyms.h>
#include <linux/string.h>
#include <linux/kvm.h>
#include <linux/kvm_host.h>
#include <linux/mm_types.h>
#include <linux/slab.h>
#include <linux/async.h>
MODULE_LICENSE("GPL");
struct list_head *vms_list;
struct mm_struct *mms_struct;
raw_spinlock_t *vm_lock;
int init_module(void)
{
struct list_head *itr;
struct kvm* kvm;
int i;
printk(KERN_INFO "Hello world!\n");
vms_list = (struct list_head*)kallsyms_lookup_name("vm_list");
mms_struct = (struct list_head*)kallsyms_lookup_name("mm_struct");
vm_lock =(raw_spinlock_t*)kallsyms_lookup_name("kvm_lock");
if(!mms_struct && !vms_list){
printk(KERN_INFO "vms_list and mms_struct are %p, %p\n", vms_list, mms_struct);
return 0; <--- This line gets executed every time.
}
printk(KERN_INFO "here 2\n");
raw_spin_lock(vm_lock);
list_for_each_entry(kvm, vms_list, vm_list)
{
printk(KERN_INFO "%p\n", kvm);
}
raw_spin_unlock(vm_lock);
itr = 0;
// printk(KERN_INFO "%p\n", itr);
return 0;
};
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world!\n");
};
References:
vm_list -> list_head
mm_struct
Answering my own question.
In short: VirtualBox (which runs the outer guest), does not support nested virtualization (see feature request).
I have found this out by simply doing a cat /proc/cpuinfo | grep vmx and getting an empty output.
Hope this will someday help someone.
Try using qemu nested virtualization on a linux host. (a dream within a dream)
--------------------
L2 | VM_1 | VM_2 | ... |
--------------------
L1 | guest hypervisor |
---------------------
L0 | host hypvevisor |
--------------------
You need to enable the VMX instructions into the guest hypervisor:
enable nested virtualization when inserting the kvm module:
modprobe kvm_intel nested=1
enable the vmx cpu flag when starting qemu in L0
qemu .... -cpu qemu64,+vmx -enable-kvm
Now when you start your VM's from L1, you should be able to see a non-null vm_list.

Resources