技术解析

Linux 通过添加内核模块增加系统调用编译报"提领指向不完全类型的指针"的错误
0
2021-06-17 16:39:07
idczone

内核是根据 linux-5.6.13 的源码自己编译的内核,虚拟机+Centos7 64 位

代码如下

#include 
#include 
#include 
#include 
#include 
#include 

#define my_syscall_num 336
/*此处我也不知道为啥,执行
cat /proc/kallsyms | grep sys_call_table
结果如下
0000000000000000 R sys_call_table
0000000000000000 R ia32_sys_call_table
*/
#define sys_call_table_adress 0x00000000

unsigned int clear_and_return_cr0(void);
void setback_cr0(unsigned int val);
asmlinkage long sys_mycall(long long num);
int orig_cr0;
unsigned long *sys_call_table = 0;
static int (*anything_saved)(void);

MODULE_AUTHOR("GuoShuSong");
MODULE_LICENSE("GPL");
unsigned int clear_and_return_cr0(void){
	unsigned int cr0 = 0;
	unsigned int ret;
	asm("movl %%cr0,%%eax":"=a"(cr0));
	ret = cr0;
	cr0 &= 0xfffeffff;
	asm("movl %%eax,%%cr0"::"a"(cr0));
	return ret;
}
void setback_cr0(unsigned int val){
	asm volatile("movl %%eax,%%cr0"::"a"(val));
}

static int __init init_addsyscall(void){
	printk("hello,kernel");
	sys_call_table=(unsigned long *)sys_call_table_adress;
	anything_saved = (int(*)(void))(sys_call_table[my_syscall_num]);
	orig_cr0 = clear_and_return_cr0();
	sys_call_table[my_syscall_num]= (unsigned long)&sys_mycall;
	setback_cr0(orig_cr0);
	return 0;
}

asmlinkage long sys_mycall(long long num){
	int res =0;
	long long r = num;
	if(do_div(num,2)== 0){
		res = do_div(r,1000000);
	}else{
		res = do_div(r,100000);
	}
	return res;
}

static void __exit exit_addsyscall(void){
	orig_cr0 = clear_and_return_cr0();
	sys_call_table[my_syscall_num]= (unsigned long)anything_saved;
	setback_cr0(orig_cr0);
	printk("call exit \n");
}

module_init(init_addsyscall);
module_exit(exit_addsyscall);

MakeFile 代码如下

ifneq  ($(KERNELRELEASE),)
EXTRA_CFLAGS = -O0
obj-m := gss.o
else
KDIR = /lib/modules/$(shell uname -r)/build

#KDIR = /lib/modules/5.6.1318130500093-GuoShuSong/build

PWD := $(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules
clean:
	rm -f *.ko *.o *.symvers *.cmd *.cmd.o
endif

执行 make 时报错如下

make -C /lib/modules/5.6.1318130500093-GuoShuSong/build M=/home/gssplus/桌面 /test/os3 modules
make[1]: 进入目录“/home/gssplus/桌面 /test/linux-5.6.13”
  CC [M]  /home/gssplus/桌面 /test/os3/gss.o
In file included from /home/gssplus/桌面 /test/os3/gss.c:5:0:
./arch/x86/include/asm/uaccess.h: 在函数‘set_fs’中:
./arch/x86/include/asm/uaccess.h:31:9: 错误:提领指向不完全类型的指针
  current->thread.addr_limit = fs;
         ^
In file included from ./include/linux/init.h:5:0,
                 from /home/gssplus/桌面 /test/os3/gss.c:1:
./arch/x86/include/asm/uaccess.h: 在函数‘user_access_begin’中:
./arch/x86/include/asm/uaccess.h:37:33: 错误:提领指向不完全类型的指针
 #define user_addr_max() (current->thread.addr_limit.seg)
                                 ^
./include/linux/compiler.h:78:42: 附注:in definition of macro ‘unlikely’
 # define unlikely(x) __builtin_expect(!!(x), 0)
                                          ^
./arch/x86/include/asm/uaccess.h:96:2: 附注:in expansion of macro ‘likely’
  likely(!__range_not_ok(addr, size, user_addr_max()));  \
  ^
./arch/x86/include/asm/uaccess.h:96:10: 附注:in expansion of macro ‘__range_not_ok’
  likely(!__range_not_ok(addr, size, user_addr_max()));  \
          ^
./arch/x86/include/asm/uaccess.h:96:37: 附注:in expansion of macro ‘user_addr_max’
  likely(!__range_not_ok(addr, size, user_addr_max()));  \
                                     ^
./arch/x86/include/asm/uaccess.h:714:16: 附注:in expansion of macro ‘access_ok’
  if (unlikely(!access_ok(ptr,len)))
                ^
make[3]: *** [/home/gssplus/桌面 /test/os3/gss.o] 错误 1
make[2]: *** [/home/gssplus/桌面 /test/os3] 错误 2
make[1]: *** [sub-make] 错误 2
make[1]: 离开目录“/home/gssplus/桌面 /test/linux-5.6.13”
make: *** [all] 错误 2

有没有大佬知道是怎么回事儿


路径换英文试试

current 找不到定义。它是一个指向当前进程块的宏,应该是缺了头文件。 另外别用中文环境,这翻译比苹果官网的还迷。

嗯,不完整的类型这种错误,一般就是没有定义或者没有头文件的问题

谁语文好的解释一下提领是什么意思?

include 加上试试。另外现在 kernel 的系统调用表应该默认是只读的,要手动改 page table entry 才能改写

另外把 locale 设成英文错误提示可能更易懂些,网上也好搜解决方法……

数据地带为您的网站提供全球顶级IDC资源
在线咨询
专属客服