免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 784 | 回复: 0
打印 上一主题 下一主题

FC6增加系统调用 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-08-16 19:09 |只看该作者 |倒序浏览
系统:32位x86系统
OS:FC6
内核版本:2.6.18
目的:新增一个系统调用,将当前进程的UID和EUID都设置成0(超级用户)
步骤:
1 内核源码树位置:SRC=/usr/src/redhat/BUILD/kernel2.6.18/linux-2.6.18.i386
2 增加新系统调用号,修改头文件
$SRC/include/arm-i386/unistd.h
   。
   。
   。
#define __NR_splice             313
#define __NR_sync_file_range    314
#define __NR_tee                315
#define __NR_vmsplice           316
#define __NR_move_pages         317
#define __NR_mysyscall          318 /*新增加的一行,其中318是系统调用号,
                                    根据系统不同自己定义与已经有的系统
                                   调用号不相同即可*/
3 修改系统调用表。修改文件
$SRC/arch/i386/kernel/syscall-table.s(注意,以前版本的内核应该修改和前面文件同
级目录下的entry.s)
ENTRY(sys_call_table)
        .long sys_restart_syscall       /* 0 - old "setup()" system call, used
for restarting */
        .long sys_exit
        .long sys_fork
        .long sys_read
        .long sys_write
        .long sys_open          /* 5 */
        .long sys_close
        .long sys_waitpid
        .long sys_creat
        .long sys_link
        .long sys_unlink        /* 10 */
        .
        .
        .
        .long sys_mysyscall           /*新增加一行*/
4 定义新系统调用的具体内容,一般可以直接在$SRC/kernel/sys.c中添加,
当然也可以加入与其功能紧密联系的代码中去。这里我加在$SRC/kernel/sys.c中,
在该文件末尾加入:
asmlinkage int sys_mysyscall(void)
{
        current->uid = current->euid  = 0;
        return 0;
}
5 通常我们在用户层使用系统调用都是通过C库支持来使用的,也就是说C库中对系统调用
进行了一次封装
,可以通过查看glibc的源码可以看到具体封装过程。由于glibc十分庞大,如果我们自己
新定义对上面新增
系统调用的C库函数的话,编译时间太长,所以我想直接利用LINUX提供的宏_syscallN来完
成。
其中N是系统调用的参数个数。举例说明该宏的用法:
对于系统调用open()的定义本来是:
long open(const char* filename,int flags,int mode)
如果不靠c库支持使用该系统调用方法如下:
#define __NR_open 5  /*5是open的系统调用号*/
_syscall3(long,open,const char* filename,flags,mode)
有了这些定义后下面对open可以直接调用了
(一般书上都会讲到这种方法),但是在实际操作过程中,会发现在2.6.X中,已经取消了
宏_syscallN的定义,所以
你在编译的时候是通不过的。当然2.6取消了这些宏定义,我们可以自己在版本的代码中找
出这些宏定义加上即
在2.4.18内核的源代码中,可以在其内核源码树下include/asm-i386/unistd.h中找到这些
宏定义:
#define __syscall_return(type, res) \
do { \
        if ((unsigned long)(res) >= (unsigned long)(-125)) { \
                errno = -(res); \
                res = -1; \
        } \
        return (type) (res); \
} while (0)
#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name)); \
__syscall_return(type,__res); \
}
#define _syscall1(type,name,type1,arg1) \
type name(type1 arg1) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name),"b" ((long)(arg1))); \
__syscall_return(type,__res); \
}
#define _syscall2(type,name,type1,arg1,type2,arg2) \
type name(type1 arg1,type2 arg2) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
__syscall_return(type,__res); \
}



将这些代码copy到你自己的$SRC/include/asm-i386/unistd.h(我在实际中去掉了所有宏

包含变量errno的一行,因为在我们的代码中没有这个变量的定义,即使你在其中加入
extern int errno;
在编译没问题,链接也会有问题的,试试就知道了,如果非要使用errno,那就自己专研吧
,呵呵!)
6 所有准备工作完成,现在就是编译新内核了(可能有人会提到将这个系统调用以模块方
式加载就不用重新
编译内核了,想法是好的,但是考虑到安全问题,不知道是从什么版本开始,已经取消了
对系统调用表
sys_call_table的导出,所以你在模块中是没法访问系统调用表的,当然也可以通过其他
途径来完成这个任务
,不过那是hacker们的办法了,这里不加讨论)
在$SRC中
make menuconfig
make
make install
即可,在2.6中已经对编译内核的方法简化了许多,不需要以前对依赖关系的检查了,新的
Makefile帮助完成这些工作了。
在make install中已经帮你完成了
(1)将新内核镜像bzImage拷贝到/boot/vmlinuz-verison
(2)构建新的initrd-version.img文件
(3)创建新的内核符号表System.map(这个文件不是内核启动必须的,一般调试用)
(4)修改你的grub或者lilo启动文件
所以你只需要reboot就可以看到你新编译的内核了。至于内核的配置和vmlinuz和initrd2
个文件各自的用处,大家可以上网查询,这里
不详细介绍了。如果你的新内核无法启动,多半是initrd出了问题(简单的说下initrd文
件包含了你的内核在加载文件系统前的一些驱动程序
比如硬盘驱动,ext3文件系统的驱动等等,如果这些有问题,内核是无法启动的,网上说
可以把这些一起编译到内核vmlinuz中而不需要initrd,
大家可以去试试)
7 现在新内核启动起来了,我们写一个用户测试程序mysyscall.c使用我们新的系统调用吧

#include
#include
#include
#include
#include
#define __NR_mysyscall 318
_syscall0(int,mysyscall)
int main()
{
        printf("before, my euid is: %d!\n",geteuid());
        if(open("/etc/shadow",O_RDONLY)0)
                printf("open succeed!\n");
      
        return 0;
}
在普通用户下运行该程序
before, my euid is: 500!
open failed!
after, my euid is 0!
open succeed!
发现居然可以访问本来只有root能访问的shadown文件了 o(∩_∩)o!
欢迎大家讨论!
                                                            八戒
                                                          2007。8.14


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/21973/showart_361504.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP