I'm quiet new to module coding and I need to run some calculation that uses the GMP library in a module.
So the first question: is it generally possible to run GMP in kernel?
For testing, I wrote this Module:
#include <linux/init.h>
#include <linux/module.h>
#include <gmp.h>
int hallo_init(void)
{
mpz_t testFactor;
mpz_init( testFactor, NULL);
mpz_set_str(testFactor, "19", 10);
int length = (int) mpz_sizeinbase(testFactor,2);
printk(KERN_ALERT "That is testFactor: %x \n",length);
return 0;
}
void hallo_exit(void)
{
printk(KERN_ALERT "exit \n");
}
module_init(hallo_init);
module_exit(hallo_exit);
I run it with the following command:
sudo make -C /lib/modules/$(uname -r)/build M=$PWD modules -lgmp
The makefile consists of
obj-m := gmpFile.o
I also tried to use the -lgmp in the makefile:
obj-m := halloGmp.o
ccflags-y := -lgmp
But I always get a Fatal error: gmp.h: No such file or directory
Any suggestions? Would be thankful for help!
I'm not familiar with GMP but it's unlikely that you can dynamically link a library to a kernel module.
The reason is that the kernel is a standalone program and don't know about any system library that you are used (such glib...) and very likely GMP uses those.
The only solution that I can think of is that you do a kernel module that communicate with a program in the userland and link the GMP to the userland part of your application.
Related
I successfully built this trivial LKM with gcc but the resulting binary is of size 70kB.
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int __init LinuxKernelModule_init(void)
{
printk("LinuxKernelModule: Hello, world!\n");
return 0;
}
static void __exit LinuxKernelModule_exit(void)
{
printk("LinuxKernelModule: Goodbye, world!\n");
}
module_init(LinuxKernelModule_init);
module_exit(LinuxKernelModule_exit);
What CFLAGS and make arguments would you suggest to make it smaller?
The standard Linux kernel is compiled in an optimal way already unless it's a debug version or some very specific options are turned on. So the simplest Makefile for an external kernel module which doesn't add any compiler of linker options on top of those used to build the kernel should be sufficient and should produce an optimal kernel module.
For this trivial LKM (let's call it lkm.c) the simplest Makefile below produces a kernel module that is 3986 bytes in size on my system. gcc version is 7.4.0, ldd version is 2.27, the kernel is 4.15.0-66-generic, the distro is Ubuntu.
KERNEL = /lib/modules/$(shell uname -r)/build
obj-m += lkm.o
all:
${MAKE} -C ${KERNEL} M=$(PWD) modules
clean:
${MAKE} -C ${KERNEL} M=$(PWD) clean
Try to just make Makefile with following contents:
obj-m += test.o
and rename your module to test.c in the same directory.
Then make the module:
make -C /usr/src/linux M=`pwd`
and tell us what is the size of your output .ko file.
It is also possible that your .config of the kernel has enabled debugging symbols and it increases size of your module.
I am trying to compile module but get this error.
fatal error: sys/types.h: No such file or directory
compilation terminated.
Here is my module file headers
#include <linux/init.h> // Macros used to mark up functions e.g. __init __exit
#include <linux/module.h> // Core header for loading LKMs into the kernel
#include <linux/device.h> // Header to support the kernel Driver Model
#include <linux/kernel.h> // Contains types, macros, functions for the kernel
#include <linux/fs.h> // Header for the Linux file system support
#include <asm/uaccess.h> // Required for the copy to user function
#include <sys/types.h>
And my Makefile
obj-m = test.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
I have tried to search for this file
find /usr/include -name types.h
Here are results
/usr/include/sys/types.h
/usr/include/libr/sdb/types.h
/usr/include/rpc/types.h
/usr/include/i386-linux-gnu/sys/types.h
/usr/include/i386-linux-gnu/asm/types.h
/usr/include/i386-linux-gnu/bits/types.h
/usr/include/linux/iio/types.h
/usr/include/linux/types.h
/usr/include/x86_64-linux-gnu/sys/types.h
/usr/include/x86_64-linux-gnu/asm/types.h
/usr/include/x86_64-linux-gnu/bits/types.h
/usr/include/asm-generic/types.h
/usr/include/c++/5/parallel/types.h
I tried to set it as #include "/usr/include/sys/types.h"
but got following error
/usr/include/sys/types.h:25:22: fatal error: features.h: No such file or directory
compilation terminated.
I am using Kali Linux(Debian) AMD64 platform
Linux kali 4.5.0-kali1-amd64 #1 SMP Debian 4.5.5-1kali1 (2016-06-06) x86_64 GNU/Linux
What is wrong ? Thanks
SOLVED
Sorry this was my fault, I made a typo in type and tried to include sys/types.h file, but it was not required at all all types are declared in /usr/src/linux-headers-4.5.0-kali1-common/include/linux/types.h in my case. Thanks everyone.
I had a similar error with Linux Mint
fatal error: sys/types.h: No such file or directory
Fixed this problem with:
sudo apt install libc6-dev
I'd suggest looking to see if gcc is looking for header files in the directory where your file is located with the command:
`gcc -print-prog-name=cc1` -v # for c
Sorry this was my fault, I made a typo in type and tried to include sys/types.h file, but it was not required at all all types are declared in /usr/src/linux-headers-4.5.0-kali1-common/include/linux/types.h in my case. Thanks everyone.
You can fix this problem with:
sudo apt-get install libc6-dev-i386
You can just add the types header file to your sources, download from here.
Trying the simplest kernel module from LDD3 without any modification on custom built kernel v4.1.0-rc6 for Beagle Bone board with BusyBox v1.23.0. The code for the module is as follows:
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
The Makefile is:
ARCH := arm
CROSS_COMPILE := arm-cortex_a8-linux-gnueabi-
obj-m := hello.o
all:
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C /path/to/linux/source/tree M=$(PWD) modules
clean:
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C /path/to/linux/source/tree M=$(PWD) clean
The module is compiling and installing on the rootfs just fine. also it is loading:
$ insmod hello.ko
[ 30.692404] Hello, world
But when trying to remove it, I am getting:
$ rmmod hello.ko
Segmentation fault
$modprobe -r hello.ko
Segmentation fault
$ lsmod
hello 813 0 - Live 0xbf000000 (O)
The kernel is compiled with module unloading (both regular and forced) support enabled.
What can be the possible cause of this issue? What is the way to approach the investigation of it?
Update:
As suggested in the comments I have tried including linux/kernel.h, defining the MODULE,LINUX and __KERNEL__ symbols. Added the__init and __exit prefixes to the functions. Removed the static modifiers. Removed the printk lines. The result the same. dmesg shows only the initial greeting. Loading and unloading of the kernel's modules such a gpio_keys or crypto/ccm is working, surprisingly. So the only thing remaining to suspect is the way the module is compiled..
Update 2
Updating the kernel to the freshest snapshot didn't help. Compiled the module with different optimization settings didn't help. Next step, I guess, I am going to modify the BusyBox's rmmod to have some indication of the problem location..
Have a look at these tutorials:
http://www.tldp.org/HOWTO/Module-HOWTO/x839.html
http://www.tldp.org/LDP/lkmpg/2.4/html/x281.htm
Try adding:
#define MODULE
#define LINUX
#define __KERNEL__
#include <linux/kernel.h> /* Needed for KERN_ALERT */
I have managed to work around this problem. Using strace I've found out that the segfault is occurring somewhere when reading the BusyBox specific modules.dep.bb file. This file is used by BusyBox when it is compiled with the "Simplified modutils" option (CONFIG_MODPROBE_SMALL). By disabling the option, selecting the utils to be installed and rebuilding BusybBox I've got the module unloading work. I believe the problem root is near the fact the test module is compiled and stored outside the /lib/..../modules directory, so busybox with the simplified modutils is just getting confused.
I'm trying to make loadable kernel module for ARM achitecture. Just for example I'm made simple hello.c
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
static int __init hello_start(void)
{
printk(KERN_INFO "Loading hello module...\n");
return 0;
}
static void __exit hello_end(void)
{
printk(KERN_INFO "Goodbye Mr.\n");
}
module_init(hello_start);
module_exit(hello_end);
And created Makefile
obj-m := hello.o
PWD := $(shell pwd)
ARCH=arm
CROSS_COMPILE_LINARO=/home/cooperok/mk908/gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130125_linux/bin/arm-linux-gnueabihf-
KERNEL_ROCKCHIP=/home/cooperok/mk908/kernel/
default:
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE_LINARO) -C $(KERNEL_ROCKCHIP) M=$(PWD) modules
clean:
make CROSS_COMPILE=$(CROSS_COMPILE_LINARO) -C $(KERNEL_ROCKCHIP) M=$(PWD) clean
Cross compiler and kernel sources are the same on both computers. When I'm running make on first machine compiled hello.ko file is successfully installed with insmod command, but when I'm compiling module on second machine and trying to install that module I'm getting error "insmod: error inserting 'hello.ko': -1 Invalid module format"
As I understand module is compiling with crosscompiler which I'm specified in CROSS_COMPILE (arm-linux-gnueabihf-gcc and others) and only it will make module without any specific libraries installed on computers, is it?
First computer have 64bit OS (Ubuntu 12.04), and second 32bit OS (Linux Mint 12), this is main difference, so make util is different. But is it realy main reason why module correctly compiling only on 64bit OS? If so is it problem in make, or it's really deals with different libraries?
Very new to linux in general and trying to build a loadable module for use in zabbix, which works, but trying to build a simple shell program for testing it. That means this module needs to be loaded dynamically.
Sharable module SNMPmath is built with this:
gcc -shared -o SNMPmath.so $(CFLAGS) -I../../../include -I/usr/include/libxml2 -fPIC SNMPmath.c
That works fine for zabbix.
The test program (TestSO.c) uses
lib_handle = dlopen("./SNMPmath.so", RTLD_NOW);
to load this image dynamically, and when it does, it is missing symbols including init_snmp which come from the net-snmp package which is referenced in the SNMPmath loadable module.
My question is both general and specific. What's the right approach -- is this library called by the loadable module supposed to be forced into the loadable module? Is it supposed to be forced into the test program (despite having no compile-time reference to it)? Or is it supposed to be dynamically loaded, itself, in the loadable module (which seems to contradict what I'm seeing in other examples)?
And in either case, how is the GCC command modified to include net-snmp? I've tried variations of whole-archive, no-as-needed, listing what I think is the library (/usr/lib/x86_64-linux-gnu/libsnmp.a) with various compiler options with no effect (or occasionally errors). Also tried linking to the .so version of that (no effect). So a hint as to the proper GCC command to include the library would be very helpful.
Here's one iteration of attempts at linking the main program:
gcc -rdynamic -o TestSO -I../../../include -I/usr/include/libxml2 TestSO.c -ldl -Wl,--no-as-needed /usr/lib/x86_64-linux-gnu/libsnmp.so
I've found numerous examples of loading modules, but they all load a simple routine that does not itself have undefined symbols that need satisfying.
Recap:
TestSO.c
==> Loads with dlopen SNMPmath.c
==> needs to refer to net-snmp routines like init_snmp
Pointers to examples or explanation welcome, I realize I'm missing something fairly obvious.
EDIT AFTER FIRST COMMENTS TO INCLUDE:
I have it sort of working now, but would appreciate a sanity check if this is correct. I pruned it down so as to show the whole code. Here is the code to produce the SO:
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <string.h>
int zbx_module_SNMPmath_avg(int i, int j)
{
init_snmp("snmpapp"); // initialize SNMP library
return 1;
}
Here is how it is compiled (note slight name change):
CFLAGS=-I. `net-snmp-config --cflags`
SNMPmath_small: SNMPmath_small.c
gcc -shared -o SNMPmath.so $(CFLAGS) -I../../../include -I/usr/include/libxml2 -fPIC SNMPmath_small.c -Wl,--no-as-needed,/usr/lib/x86_64-linux-gnu/libsnmp.so
Then here is the main program:
#include <stdio.h>
#include <dlfcn.h>
#include <dlfcn.h>
#include <string.h>
int main(int argc, char **argv)
{
void *lib_handle;
int(*fn)(int req, int ret);
int x;
char *error;
lib_handle = dlopen("./SNMPmath.so", RTLD_NOW);
if (!lib_handle)
{
fprintf(stderr, "Error on open - %s\n", dlerror());
exit(1);
}
else
fprintf(stderr,"Successfully loaded module\n");
fn = dlsym(lib_handle, "zbx_module_SNMPmath_avg");
if ((error = dlerror()) != NULL)
{
fprintf(stderr, "Error on dlsym %s\n", error);
exit(1);
}
else fprintf(stderr,"Successfully called dlsym\n");
// testing
int req, ret;
req=1;
ret=1;
x=(*fn)(req, ret);
printf("Valx=%i\n",x);
dlclose(lib_handle);
return 0;
}
And finally this is built with:
TestSO: TestSO.c
gcc -rdynamic -o TestSO -I../../../include -I/usr/include/libxml2 TestSO.c -ldl
This now will run as expected. I found that linking against the netsnmp library's so file when building my so seemed to work.
But is this the correct sequence? And/or the preferred sequence?
Ps. Off to read the paper in the first proposed answer.
Pointer to explanation: Drepper's paper: Howto write shared libraries
But we need more source code (and the commands used to compile it), and the real error messages (e.g. as given by dlerror() after dlopen call) to help more.
(See also this answer)
You might want to add some libraries like -lsomething (I don't know which, you probably do know!) to your command gcc -shared which is building SNMPmath.so .... You don't want to link a static library like libsnmp.a to it (you should link shared libraries to your SNMPmath.so shared object).