I have a kernel module that checks the IP address of a requests and adds it to a "blacklist" variable if the request contains bad data (spam keywords).
The way I declare the blacklist is as follows:
#define blacklist (uint32_t[3]) { \
2071690107, \
168430090, \
4294967295 \
}
I did some initial testing reaching this step (filtering IPv4, printk logs) and must have already blocked an ip address of one of the requests I need to test.
I say this because when I do a make clean, make, and reinsert my module, I automatically see the IP address blocked.
What should happen is the data prints first showing a spam word, then it blocks the IP address, then it will print it is already blocked on any subsequent requests (which I know will follow shortly after).
Mar 16 18:43:33 deadsupra-VirtualBox kernel: [36594.961054] Module insertion completed successfully!
Mar 16 18:43:46 deadsupra-VirtualBox kernel: [36607.186539] ip checking: 127.0.0.1
Mar 16 18:43:46 deadsupra-VirtualBox kernel: [36607.186541] ip is already blacklisted 127.0.0.1
Mar 16 18:43:46 deadsupra-VirtualBox kernel: [36607.186546] ip checking: 127.0.0.1
Mar 16 18:43:46 deadsupra-VirtualBox kernel: [36607.186547] ip is already blacklisted 127.0.0.1
Mar 16 18:43:51 deadsupra-VirtualBox kernel: [36612.190103] ip checking: 127.0.0.1
Mar 16 18:43:51 deadsupra-VirtualBox kernel: [36612.190108] ip is already blacklisted 127.0.0.1
Mar 16 18:43:51 deadsupra-VirtualBox kernel: [36612.190119] ip checking: 127.0.0.1
Mar 16 18:43:51 deadsupra-VirtualBox kernel: [36612.190121] ip is already blacklisted 127.0.0.1
My make file is as follows:
obj-m += wander.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
all:
make -C $(KERNELDIR) -Wno-declaration-after-statement M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
insert:
-sudo rmmod wander
sudo dmesg -C
sudo insmod wander.ko
dmesg
test:
curl "http://www1.udel.edu/registrar/graduation-diplomas/diplomas.html" | grep -i -o -P '.{0,10}university.diploma.{0,20}'
log:
cat /var/log/kern.log
Am I not cleaning my project space properly? I want to refresh my test scenario every time and forget about any ip addresses previously blocked when I rebuild my source code.
I'm thinking that when I clean the module, it removes it but must be keeping the data for some reason.
Related
I am currently trying to develop a simple linux kernel module. It should just log something, its 1:1 copied from the internet.
I have the following files:
lkm_example.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Robert W. Oliver II");
MODULE_DESCRIPTION("A simple example Linux module.");
MODULE_VERSION("0.01");
static int __init lkm_example_init(void) {
printk(KERN_INFO "Hello, World!\n");
return 0;
}
static void __exit lkm_example_exit(void) {
printk(KERN_INFO "Goodbye, World!\n");
}
module_init(lkm_example_init);
module_exit(lkm_example_exit);
Makefile:
obj-m += lkm_example.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
I also did the following:
sudo apt-get install build-essential linux-headers-`uname -r`
For compilation i used:
stbau#kernel-dev-vm:~/src/lkm_example$ sudo make
make -C /lib/modules/5.13.0-39-generic/build M=/home/stbau/src/lkm_example modules
make[1]: Entering directory '/usr/src/linux-headers-5.13.0-39-generic'
CC [M] /home/stbau/src/lkm_example/lkm_example.o
MODPOST /home/stbau/src/lkm_example/Module.symvers
CC [M] /home/stbau/src/lkm_example/lkm_example.mod.o
LD [M] /home/stbau/src/lkm_example/lkm_example.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.13.0-39-generic'
Executing with insmod:
stbau#kernel-dev-vm:~/src/lkm_example$ sudo insmod lkm_example.ko
insmod: ERROR: could not insert module lkm_example.ko: Invalid module format
The dmesg log gives the following error:
[ 49.272618] lkm_example: module verification failed: signature and/or required key missing - tainting kernel
[ 49.272630] module: x86/modules: Skipping invalid relocation target, existing value is nonzero for type 1, loc 0000000054f3f1c5, val ffffffffc0a0a000
I am using the following kernel:
stbau#kernel-dev-vm:~/src/lkm_example$ uname -a
Linux kernel-dev-vm 5.13.0-39-generic #44-Ubuntu SMP Thu Mar 24 15:35:05 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
As you can see in the dmesg log, i only get an error and not the messages i expected. I have no idea what i did wrong/what is missing.
I think the problem is that the module is not signed. I tried signing it using the sign-file but i was not able to generate a private/public key file.
Re-Installing the kernel headers worked for me.
I used the following commands:
sudo apt update && sudo apt upgrade
sudo apt remove --purge linux-headers-*
sudo apt autoremove && sudo apt autoclean
sudo apt install linux-headers-generic
I written simple hello world dynamic module for ubuntu, while inserting it I'm getting an error
insmod: ERROR: could not insert module pcd.ko: Invalid module format
when I check dmesg, I get this
module: x86/modules: Skipping invalid relocation target, existing value is nonzero for type 1, loc 00000000f1750993, val ffffffffc39162ea
I tried to check if version of kernel is same or not but they are same
xxxxxxx#xxxxxxx:~/workspace/ldd/custom_drivers/002pseudo_char_driver$ uname -r
5.13.0-35-generic
xxxxxx#xxxxxxxx:~/workspace/ldd/custom_drivers/002pseudo_char_driver$ modinfo pcd.ko
filename: /home/xxxxxxx/workspace/ldd/custom_drivers/002pseudo_char_driver/pcd.ko
description: A pseudo character driver
author: xxxxxxx
license: GPL
srcversion: 30261074162DBCAE996D8E0
depends:
retpoline: Y
name: pcd
vermagic: 5.13.0-35-generic SMP mod_unload modversions
so what is the problem and how to solve it?
this is Makefile I used
obj-m := pcd.o
ARCH=arm
CROSS_COMPILE=arm-linux-gnueabihf-
KERN_DIR=/home/xxxxxxx/workspace/ldd/source/linux_kernel4.19.94-ti-r42/
HOST_KERN_DIR = /lib/modules/$(shell uname -r)/build/
all:
sudo make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERN_DIR) M=$(shell pwd) modules
clean:
sudo make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERN_DIR) M=$(shell pwd) clean
help:
sudo make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERN_DIR) M=$(shell pwd) help
host:
sudo make -C $(HOST_KERN_DIR) M=$(shell pwd) modules
to compile I entered
make host
result of uname -a
subhash#subhashHP:~/workspace/ldd/custom_drivers/002pseudo_char_driver$ uname -a
Linux subhashHP 5.13.0-35-generic #40~20.04.1-Ubuntu SMP Mon Mar 7 09:18:32 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
I am trying to make use of a library, https://github.com/go-steem/rpc, that makes use of some C code, which references a library.
The C library can be found here, https://github.com/bitcoin-core/secp256k1
I followed the steps to get that installed
$ ./autogen.sh
$ ./configure
$ make
$ ./tests
$ sudo make install # optional
And have this output;
$ sudo make install
Password:
CC src/libsecp256k1_la-secp256k1.lo
CCLD libsecp256k1.la
CC src/tests-tests.o
CCLD tests
CC src/exhaustive_tests-tests_exhaustive.o
CCLD exhaustive_tests
build-aux/install-sh -c -d '/usr/local/lib'
/bin/sh ./libtool --mode=install /usr/bin/install -c libsecp256k1.la '/usr/local/lib'
libtool: install: /usr/bin/install -c .libs/libsecp256k1.0.dylib /usr/local/lib/libsecp256k1.0.dylib
libtool: install: (cd /usr/local/lib && { ln -s -f libsecp256k1.0.dylib libsecp256k1.dylib || { rm -f libsecp256k1.dylib && ln -s libsecp256k1.0.dylib libsecp256k1.dylib; }; })
libtool: install: /usr/bin/install -c .libs/libsecp256k1.lai /usr/local/lib/libsecp256k1.la
libtool: install: /usr/bin/install -c .libs/libsecp256k1.a /usr/local/lib/libsecp256k1.a
libtool: install: chmod 644 /usr/local/lib/libsecp256k1.a
libtool: install: /usr/bin/ranlib /usr/local/lib/libsecp256k1.a
build-aux/install-sh -c -d '/usr/local/include'
/usr/bin/install -c -m 644 include/secp256k1.h '/usr/local/include'
build-aux/install-sh -c -d '/usr/local/lib/pkgconfig'
/usr/bin/install -c -m 644 libsecp256k1.pc '/usr/local/lib/pkgconfig'
I try to run the upvote example from that Go library, go-steem/rpc/examples/upvote/ and get the following output;
$ go run main.go
# github.com/go-steem/rpc/transactions
../../transactions/signing.c:5:10: fatal error: 'secp256k1.h' file not found
Already it feels as though the wheels are falling off...
Please bear with me as I do not develop in C, so I get a bit hack-y.
After much reading, and googling I decide to copy the files from the 'include' directory where I compiled libsecp256k1 into the same directory as the error is originating from.
You can see the files are not there;
$ ls -la ../../transactions/
total 48
drwxr-xr-x 8 shaunmorrow staff 272 May 8 18:09 .
drwxr-xr-x 15 shaunmorrow staff 510 May 8 18:09 ..
-rw-r--r-- 1 shaunmorrow staff 256 Apr 27 17:53 chains.go
-rw-r--r-- 1 shaunmorrow staff 3731 May 8 18:09 signed_transaction.go
-rw-r--r-- 1 shaunmorrow staff 1849 May 8 18:09 signed_transaction_test.go
-rw-r--r-- 1 shaunmorrow staff 3075 Apr 27 17:53 signing.c
-rw-r--r-- 1 shaunmorrow staff 408 Apr 27 17:53 signing.h
-rw-r--r-- 1 shaunmorrow staff 1049 May 8 18:09 transactions.go
and after the copy;
$ ls -la ../../transactions/
total 128
drwxr-xr-x 11 shaunmorrow staff 374 Jul 18 19:08 .
drwxr-xr-x 15 shaunmorrow staff 510 May 8 18:09 ..
-rw-r--r-- 1 shaunmorrow staff 256 Apr 27 17:53 chains.go
-rw-r--r-- 1 shaunmorrow staff 27071 Jul 18 19:08 secp256k1.h
-rw-r--r-- 1 shaunmorrow staff 1014 Jul 18 19:08 secp256k1_ecdh.h
-rw-r--r-- 1 shaunmorrow staff 4700 Jul 18 19:08 secp256k1_recovery.h
-rw-r--r-- 1 shaunmorrow staff 3731 Jul 18 19:05 signed_transaction.go
-rw-r--r-- 1 shaunmorrow staff 1849 May 8 18:09 signed_transaction_test.go
-rw-r--r-- 1 shaunmorrow staff 3075 Apr 27 17:53 signing.c
-rw-r--r-- 1 shaunmorrow staff 408 Apr 27 17:53 signing.h
-rw-r--r-- 1 shaunmorrow staff 1049 May 8 18:09 transactions.go
Now I get a new error;
$ go run main.go
# github.com/go-steem/rpc/transactions
ld: library not found for -lsecp256k1
clang: error: linker command failed with exit code 1 (use -v to see invocation)
This has me reading and googling some more,
Finally I get even more hack-y and change transactions.go;
// #cgo LDFLAGS: -lsecp256k1
// #include <stdlib.h>
// #include "signing.h"
import "C"
becomes
// #cgo LDFLAGS: -L/usr/local/lib
// #include <stdlib.h>
// #include "signing.h"
import "C"
which fails, output on that later
I also try;
// #cgo LDFLAGS: -L/usr/local/lib -I/usr/local/include
// #include <stdlib.h>
// #include "signing.h"
import "C"
and copy the .h files into the /usr/local/include directory.
None of this works and now I am stuck with an error like this
$ go run main.go
# github.com/go-steem/rpc/transactions
ld: library not found for -lsecp256k1
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ShaunsSePc-2:upvote shaunmorrow$ go run main.go
# github.com/go-steem/rpc/transactions
Undefined symbols for architecture x86_64:
"_secp256k1_context_create", referenced from:
_sign_transaction in signing.o
_verify_recoverable_signature in signing.o
"_secp256k1_context_destroy", referenced from:
_sign_transaction in signing.o
_verify_recoverable_signature in signing.o
"_secp256k1_ec_pubkey_serialize", referenced from:
_verify_recoverable_signature in signing.o
"_secp256k1_ecdsa_recover", referenced from:
_verify_recoverable_signature in signing.o
"_secp256k1_ecdsa_recoverable_signature_convert", referenced from:
_verify_recoverable_signature in signing.o
"_secp256k1_ecdsa_recoverable_signature_parse_compact", referenced from:
_verify_recoverable_signature in signing.o
"_secp256k1_ecdsa_recoverable_signature_serialize_compact", referenced from:
_sign_transaction in signing.o
"_secp256k1_ecdsa_sign_recoverable", referenced from:
_sign_transaction in signing.o
"_secp256k1_ecdsa_verify", referenced from:
_verify_recoverable_signature in signing.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
At this point I really have no idea how to continue.
As you can see I am not experienced in C at all and have no idea how to test if the library libsecp256k1 is even installed properly!
This is where I ended up, but it's highly likely I took a wrong turn early in my journey, I would appreciate any help given as I have been struggling with this for a few nights already now :(
Not sure whats needed so here some env variables
$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/shaunmorrow/Work/go/"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/86/hlqptn5101z5bcydjz05qy8m0000gn/T/go-build689438019=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
Version is go version go1.8.3 darwin/amd64 with no old versions lying around.
Thanks!
Your problem is twofold:
Improperly configured libsecp256k1 package
Your C compiler not searching /usr/local directories for installed headers/libs
Fixing the improperly libsecp256k1 configured package
Your "undefined symbols" issue when it comes to linking C libraries sometimes points to an improperly configured package (in the sense of an Autotools package or a CMake package, not a Go package). Running ./configure --help, I see there is an option named --enable-module-recovery. Judging by names like _secp256k1_ecdsa_sign_recoverable and _secp256k1_ecdsa_recover, you need to add that option when configuring, meaning instead of executing the simpler ./configure, you should execute this:
./configure --enable-module-recovery
Is the C compiler broken?
Since the secp256k1.h header file isn't found in /usr/local/include, despite the fact that the header file most definitely exists after sudo make install is finished, it means your compiler doesn't search /usr/local.
Barring any fixes in the linked question, you can work around the issue by altering the source of the Go package as needed to add/modify the CFLAGS and LDFLAGS used when dealing with import "C" statements like this:
// #cgo CFLAGS: -I/usr/local/include
// #cgo LDFLAGS: -L/usr/local/lib -lsecp256k1
// #include <secp256k1.h>
import "C"
If you have pkg-config installed, you can use that instead of setting CFLAGS and LDFLAGS manually:
Export the PKG_CONFIG_PATH environment variable with a custom set of paths. Because no prefix (i.e. directory serving as the install root) was specified, /usr/local is assumed, meaning /usr/local/include will contain headers and /usr/local/lib will contain libraries. This means you need to export PKG_CONFIG_PATH on your command line as in export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig. The default setting of PKG_CONFIG_PATH when unset includes /usr/lib/pkgconfig and /usr/share/pkgconfig in that order on Linux and are specified as a fallback for other packages that might be used, though it may not be necessary in this case. The default set of paths may differ on OS X, so consult your pkg-config man page for reference.
Use // #cgo pkg-config: libsecp256k1, and CFLAGS and LDFLAGS will be set as necessary without you needing to do anything to them. Since not all systems have pkg-config installed, relying on this is perhaps a bad idea if you want a package to remain portable. Then again, I think it'd be preferable to the mess you dealt with since pkg-config simply wouldn't be found.
Change to the upvote directory and type make to build a working upvote binary.
Additional customization
Custom prefix
If you use something other than /usr/local as your prefix (e.g. ./configure --enable-module-recovery --prefix=/opt/libsecp256k1), then you'll need to adjust some things accordingly:
// #cgo CFLAGS: -I/opt/libsecp256k1/include
// #cgo LDFLAGS: -L/opt/libsecp256k1/lib -lsecp256k1
// #include "secp256k1.h"
import "C"
// or just use pkg-config and export the PKG_CONFIG_PATH environment
// variable containing the following paths:
// /opt/libsecp256k1/lib/pkgconfig
// /opt/libsecp256k1/share/pkgconfig
// /usr/lib/pkgconfig
// /usr/share/pkgconfig
You'll also need to modify the provided Makefile in the upvote directory to set the runtime path of the binary that gets built, else libsecp256k1.0.dylib will not be found:
# If you copy and paste this, replace the spaces in front of `go build`
# with a single horizontal tab character, else `make` will fail.
#
# Note that the "ldflags" specified are for the Go linker (go tool link),
# not the system's linker (ld).
build:
go build -ldflags="-r /opt/libsecp256k1/lib"
For more information about working with cgo, check out the following resources:
"C? Go? Cgo!" introduction to cgo on The Go Blog
Cgo documentation
This is my simple hello-world FastCGI script written in C.
#include "fcgi_stdio.h"
#include <stdlib.h>
void main(void)
{
int count = 0;
while(FCGI_Accept() >= 0)
printf("Content-type: text/html\r\n"
"\r\n"
"<title>FastCGI Hello!</title>"
"<h1>FastCGI Hello!</h1>"
"Request number %d running on host <i>%s</i>\n",
++count, getenv("SERVER_NAME"));
}
It works fine if I compiled it using static linking.
gcc -o "test.fcg" "test.c" /usr/local/lib/libfcgi.a
But when using dynamic linking...
gcc -o "test.fcg" -lfcgi "test.c"
It fails whith the following error in Apache's error_log.
/var/www/fcgi-bin/test.fcg: error while loading shared libraries: libfcgi.so.0: cannot open shared object file: No such file or directory
[Thu Mar 05 14:04:22.707096 2015] [:warn] [pid 6544] FastCGI: (dynamic) server "/var/www/fcgi-bin/test.fcg" (pid 6967) terminated by calling exit with status '127'
[Thu Mar 05 14:04:22.707527 2015] [:warn] [pid 6544] FastCGI: (dynamic) server "/var/www/fcgi-bin/test.fcg" has failed to remain running for 30 seconds given 3 attempts, its restart interval has been backed off to 600 seconds
So I'm telling Apache and mod_fastcgi to look for that file where it's located setting the LD_LIBRARY_PATH variable in httpd.conf...
SetEnv LD_LIBRARY_PATH /usr/local/lib
...and fastcgi.conf.
FastCgiConfig -initial-env LD_LIBRARY_PATH=/usr/local/lib -idle-timeout 20 -maxClassProcesses 1
Using a static-linked script, getenv("LD_LIBRARY_PATH") returns /usr/local/lib, but dynamic-linked scripts are still throwing not found errors for libfcgi.so.0.
Any ideas to make this work?
Thanks in advance.
I had similar issue with nginx, I fixed it by using rpath option.
Not sure if it will help with Apache. Try building your binary like this:
gcc test.c -Wl,-rpath /usr/local/lib -lfcgi -o test.fcg
Make sure the library file libfcgi.so.0 is present at /usr/local/lib.
If you don't have access to /usr/local/lib, then create the lib folder in your $HOME, and copy the library file there. And update the rpath to point to there. For example, if your $HOME is /home/xyz, then you would build like:
gcc test.c -Wl,-rpath /home/xyz/lib -lfcgi -o test.fcg
Sometimes I use this trick to load newer libraries than what is installed on the system.
I have an openvz machine which I am root on, it is a virtual machine I am ssh to:
>uname -a
Linux molo 2.6.32-042stab084.25 #1 SMP Wed Feb 12 16:04:42 MSK 2014 x86_64 x86_64 x86_64 GNU/Linux
I am trying to build an hello world kernel module:
hello.c:
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
static int __init hello_start(void)
{
printk(KERN_INFO "Loading hello module...\n");
printk(KERN_INFO "Hello world\n");
return 0;
}
static void __exit hello_end(void)
{
printk(KERN_INFO "Goodbye Mr.\n");
}
module_init(hello_start);
module_exit(hello_end);
Makefile:
obj-m = hello.o
KVERSION = $(shell uname -r)
all:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
And when I am trying to compile hello.c:
#make
make -C /lib/modules/2.6.32-042stab084.25/build M=/local/my_modules modules
make: *** /lib/modules/2.6.32-042stab084.25/build: No such file or directory. Stop.
make: *** [all] Error 2
That is the kernel version uname -r reports
#uname -r
2.6.32-042stab084.25
The following didn't help too:
$sudo apt-get install "linux-headers-$(uname -r)"
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package linux-headers-2.6.32-042stab084.25
E: Couldn't find any package by regex 'linux-headers-2.6.32-042stab084.25'
Here is the /lib/modules directory:
ls /lib/modules/2.6.32-042stab084.25/
modules.alias modules.ccwmap modules.dep.bin modules.ieee1394map modules.isapnpmap modules.pcimap modules.softdep modules.symbols.bin
modules.alias.bin modules.dep modules.devname modules.inputmap modules.ofmap modules.seriomap modules.symbols modules.usbmap
Download and install linux-headers package from openvz page (more on http://openvz.org/Installation_on_Debian)
1) Add source
cat << EOF > /etc/apt/sources.list.d/openvz-rhel6.list
deb http://download.openvz.org/debian wheezy main
# deb http://download.openvz.org/debian wheezy-test main
EOF
2) Install
wget http://ftp.openvz.org/debian/archive.key
sudo apt-key add archive.key
sudo apt-get update
sudo apt-get install "linux-headers-$(uname -r)"
Remember that you can only do this from the "Host", not from inside of a OpenVZ VPS. Meaning that loading kernel drivers to kernel is only permitted from the Host and would affect all containers on that Host.
Your kernel doesn't appear to be one of the ones provided by Canonical, usually official kernels end with a version number or with the generic or other suffix.
Usually you find the package with the kernel headers under pool/main/l as you can see here in the case of the security repository for Ubuntu Saucy.
You should ask the question to the person that provided the kernel that you are using, there is not that much you can do without more information unless you are willing to go for an officially supported kernel.