I am trying to implement a kernel module, which can access the task_struct of a user process, whose Process ID is already known to me. I am using find_get_pid and pid_task to get the task_struct of the process:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/pid.h>
#include <linux/pid_namespace.h>
int init_module( void )
{
//Declaring the variables
int p_id = 6980; //6980 is the process ID of my user process
struct pid *pid_struct;
struct task_struct *task;
// Trying to access the variables of the p_id
pid_struct = find_get_pid(p_id);
task = pid_task(pid_struct, PIDTYPE_PID);
//Printing the info from the task_struct
printk( KERN_INFO "*** [%d]\n",task->pid);
return 0;
}
void cleanup_module( void )
{
return;
}
It is getting compiled successfully and I am getting *.ko file, but when I am trying to insert it in the kernel, it is giving me an error:
insmod: error inserting 'main.ko': -1 Unknown symbol in module
Dmesg is giving me the following output:
main: Unknown symbol find_get_pid (err 0)
I dont know how to proceed, it would be really appreciated if anyone can help me.
Check carefully what the functions you want to use are called.
Also remember that much of what is "core kernel" (that presumably includes frob_task_by_pid_hardand its ilk) is GPL-only, so unless you declare your module's licence as GPL you won't go anywhere. Also be so kind to fill in the other boilerplate data on the module: MODULE_AUTHOR, MODULE_DESCRIPTION, MODULE_LICENSE at least.
There could be another reason for failure while loading kernel module like if it shows error as "insmod :ERROR: .ko operation not permitted". your kernel is booting with secure boot option on latest PC which must be disabled to avoid failure in loading/inserting a kernel module.this can be done by using below commands.
sudo apt install mokutil
sudo mokutil --disable-validation
or you can search for How to disable secure boot option for your specific OS.
Related
Since the RPL border router example works as either a Cooja mote or a native mote, I thought using the SLIP code in /services/rpl-border-router/native might work. I made a copy of hello-world. I edited hello-world.c to read
#include "contiki.h"
#include "services/rpl-border-router/native/border-router.h"
#include <stdio.h> /* For printf() */
extern int contiki_argc;
extern char **contiki_argv;
/*---------------------------------------------------------------------------*/
PROCESS(hello_world_process, "Hello world process");
AUTOSTART_PROCESSES(&hello_world_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(hello_world_process, ev, data)
{
static struct etimer timer;
PROCESS_BEGIN();
/* Setup a periodic timer that expires after 10 seconds. */
etimer_set(&timer, CLOCK_SECOND * 10);
slip_config_handle_arguments(contiki_argc, contiki_argv);
slip_init();
while(1) {
printf("Hello, world\n");
/* Wait for the periodic timer to expire and then restart the timer. */
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
etimer_reset(&timer);
}
PROCESS_END();
}
And edited the makefile:
CONTIKI_PROJECT = hello-world
all: $(CONTIKI_PROJECT)
CONTIKI = ../..
include $(CONTIKI)/Makefile.dir-variables
MODULES += $(CONTIKI_NG_SERVICES_DIR)/rpl-border-router
include $(CONTIKI)/Makefile.include
This inclusion of rpl-border-router module was done because I was getting undefined reference to ‘slip_init()’... and undefined reference to ‘slip_config_handle_arguments(contiki_argc, contiki_argv);’... errors when compiling, despite the #include "services/rpl-border-router/native/border-router.h" line in hello-world.c. This does appear to be the right header to include for declarations of these functions, but if I am mistaken please say so.
From the folder where the edited hello-world code resides, I did make distclean, and then make TARGET=native. If I run this edited hello-world with
sudo ./hello-world.native fd00::3 -s ttyS0
it looks like it is starting up, but I see:
…[INFO: Native ] Added global IPv6 address fd00::302:304:506:708
********SLIP started on ``/dev/ttyS0''
Hello, world
[INFO: BR ] RPL-Border router started
********SLIP started on ``/dev/ttyS0''
opened tun device ``/dev/tun0''
So it is trying to start up the border router as well as opening the SLIP interface, and just below the ifconfig tun0 output (which looks fine) I see
…hello-world.native: serial_input: read: Success
ifconfig tun0 down
netstat -nr | awk '{ if ($2 == "tun0") print "route delete -net "$1; }' | sh
So, it seems I need to do something to stop from starting the border router module. I have seen that there are 'slip.c' and 'slip.h' in os/dev/, used in the slip-radio example but the declaration of 'slip_arch_init()' in slip.h without a definition of slip_arch_init() in slip.c has me confused, and motivated me to use 'slip_init()' from the /services/rpl-border-router/native folder, since in there I can see a pretty normal bit of code opening up a serial interface.
I have done a lot of google searching and searched through several of the more complex examples for something similar to what I am trying to do, but haven’t found anything that seems very close. If there is something ready made then or course that would be the greatest help, but I am sure it must be obvious that my understanding of Make and file interrelations is nowhere near where it needs to be.
Just to be clear, my goal at the moment is to get a SLIP interface up and running on the remote VM so that I can get a ping6 response on the VM with the border router. I will worry about writing the callback once I have some baseline connectivity. Maybe this is a misunderstanding on my part as well.
Here my basic kernel module code.
#include <linux/kernel.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int test_bug_init(void)
{
printk(KERN_INFO"%s: In init\n", __func__);
BUG();
return 0;
}
static void test_bug_exit(void)
{
printk(KERN_INFO"%s: In exit\n", __func__);
}
module_init(test_bug_init);
module_exit(test_bug_exit);
When I load this module it was successfully loaded but, while unloading time gets the message like "Module in use".
So, why we can't unload the module after BUG() call? Is there another way to unload the module?
In kernel sources you can see that BUG() code eventually invokes unreachable() macro:
# define unreachable() do { } while (1)
Hence your init function test_bug_init() is in use because of infinite loop in it - it cannot return. Verify this by adding something like
//...
BUG();
printk(KERN_INFO "%s: After BUG()\n", __func__);
So you won't see this print in log.
Read also: BUG() FAQ
Is there another way to unload the module?
You can't unload it, because it is 'in use' and you can't make it not in use somehow (can't stop using it). Just reboot.
I was referring:
http://www-users.cs.umn.edu/~boutcher/kprobes/kprobes.txt.html to understand kprobe. I used kprobe_example.c as given in the doc.
I compiled it using the makefile (code taken from the same document)
I got compilation errors because my kernel version is 4.2 and some fields were changed in struct pt_regs. So I replaced eip with ip and eflag with flag in kprobe_example.c which is https://gist.github.com/murlee417/87c2eb43a6afa1954b05404a07813e81. Then I was able to compile it successfully.
Now, as a root user, I did:
#insmod kprobe_example.ko
and I got:
insmod: ERROR: could not insert module kprobe_example.ko: Operation not permitted
My message buffer has:
#dmesg
[ 4537.478408] Couldn't find do_fork to plant kprobe
Please help me to resolve this error and make insmod work.
In x86 do_fork() is known as sys_fork(), so change the code as below
/* For each probe you need to allocate a kprobe structure */
static struct kprobe kp = {
//.symbol_name = "do_fork",
.symbol_name = "sys_fork",
};
I'm having trouble getting my kernel messages to update. I think I may have corrupted my kernel since the KERN ALERT messages do not seem to be updating.
I called "dmesg" command and this is what was displayed:
Jan 20 18:18:59 cu-cs-vm kernel: [29194.126766] hello world
But after updating the helloworld.c:
#include <linux/kernel.h>
#include <linux/linkage.h>
asmlinkage long sys_helloworld(void)
{
printk(KERN_ALERT "Why isn't this working now???");
return 0;
}
It still prints:
Jan 20 18:35:25 cu-cs-vm kernel: [30178.146268] hello world
This is my script for testing it:
#include <unistd.h>
#include <stdio.h>
int main(){
int id;
id = syscall(318);
printf("should print out zero: %d\n", id);
return 0;
}
printf does print 0 and not -1, which is good, but why isn't the kernel message updating from "hello world" to "Why isn't this working now???" I have recompiled. If anyone has any ideas, I would appreciate it if you can share it with me. Thanks!
You had it working, so your code isn't the problem, the problem is either your kernal installation or your versioning. insmod wont overwrite it if the version isn't newer. Fully remove the old install (rmmod) before installing the new one (insmod) or bump the version.
http://linux.die.net/man/8/rmmod
http://linux.die.net/man/8/insmod
Even the man pages suggest using modprobe instead. Maybe you should give it a try, its pretty easy.
http://linux.die.net/man/8/modprobe
Of course with modprobe you can simply give it a --force to ignore a lot of the version checking. But, what you need is the -v option so you can look at the errors about why the module is rejected.
The system may also need a reboot if the kernel is already loaded/cached.
I am working on a linux kernel module which would take care of all the processes that are running for a specific task. Is it possible to know if the certain process named 'X' is still running or not and whats its current state???
well the code is ready.. you can try this..
#include<linux/init.h>
#include<linux/module.h>
#include<linux/sched.h>
MODULE_LICENSE("GPL");
static int info_init(void)
{
struct task_struct *iTask;
for_each_process(iTask) {
printk(KERN_INFO "Process Info \nName: %s\nState:%ld\n",iTask->comm, iTask->state);
}
return 0;
}
static void info_exit(void)
{
printk(KERN_INFO "Tata Bye-bye from Anshul");
}
module_init(info_init);
module_exit(info_exit);
~
After executing it run a
dmesg
command and you can see all the process namess and their states.
Every Task in Linux is being represented by a structure (PCB/TCB) i.e. process/task control block. This is implemented as struct task_struct. It contains all the information about a process. All the PCBs are arranged in a link list and you can traverse through it and extract necessary information.
Inside your module you can initiate a kernel thread as a helper to do this work for you.