uprobe programming on ARM Target - linux-kernel

I want place a uprobe on target ARMV7 Board, i have uprobe_example.ko which is build against kernel 2.6.39.
insmod uprobe_example.ko vaddr=$vaddr pid=$!
Uprobes handles interesting events in the lifetime of the probed
+process, such as fork, clone, exec, and exit.
# insmod uprobe_example.ko pid=1461 vaddr=0x000084ac
[15245.267358] up: Unknown parameterpid'`
I want to Insert this module with the above parameters, it is not allowing.
/*
* Usage: insmod uprobe_example.ko pid=<pid> vaddr=<address> [verbose=0]
* where <pid> identifies the probed process and <address> is the virtual
* address of the probed instruction.
*/
static int pid = 0;
module_param(pid, int, 0);
MODULE_PARM_DESC(pid, “pid”);
static int verbose = 1;
module_param(verbose, int, 0);
MODULE_PARM_DESC(verbose, “verbose”);
static long vaddr = 0;
module_param(vaddr, long, 0);
MODULE_PARM_DESC(vaddr, “vaddr”);
static int nhits;
static struct uprobe usp;
static void uprobe_handler(struct uprobe *u, struct pt_regs *regs)
{
nhits++;
if (verbose)
printk(KERN_INFO “Hit #%d on probepoint at %#lx\n”,
nhits, u->vaddr);
}
int __init init_module(void)
{
int ret;
usp.pid = pid;
usp.vaddr = vaddr;
usp.handler = uprobe_handler;
printk(KERN_INFO “Registering uprobe on pid %d, vaddr %#lx\n”,
usp.pid, usp.vaddr);
ret = register_uprobe(&usp);
if (ret != 0) {
printk(KERN_ERR “register_uprobe() failed, returned %d\n”, ret);
return -1;
}
return 0;
}
void __exit cleanup_module(void)
{
printk(KERN_INFO “Unregistering uprobe on pid %d, vaddr %#lx\n”,
usp.pid, usp.vaddr);
printk(KERN_INFO “Probepoint was hit %d times\n”, nhits);
unregister_uprobe(&usp);
}
Make File
obj-m := uprobe_example.o
KERNELDIR ?= $(DLI_KERNEL)
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) EXTRA_CFLAGS=-I`pwd` modules
#sync.sh up.ko
clean:
rm -f *.o *.ko *.mod.c *.symvers
rm -f trace/*.o arch/*.o

obj-m += uprobe_example.o
KERNELDIR ?= $(DLI_KERNEL)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
This Makefile will work fine, without any errors

Related

Understanding Linux kernel semaphore

My understanding of semaphore is:
count cannot go below 0 : if tried block the task.
count cannot go above the value given during sema_init().
First case is always honoured. However as you can see from below code, I can increase the count of semaphore beyond the given value, I was expecting down_interruptible() get blocked and up() to fail to increment the count.
# uname -r
5.4.0-132-generic
# tree
.
├── Makefile
├── sm_define.c
Makefile:
obj-m := sm_define.o
KVERS := $(shell uname -r)
all:
make -C /lib/modules/$(KVERS)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KVERS)/build M=$(PWD) clean
sm_define.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/semaphore.h>
struct semaphore sem;
static int __init
start_module(void)
{
int ret;
sema_init(&sem, 1); /* Binary semaphore */
up(&sem);
up(&sem);
up(&sem);
printk(KERN_INFO "count %d\n", sem.count);
ret = down_interruptible(&sem);
if (ret) {
printk(KERN_INFO "down_interruptible : failed\n");
return -EINVAL;
}
printk(KERN_INFO "count %d\n", sem.count);
ret = down_interruptible(&sem);
if (ret) {
printk(KERN_INFO "down_interruptible : failed\n");
return -EINVAL;
}
printk(KERN_INFO "count %d\n", sem.count);
ret = down_interruptible(&sem);
if (ret) {
printk(KERN_INFO "down_interruptible : failed\n");
return -EINVAL;
}
printk(KERN_INFO "count %d\n", sem.count);
return 0;
}
static void __exit
end_module(void)
{
printk(KERN_INFO "Module exited.\n");
return;
}
module_init(start_module);
module_exit(end_module);
MODULE_LICENSE("GPL");
Output:
# insmod sm_define.ko
# rmmod sm_define
# dmesg
[ 8492.896319] count 4
[ 8492.896320] count 3
[ 8492.896320] count 2
[ 8492.896320] count 1
[ 8500.225030] Module exited.
#
Why this behaviour? and if it is allowed and can't we say notion of binary / counting semaphore is a myth, its just the self followed rule during code, that "I will never increment the value of semaphore before decrementing it?

Cross-compiling to arm64 against kernel source, does not find header files

I wrote a basic module that implements IOCTL handling. I'm trying to cross compile this module to arm64, against 4.19.114 kernel source. Here is my Makefile:
ARCH=arm64
CROSS_COMPILE=aarch64-linux-gnu-
obj-m := chardev.o
KDIR := linux-4.19.114
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean
Here is my module source:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/uaccess.h>
#define NAME "chardev_roi"
#define MAGIC 'a'
#define READPARAM 'b'
#define WRITEPARAM 'c'
#define IOCTL_READ_ROI _IOR(MAGIC, READPARAM, int64_t*)
#define IOCTL_WRITE_ROI _IOW(MAGIC, WRITEPARAM, int64_t*)
static ssize_t ext_read(struct file *filp, char __user *buf, size_t len, loff_t *off)
{
printk("Reading from driver\n");
return 0;
}
static ssize_t ext_write(struct file *filp, const char __user *buf, size_t len, loff_t *off)
{
printk("Writing to driver...\n");
return 0;
}
static long ext_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
char* _from_user_buffer = NULL;
switch (cmd)
{
case IOCTL_WRITE_ROI:
printk("IOCTL_WRITE_ROI just has benn called\n");
_from_user_buffer = kmalloc(32, GFP_KERNEL);
copy_from_user(_from_user_buffer, (char*) arg, sizeof(_from_user_buffer));
break;
case IOCTL_READ_ROI:
printk("IOCTL_READ_ROI just has been called\n");
copy_to_user((char*) arg, "Hello, World!\n", 14);
break;
}
}
static int init(void)
{
int major_number;
static struct file_operations _fops =
{
.owner = THIS_MODULE,
.read = ext_read,
.write = ext_write,
.unlocked_ioctl = ext_ioctl
};
major_number = register_chrdev(0, NAME, &_fops);
return 0;
}
Running this command: sudo ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -d -C linux-4.19.114 M=$(pwd) modules
Throws this error:
./include/uapi/linux/types.h:5:10: fatal error: asm/types.h: No such file or directory
The kernel configuration is defconfig without any changes. Tried to run make clean && make mrproper but it didn't help.
The problem was that I didn't generate the modules.
Run:
make <args> modules
Will probably solve the problem.

Can't cross-compile simple kernel module

I'm trying to compile following 'Hello World'.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("BOBR");
MODULE_DESCRIPTION("HELLO MODULE");
MODULE_VERSION("0.10");
static char *name = "user";
module_param(name, charp, S_IRUGO);
MODULE_PARM_DESC(name, "The name to display");
static int __init hello_init(void) {
printk(KERN_INFO "HEllo, %s!\n", name);
return 0;
}
static void __exit hello_exit(void) {
printk(KERN_INFO "Goodbye, %s !\n", name);
}
module_init(hello_init);
module_exit(hello_exit);
My Makefile is
ifneq ($(KERNELRELEASE),)
include Kbuild
#KDIR ?= ../repos/linux
else
KDIR ?= /lib/modules/4.9.0-6-amd64/build
default:
$(MAKE) -C $(KDIR) M=$$PWD
clean:
$(MAKE) -C $(KDIR) M=$$PWD clean
endif
I start make as: make ARCH=arm CROSS_COMPILE='ccache arm-eabi-' PATH=/opt/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin:$PATH
I compile on Debian 4.9.0-6-amd64. Target is arm32 4.16.18.
The problem is that I get a module for my host machine (I can insmod it), but the target kernel rejects it as invalid module.
When I try to change the linux path in the Makefile to the target kernel sources, the compilation fails with fatal error: asm/barrier.h: No such file or directory.

"Unknown symbol" shown when 'insmod' module1 calls function declared in module2

I am newbee to linux kernel. Currently I want to have 2 module they can interact with each other. I've tried to call function2 from module2 in module1 by EXPORT_SYMBOL_GPL. When I 'insmod' module1 it tells me function2 is "unknown symbol" to module1. I did export function2 and add -DEXPORT_SYMTAB in Makefile. What else I miss? Any advice great appreciate.
Here's my hello samples
/* *************************************************************************************
* hello-1.c - The simplest kernel module.
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include "hello2.h"
static int __init init_module1(void)
{
printk(KERN_INFO "Hello world 1.\n");
function2();
/*
* A non 0 return means init_module failed; module can't be loaded.
*/
return 0;
}
static void __exit cleanup_module1(void)
{
printk(KERN_INFO "Goodbye world 1.\n");
}
module_init(init_module1);
module_exit(cleanup_module1);
MODULE_DESCRIPTION("Hello1");
MODULE_LICENSE("GPL");
/* *************************************************************************************
* hello-2.c - The simplest kernel module.
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
static void function2 (void)
{
printk(KERN_INFO "Function called in hello2.\n");
}
EXPORT_SYMBOL_GPL(function2);
static int __init init_module2(void)
{
printk(KERN_INFO "Hello world 2.\n");
/*
* A non 0 return means init_module failed; module can't be loaded.
*/
return 0;
}
static void __exit cleanup_module2(void)
{
printk(KERN_INFO "Goodbye world 2.\n");
}
module_init(init_module2);
module_exit(cleanup_module2);
MODULE_DESCRIPTION("Hello2");
MODULE_LICENSE("GPL");
/* *************************************************************************************
* hello-2.h - The simplest kernel module header
*/
extern void function2 (void);
################################################
# Makefile for hello2
PWD := $(shell pwd)
KVERSION := $(shell uname -r)
KDIR := /lib/modules/$(shell uname -r)/build
KERNEL_DIR := /usr/src/linux-headers-$(KVERSION)/
INSTALL_PATH := /lib/modules/$(shell uname -r)/extra
EXTRA_CFLAGS = -DEXPORT_SYMTAB
MODULE_NAME = hello2
obj-m := hello2.o
#.PHONY: all clean insert
.PHONY: all clean
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
rm -rf *.o *.ko *.mod.* .c* .t*
insert:
$(MAKE) INSTALL_MOD_DIR=$(INSTALL_PATH) -C $(KDIR) M=$(PWD) modules_install
In hello-2.c you have:
static void function2 (void)
{
...
}
Please consider making it non-static:
void function2(void)
{
...
}
I found the solution from an old post:
insmod fails with "Unknown symbol in module" for a symbol defined in another module
Turns out 2 modules need to be built at the same time. I built they separately with 2 different Makefile.

kernel programming - Makefile error

i am not getting output for this code. What changes have to make in my Makefile??
code:
#define MODULE
#define LINUX
#define __KERNEL__
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>``
MODULE_LISENCE("GPL");
MODULE_AUTHOR("Peter Jay Salzman");
static u8 (mybyte='A');
static int (myint='i');
MODULE_PARM(mybyte, "b");
MODULE_PARM(myint, "i");
MODULE_PARM_DESC(mybyte, "this cannot do anything\n");
static int __init hello5_init(void)
{
printk("my byte %i\n",mybyte);
printk("my integer %i \n",myint);
}
static void __exit hello5_exit()
{
printk("bye world\n");
}
module_init(hell05_init);
module_exit(helo5_exit);
Makefile:
obj-m += hello5.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
exit:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
.PHONY: all, exit
Error:
/home/kumarmagi/Desktop/amit/hello5/hello5.c:23:24: error: ‘mybyte’ undeclared (first use in this function)
/home/kumarmagi/Desktop/amit/hello5/hello5.c:23:24: note: each undeclared identifier is reported only once for each function it appears in
/home/kumarmagi/Desktop/amit/hello5/hello5.c:24:28: error: ‘myint’ undeclared (first use in this function)
/home/kumarmagi/Desktop/amit/hello5/hello5.c:25:1: warning: no return statement in function returning non-void [-Wreturn-type]
Try to change:
MODULE_PARM(mybyte, "b");
MODULE_PARM(myint, "i");
static int (myint='i');
static u8 (mybyte='A');
to:
module_param(mybyte, short, 0660);
module_param(myint, int, 0660);
static short mybyte='A';
static int myint='i';

Resources