MIPS Linux下添加系统调用实例,添加一个系统调用有以下几个步骤:
1. 在 kernel 的系统调用表 sys_call_table 中添加你的系统调用入口
根据你用的内核位数(32/64bit) 选择需要修改的文件:
(如果你分不清,那就吧scall开头的几个文件全部添加上)
arch/mips/kernel/scall32-o32.S ——> 32bit kernel
arch/mips/kernel/scall64-64.S ——> 64bit kernel
64bit内核,如果支持兼容32 bit ABI (o32, n32 ) 则还需修改 scall64-o32.S 或 scall64-n32.S
以32bit 内核为例,在 arch/mips/kernel/scall32-o32.S 中找到宏定义
.macro syscalltable
……
……
sys sys_timerfd 4
sys sys_eventfd 1
sys sys_fallocate 6
sys sys_comcat 0
.endm
最后加入自定义的系统调用 sys_comcat 于 sys_call_table 中, sys 为辅助宏,调用名后的数值 0 指示该系统调用所需的参数个数。
只能加在 sys_call_table 的最后,否则会扰乱标准的系统调用。
2. 实现系统调用
可以在 arch/mips/kernel/syscall.c (也可以在其他文件实现)中给出一个实现,如:
asmlinkage void sys_comcat(void)
{
printk(KERN_EMERG “This’s comcat syscall/n”);
}
3. 修改 include/asm-mips/unistd.h
(这个目录找不到啊,难道是arch/mips/include/asm/unistd.h ????!!! )
根据你的内核位和支持的ABI版本修改相应的宏定义,32bit 内核需修改:
#define __NR_Linux_syscalls 320 ———> 321 (The number of linux syscalls)
#define __NR_O32_Linux_syscalls 320 ———> 321 (The number of linux O32 syscalls)
相应的在其上的宏集的最后加入:
…….
#define __NR_timerfd (__NR_Linux + 318)
#define __NR_eventfd (__NR_Linux + 319)
#define __NR_fallocate (__NR_Linux + 320)
#define __NR_comcat (__NR_Linux + 321)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
我还在include\asm-generic\Unistd.h目录下添加了。。。
#define __NR_comcat 242
__SYSCALL(__NR_comcat, sys_comcat)
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<</FONT>
4. 测试新的系统调用sys_comcat
用重新编译后的内核启动,如下程序测试之:
.text
.globl main
.ent main
main:
li $2, 4321
syscall
.end main
其中 MIPS 下系统调用的约定为:
v0: 用于置系统调用号
a0~a3: 置前四个参数,后面的参数用栈传
syscall 系统调用触发指令
编译 gcc cat.S -o cat
执行 ./cat
正确的话应有如下输出:
Message from syslogd@localhost at Wed Aug 29 13:15:37 2007 …
localhost kernel: This’s comcat syscall
主要转载于:http://blog.csdn.net/comcat/article/details/1774231
后记:patch实例 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
diff -uNr kernel-3a-gw-2.6.36-3.clean/arch/mips/include/asm/unistd.h kernel-3a-gw-2.6.36-3.clean.cap/arch/mips/include/asm/unistd.h
— kernel-3a-gw-2.6.36-3.clean/arch/mips/include/asm/unistd.h 2013-08-16 10:33:33.000000000 -0400
+++ kernel-3a-gw-2.6.36-3.clean.cap/arch/mips/include/asm/unistd.h 2013-09-09 16:51:09.000000000 -0400
@@ -358,6 +358,7 @@
#define __NR_fanotify_init (__NR_Linux + 336)
#define __NR_fanotify_mark (__NR_Linux + 337)
#define __NR_prlimit64 (__NR_Linux + 338)
+#define __NR_cap_user_set (__NR_Linux + 339)
#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 338
+#define __NR_O32_Linux_syscalls 339
#if (defined(__WANT_SYSCALL_NUMBERS) && \
(__WANT_SYSCALL_NUMBERS == _MIPS_SIM_ABI64)) || \
@@ -673,16 +674,17 @@
#define __NR_fanotify_init (__NR_Linux + 295)
#define __NR_fanotify_mark (__NR_Linux + 296)
#define __NR_prlimit64 (__NR_Linux + 297)
+#define __NR_cap_user_set (__NR_Linux + 298)
-#define __NR_Linux_syscalls 297
+#define __NR_Linux_syscalls 298
#endif
#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 297
+#define __NR_64_Linux_syscalls 298
#if (defined(__WANT_SYSCALL_NUMBERS) && \
(__WANT_SYSCALL_NUMBERS == _MIPS_SIM_NABI32)) || \
@@ -995,16 +997,17 @@
#define __NR_fanotify_init (__NR_Linux + 300)
#define __NR_fanotify_mark (__NR_Linux + 301)
#define __NR_prlimit64 (__NR_Linux + 302)
+#define __NR_cap_user_set (__NR_Linux + 303)
-#define __NR_Linux_syscalls 302
+#define __NR_Linux_syscalls 303
#endif
#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 302
+#define __NR_N32_Linux_syscalls 303
#ifdef __KERNEL__
diff -uNr kernel-3a-gw-2.6.36-3.clean/arch/mips/kernel/scall32-o32.S kernel-3a-gw-2.6.36-3.clean.cap/arch/mips/kernel/scall32-o32.S
— kernel-3a-gw-2.6.36-3.clean/arch/mips/kernel/scall32-o32.S 2013-08-16 10:33:36.000000000 -0400
+++ kernel-3a-gw-2.6.36-3.clean.cap/arch/mips/kernel/scall32-o32.S 2013-09-09 16:51:35.000000000 -0400
@@ -587,6 +587,7 @@
sys sys_fanotify_init 2
sys sys_fanotify_mark 6
sys sys_prlimit64 4
+ sys sys_cap_user_set 2
.endm
PTR sys_fanotify_mark
PTR sys_prlimit64
+ PTR sys_cap_user_set
.size sys_call_table,.-sys_call_table
diff -uNr kernel-3a-gw-2.6.36-3.clean/arch/mips/kernel/scall64-n32.S kernel-3a-gw-2.6.36-3.clean.cap/arch/mips/kernel/scall64-n32.S
— kernel-3a-gw-2.6.36-3.clean/arch/mips/kernel/scall64-n32.S 2013-08-16 10:33:36.000000000 -0400
+++ kernel-3a-gw-2.6.36-3.clean.cap/arch/mips/kernel/scall64-n32.S 2013-09-09 16:51:37.000000000 -0400
@@ -427,4 +427,5 @@
PTR sys_fanotify_init
PTR sys_fanotify_mark
PTR sys_prlimit64
+ PTR sys_cap_user_set
.size sysn32_call_table,.-sysn32_call_table
diff -uNr kernel-3a-gw-2.6.36-3.clean/arch/mips/kernel/scall64-o32.S kernel-3a-gw-2.6.36-3.clean.cap/arch/mips/kernel/scall64-o32.S
— kernel-3a-gw-2.6.36-3.clean/arch/mips/kernel/scall64-o32.S 2013-08-16 10:33:36.000000000 -0400
+++ kernel-3a-gw-2.6.36-3.clean.cap/arch/mips/kernel/scall64-o32.S 2013-09-09 16:51:38.000000000 -0400
@@ -545,4 +545,5 @@
PTR sys_fanotify_init
PTR sys_32_fanotify_mark
PTR sys_prlimit64
+ PTR sys_cap_user_set
.size sys_call_table,.-sys_call_table
diff -uNr kernel-3a-gw-2.6.36-3.clean/arch/x86/include/asm/unistd_32.h kernel-3a-gw-2.6.36-3.clean.cap/arch/x86/include/asm/unistd_32.h
— kernel-3a-gw-2.6.36-3.clean/arch/x86/include/asm/unistd_32.h 2013-08-16 10:32:44.000000000 -0400
+++ kernel-3a-gw-2.6.36-3.clean.cap/arch/x86/include/asm/unistd_32.h 2013-09-09 16:10:13.000000000 -0400
@@ -346,10 +346,11 @@
#define __NR_fanotify_init 338
#define __NR_fanotify_mark 339
#define __NR_prlimit64 340
+#define __NR_cap_user_set 341
#ifdef __KERNEL__
-#define NR_syscalls 341
+#define NR_syscalls 342
#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
diff -uNr kernel-3a-gw-2.6.36-3.clean/arch/x86/include/asm/unistd_64.h kernel-3a-gw-2.6.36-3.clean.cap/arch/x86/include/asm/unistd_64.h
— kernel-3a-gw-2.6.36-3.clean/arch/x86/include/asm/unistd_64.h 2013-08-16 10:32:43.000000000 -0400
+++ kernel-3a-gw-2.6.36-3.clean.cap/arch/x86/include/asm/unistd_64.h 2013-09-09 16:10:13.000000000 -0400
@@ -669,6 +669,10 @@
__SYSCALL(__NR_fanotify_mark, sys_fanotify_mark)
#define __NR_prlimit64 302
__SYSCALL(__NR_prlimit64, sys_prlimit64)
+
+#define __NR_cap_user_set 303
+__SYSCALL(__NR_cap_user_set, sys_cap_user_set)
+
#ifndef __NO_STUBS
#define __ARCH_WANT_OLD_READDIR
diff -uNr kernel-3a-gw-2.6.36-3.clean/arch/x86/kernel/syscall_table_32.S kernel-3a-gw-2.6.36-3.clean.cap/arch/x86/kernel/syscall_table_32.S
— kernel-3a-gw-2.6.36-3.clean/arch/x86/kernel/syscall_table_32.S 2013-08-16 10:32:46.000000000 -0400
+++ kernel-3a-gw-2.6.36-3.clean.cap/arch/x86/kernel/syscall_table_32.S 2013-09-09 16:10:13.000000000 -0400
@@ -340,3 +340,4 @@
.long sys_fanotify_init
.long sys_fanotify_mark
.long sys_prlimit64
+ .long sys_cap_user_set
diff -uNr kernel-3a-gw-2.6.36-3.clean/security/commoncap.c kernel-3a-gw-2.6.36-3.clean.cap/security/commoncap.c
— kernel-3a-gw-2.6.36-3.clean/security/commoncap.c 2013-08-16 10:33:44.000000000 -0400
+++ kernel-3a-gw-2.6.36-3.clean.cap/security/commoncap.c 2013-09-09 16:10:13.000000000 -0400
@@ -29,6 +29,26 @@
#include
#include
+
+struct cap_user_cache
+{
+ struct list_head cache;
+ __u32 node_num;
+};
+
+struct cap_user_cache_node
+{
+// kernel_cap_t permitted;
+ kernel_cap_t effective;
+// kernel_cap_t inheritable;
+ struct list_head list;
+ __u32 uid;
+};
+
+struct cap_user_cache cap_user_cache;
+static struct kmem_cache *cap_cache_nodep;
+
+
+
+void cap_user_init(void)
+{
+ //printk(KERN_INFO “kernel cap : cap_user_init() init user cap cache begin…\n”);
+ INIT_LIST_HEAD(&cap_user_cache.cache);
+ cap_user_cache.node_num = 0;
+ cap_cache_nodep = kmem_cache_create(“cap_cache_node” ,sizeof(struct cap_user_cache_node),0,SLAB_PANIC,NULL);
+ //printk(KERN_INFO “kernel cap : cap_user_init() init user cap cache end\n”);
+}
+
+
+void cap_bprm_user_set(struct cred *cred)
+{
+ u32 uid = cred->uid;
+ struct cred *new = cred;
+ struct cap_user_cache_node *node;
+
+ list_for_each_entry(node, &cap_user_cache.cache, list)
+ {
+ if(uid == node->uid)
+ {
+ new->cap_effective= node->effective;
+ //printk(KERN_INFO “kernel cap : cap_bprm_user_set() uid = %d\n”,node->uid);
+ }
+ }
+}
+
+
+asmlinkage long sys_cap_user_set (int user, char cap_user_data[6][12])
+{
+ struct cap_user_cache_node *node_t = NULL;
+ struct cap_user_cache_node *node = NULL;
+
+#if 0
+ int i =0;
+ for (i=0; i<6; i++)
+ {
+ printk(KERN_INFO “kernel cap : sys_cap_user_set() cap_user_data[%d] = %s, strlen = %d\n”, i, cap_user_data[i], strlen(cap_user_data[i]));
+ }
+#endif
+
+ list_for_each_entry(node_t, &cap_user_cache.cache, list)
+ {
+ if(user == node_t->uid)
+ {
+ node = node_t;
+ break;
+ }
+ }
+
+ if(node == NULL)
+ {
+ node = kmem_cache_alloc(cap_cache_nodep, GFP_ATOMIC);
+ node -> uid = user;
+ list_add(&node->list,&cap_user_cache.cache);
+ }
+
+#if 0
+ for(i=0; i<2; i++)
+ {
+ if(copy_from_user(&(node->effective.cap[i]), &(data[i]->effective), sizeof(node->effective.cap[i])))
+ {
+ return -EFAULT;
+ }
+ }
+#endif
+
+ node->effective.cap[0] = simple_strtoul(cap_user_data[0], NULL, 0);//char -> u32
+ node->effective.cap[1] = simple_strtoul(cap_user_data[3], NULL, 0);
+ //printk(KERN_INFO “kernel cap : sys_cap_user_set() cap[0] = 0x%x\n”, node->effective.cap[0]);
+ //printk(KERN_INFO “kernel cap : sys_cap_user_set() cap[1] = 0x%x\n”, node->effective.cap[1]);
+
+ return 0;
+}
+
+
extern void __init security_fixup_ops(struct security_operations *ops);
@@ -61,6 +63,7 @@
security_fixup_ops(&default_security_ops);
security_ops = &default_security_ops;
do_security_initcalls();
+ cap_user_init();
return 0;
}