Linux Kernel Module - Producing two modules with shared local header - c

I have the following files: buffer.c, buffer.h, chardevin.c, chardevout.c and Makefile. Both chardevin.c and chardevout.c are kernel modules. Both kernel modules include buffer.h, which is implemented by buffer.c. Ideally, I'd like the makefile to make both kernel modules while linking the buffer implementation (i.e. produce chardevin.ko and chardevout.ko). I can't seem to figure this part out...
Here's the contents of my Makefile:
obj-m += chardevin.o chardevout.o
obj-y += buffer.c
all:
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
I get the following as output, however:
kylemart#ubuntu:/mnt/hgfs/ucf-os-linux/SplitDriverWithMutex$ make
make -C /lib/modules/4.4.0-31-generic/build/ M=/mnt/hgfs/ucf-os-linux/SplitDriverWithMutex modules
make[1]: Entering directory `/usr/src/linux-headers-4.4.0-31-generic'
CC [M] /mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevin.o
CC [M] /mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevout.o
Building modules, stage 2.
MODPOST 2 modules
WARNING: "buffer_read" [/mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevout.ko] undefined!
WARNING: "buffer_length" [/mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevout.ko] undefined!
WARNING: "buffer_write" [/mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevin.ko] undefined!
WARNING: "buffer_length" [/mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevin.ko] undefined!
CC /mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevin.mod.o
LD [M] /mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevin.ko
CC /mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevout.mod.o
LD [M] /mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevout.ko
make[1]: Leaving directory `/usr/src/linux-headers-4.4.0-31-generic'
Here's the contents of buffer.h:
#ifndef BUFFER_H
#define BUFFER_H
ssize_t buffer_write(const char *src, size_t n);
ssize_t buffer_read(char *dest, size_t n);
size_t buffer_length(void);
#endif
What am I doing wrong?
EDIT:
Changed "buffer.c" to "buffer.o" in the Makefile. Here's the output:
kylemart#ubuntu:/mnt/hgfs/ucf-os-linux/SplitDriverWithMutex$ make
make -C /lib/modules/4.4.0-31-generic/build/ M=/mnt/hgfs/ucf-os-linux/SplitDriverWithMutex modules
make[1]: Entering directory `/usr/src/linux-headers-4.4.0-31-generic'
Building modules, stage 2.
MODPOST 2 modules
WARNING: "buffer_read" [/mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevout.ko] undefined!
WARNING: "buffer_length" [/mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevout.ko] undefined!
WARNING: "buffer_write" [/mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevin.ko] undefined!
WARNING: "buffer_length" [/mnt/hgfs/ucf-os-linux/SplitDriverWithMutex/chardevin.ko] undefined!
make[1]: Leaving directory `/usr/src/linux-headers-4.4.0-31-generic'

Replace as below this:
obj-y += buffer.c -- > obj-y += buffer.o

Related

KBuild fails while compiling without debugging flag

I am trying to compile a very simple module, but it fails to create *.ko when i am not adding -g flag. Here is the source code:
#include <linux/init.h>
#include <linux/module.h>
static int simple_test_init(void){
printk(KERN_INFO "Hello Kernel!");
return 0;
}
static void simple_test_exit(void){
printk(KERN_INFO "Goodbye Kernel!");
}
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Simple test module");
module_init(simple_test_init);
module_exit(simple_test_exit);
And here is GCC/Makefile.
KBUILD_CFLAGS := -Werror -fcf-protection=branch
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
And finally the output of GCC.
make -C /lib/modules/5.19.3-arch1-1/build M=/test modules
make[1]: Entering directory '/usr/lib/modules/5.19.3-arch1-1/build'
CC [M] /test/test.o
/test/test.o: warning: objtool: folio_flags+0x29: 'naked' return found in RETHUNK build
/test/test.o: warning: objtool: simple_test_init+0x22: 'naked' return found in RETHUNK build
/test/test.o: warning: objtool: simple_test_exit+0x1e: 'naked' return found in RETHUNK build
/test/test.o: warning: objtool: folio_flags+0x29: missing int3 after ret
/test/test.o: warning: objtool: simple_test_init+0x22: missing int3 after ret
/test/test.o: warning: objtool: simple_test_exit+0x1e: missing int3 after ret
MODPOST /test/Module.symvers
CC [M] /test/test.mod.o
LD [M] /test/test.ko
BTF [M] /test/test.ko
pahole: /test/test.ko: No such file or directory
make[3]: *** [scripts/Makefile.modfinal:60: /test/test.ko] Error 1
make[3]: *** Deleting file '/test/test.ko'
make[2]: *** [scripts/Makefile.modpost:134: __modpost] Error 2
make[1]: *** [Makefile:1763: modules] Error 2
make[1]: Leaving directory '/usr/lib/modules/5.19.3-arch1-1/build'
make: *** [Makefile:6: all] Error 2
Thank you.

MODULE_LICENSE is defined but undetected in linux kernel 5.X

I have a simple kernel module with multiple objects. When I compile it, it prompts me that MODULE_LICENSE is missing. It's defined in the main.o but somehow undetected by the compiler:
make -C /lib/modules/`uname -r`/build M=`pwd` modules
make[1]: Entering directory '/usr/src/kernels/5.14.0-105.el9.x86_64'
CC [M] /tmp/linux5-multi-files/util.o
LD [M] /tmp/linux5-multi-files/main.o
MODPOST /tmp/linux5-multi-files/Module.symvers
ERROR: modpost: missing MODULE_LICENSE() in /tmp/linux5-multi-files/main.o
make[2]: *** [scripts/Makefile.modpost:150: /tmp/linux5-multi-files/Module.symvers] Error 1
make[2]: *** Deleting file '/tmp/linux5-multi-files/Module.symvers'
make[1]: *** [Makefile:1792: modules] Error 2
make[1]: Leaving directory '/usr/src/kernels/5.14.0-105.el9.x86_64'
make: *** [Makefile:5: build] Error 2
On older Linux (centos 6-7) it works fine, but on CentOS 8 and CentOS 9, it no longer works. What was wrong? I've attached all the files.
-- attached all files --
Makefile
main-objs := util.o
obj-m += main.o
build:
make -C /lib/modules/`uname -r`/build M=`pwd` modules
clean:
make -C /lib/modules/`uname -r`/build M=`pwd` clean
main.c
#include "util.h"
static void __exit cleanup(void)
{
}
static int __init startup(void)
{
test();
return 0;
}
module_init(startup);
module_exit(cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux");
util.h
#ifndef UTIL_H
#define UTIL_H
#include <linux/module.h>
#include <linux/kernel.h>
void test(void);
#endif
util.c
#include "util.h"
void test()
{
printk(KERN_INFO "whatever\n");
}
To further debug this issue, I've added -v to the ccflags, and main.c is not even compiled on CentOS 8!
So far it looks like the module name can't be the same as the object name, so I have to modify the makefile to something like this:
xxx-objs := main.o util.o
obj-m += xxx.o
And the problem is gone.

How to read a text file from Linux Kernel Module (Linux Kernel 5.11.0)

I want to read a txt file and write another txt file in kernel module
How should I do ?
I have seen many website.
It seems like it has many ways to solve this question
ex : filp_read() or kernel_read() or vfs_read()
[Sloved] But I have tried many times, it couldn't makefile.
[Answer] Use mv make Makefile
reverse.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
static char buf[] ="It's from linux kernel\n";
static char buf1[32];
int __init test_init(void)
{
struct file *fp;
mm_segment_t fs;
loff_t pos;
printk("test enter\n");
fp =filp_open("/home/j0000/Desktop/file/kernel_file",O_RDWR | O_CREAT,0644);
if (IS_ERR(fp)){
printk("create file error\n");
return -1;
}
fs =get_fs();
set_fs(KERNEL_DS);
pos =0;
vfs_write(fp,buf, sizeof(buf), &pos);
pos =0;
vfs_read(fp,buf1, sizeof(buf), &pos);
printk("Write contet=%s\n",buf1);
filp_close(fp,NULL);
set_fs(fs);
return 0;
}
void __exit test_exit(void)
{
printk("test exit\n");
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
makefile
obj-m :=reverse.o
read_userspace-objs:= read_userspace_file.o
KVERSION := $(shell uname -r)
KDIR := /usr/src/linux-headers-$(KVERSION)/
PWD := $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.cmd *.ko *.mod.c .tmp_versions Module.symvers modules.order
error message
j0000#ubuntu:~/Desktop/file$ make
make -C /usr/src/linux-headers-5.11.0-37-generic/ M=/home/j0000/Desktop/file modules
make[1]: Entering directory '/usr/src/linux-headers-5.11.0-37-generic'
scripts/Makefile.build:44: /home/j0000/Desktop/file/Makefile: No such file or directory
make[2]: *** No rule to make target '/home/j0000/Desktop/file/Makefile'. Stop.
make[1]: *** [Makefile:1849: /home/j0000/Desktop/file] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.11.0-37-generic'
make: *** [makefile:8: default] Error 2
j0000#ubuntu:~/Desktop/file$
updated error message
I have seen these error many times~
So may I ask why it can't use get_fs & set_fs in this situation
j0000#ubuntu:~/Desktop/file$ make
make -C /usr/src/linux-headers-5.11.0-37-generic/ M=/home/j0000/Desktop/file modules
make[1]: Entering directory '/usr/src/linux-headers-5.11.0-37-generic'
CC [M] /home/j0000/Desktop/file/reverse.o
/home/j0000/Desktop/file/reverse.c: In function ‘test_init’:
/home/j0000/Desktop/file/reverse.c:20:9: error: implicit declaration of function ‘get_fs’; did you mean ‘sget_fc’? [-Werror=implicit-function-declaration]
20 | fs =get_fs();
| ^~~~~~
| sget_fc
/home/j0000/Desktop/file/reverse.c:20:9: error: incompatible types when assigning to type ‘mm_segment_t’ {aka ‘struct <anonymous>’} from type ‘int’
/home/j0000/Desktop/file/reverse.c:21:5: error: implicit declaration of function ‘set_fs’; did you mean ‘sget_fc’? [-Werror=implicit-function-declaration]
21 | set_fs(KERNEL_DS);
| ^~~~~~
| sget_fc
/home/j0000/Desktop/file/reverse.c:21:12: error: ‘KERNEL_DS’ undeclared (first use in this function); did you mean ‘KERNFS_NS’?
21 | set_fs(KERNEL_DS);
| ^~~~~~~~~
| KERNFS_NS
/home/j0000/Desktop/file/reverse.c:21:12: note: each undeclared identifier is reported only once for each function it appears in
cc1: some warnings being treated as errors
make[2]: *** [scripts/Makefile.build:288: /home/j0000/Desktop/file/reverse.o] Error 1
make[1]: *** [Makefile:1849: /home/j0000/Desktop/file] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.11.0-37-generic'
make: *** [Makefile:8: default] Error 2
Actually I use this website for tutorial
https://www.cnblogs.com/arnoldlu/p/8879800.html
After all, I will use kernel_read & kernel_write to fix my bug.
Thanks for answering my question :)

Makefile issue when trying to compile an application that uses net-snmp and rapidjson

I am compiling a snmp agent application using net-snmp and compiling it correctly with this Makefile:
CC = gcc
SRC = $(shell find . -name '*.c')
OBJS = $(SRC:.c=.o)
TARGET = agent_daemon
CFLAGS = -I. `net-snmp-config --cflags`
# CFLAGS = -I. `net-snmp-config --cflags` `rapidjson`
BUILDLIBS = `net-snmp-config --libs`
BUILDAGENTLIBS = `net-snmp-config --agent-libs`
# shared library flags (assumes gcc)
DLFLAGS = -fPIC -shared
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) -o $(TARGET) $(OBJS) $(BUILDAGENTLIBS)
clean:
rm -Rf $(OBJS) $(TARGET)
Now I need to use the rapidjson library in one of the snmp agent's .c files.
rapidson is installed in /usr/include/rapidjson
In the .c file I have added the following include:
#include "rapidjson/filereadstream.h"
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
And the source code that is using rapidjson is this:
char readBuffer[65536];
FILE* fp = fopen("my_config_file.json", "r");
FileReadStream is(fp, readBuffer, sizeof(readBuffer));
Document doc;
doc.ParseStream(is);
char jsonKey[21];
fclose(fp);
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
doc.Accept(writer);
printf("JSON: %s\n", buffer.GetString());
In order to be able to compile the version of the SNMP agent that uses rapidjson I have changed in the previous Makefile the line:
CC = gcc
For :
CC = g++
However, when compiling it with the new Makefile, I get these errors:
readConfigFile.c:42:3: error: ‘FileReadStream’ was not declared in this scope
FileReadStream is(fp, readBuffer, sizeof(readBuffer));
^
readConfigFile.c:42:3: note: suggested alternative:
In file included from readConfigFile.c:17:0:
/usr/include/rapidjson/filereadstream.h:33:7: note: ‘rapidjson::FileReadStream’
class FileReadStream {
^
readConfigFile.c:44:3: error: ‘Document’ was not declared in this scope
Document doc;
^
readConfigFile.c:44:3: note: suggested alternative:
In file included from readConfigFile.c:18:0:
/usr/include/rapidjson/document.h:1889:34: note: ‘rapidjson::Document’
typedef GenericDocument<UTF8<> > Document;
^
readConfigFile.c:45:3: error: ‘doc’ was not declared in this scope
doc.ParseStream(is);
^
readConfigFile.c:45:19: error: ‘is’ was not declared in this scope
doc.ParseStream(is);
^
readConfigFile.c:50:3: error: ‘StringBuffer’ was not declared in this scope
StringBuffer buffer;
^
readConfigFile.c:50:3: note: suggested alternative:
In file included from /usr/include/rapidjson/writer.h:29:0,
from readConfigFile.c:19:
/usr/include/rapidjson/stringbuffer.h:69:38: note: ‘rapidjson::StringBuffer’
typedef GenericStringBuffer<UTF8<> > StringBuffer;
^
readConfigFile.c:51:3: error: ‘Writer’ was not declared in this scope
Writer<StringBuffer> writer(buffer);
^
readConfigFile.c:51:3: note: suggested alternative:
In file included from readConfigFile.c:19:0:
/usr/include/rapidjson/writer.h:56:7: note: ‘rapidjson::Writer’
class Writer {
^
readConfigFile.c:51:31: error: ‘buffer’ was not declared in this scope
Writer<StringBuffer> writer(buffer);
^
readConfigFile.c:51:37: error: ‘writer’ was not declared in this scope
Writer<StringBuffer> writer(buffer);
^
<builtin>: recipe for target 'readConfigFile.o' failed
make: *** [readConfigFile.o] Error 1
I have tried modifying the Makefile and adding "-I" option, like this:
$(TARGET): $(OBJS)
$(CC) -o $(TARGET) $(OBJS) $(BUILDAGENTLIBS) -I/usr/include/rapidjson
But I get the same errors.
I appreciate any help or suggestions.

How to write and compile kernel module from multiple sources? (WARNING: "do_function" [... main.ko] undefined)

I want to separate my kernel module to sources. But I can't compile it properly.
print_hello.h
#ifndef PRINT_HELLO_H_
#define PRINT_HELLO_H_
void print_hello(void);
#endif /* PRINT_HELLO_H_ */
print_hello.c:
#include <linux/kernel.h>
#include "print_hello.h"
void print_hello(void) {
printk("Hello, World!\n");
}
main.c:
#include<linux/module.h>
#include<linux/version.h>
#include<linux/kernel.h>
#include<linux/init.h>
#include "print_hello.h"
int hello_init(void) {
print_hello();
return 0;
}
module_init(hello_init);;
MODULE_LICENSE("GPL");
Makefile:
obj-m += main.o
main-objs := print_hello.o main.o
all:
make -C /lib/modules/3.2.51/build M=$(PWD) modules
clean:
make -C /lib/modules/3.2.51/build M=$(PWD) clean
but when I compile this program this error occur:
root#linux:r# make
make -C /lib/modules/3.2.51/build M=/home/root/hello modules
make[1]: Entering directory `/usr/src/build'
CC [M] /home/root/hello/main.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: "print_hello" [/home/root/hello/main.ko] undefined!
LD [M] /home/root/hello/foo.ko
make[1]: Leaving directory `/usr/src/build'
Any solution to solve this problem?

Resources