一   使用gdb工具跟踪分析一个自添加的系统调用

应用程序的进程通常在用户空间下运行,当它调用一个系统调用时,进程进入内核空间,执行的是kernel内部的代码,从而具有执行特权指令的权限,完成特定的功能。

在上次实验的基础上修改test.c,添加自己实现的setuid系统调用,部分代码修改如下:

 int uid_c()
{
int i=65535,k=0;
i=getuid();
printf("current user id is:%d\n",i); setuid(200);
k=getuid();
printf("after change uid:%d\n",k); return 0;
} int uid_asm()
{
int i=65535,j=200,k=0;
asm volatile(
"mov $0,%%ebx\n\t"
"mov $0x18,%%eax\n\t"
"int $0x80\n\t"
"mov %%eax,%0\n\t"
:"=m"(i)
);
printf("cureent user id is:%d\n",i);
asm volatile(
"mov $0,%%ebx\n\t"
"mov $0x17,%%eax\n\t"
"mov %1,%%ebx\n\t"
"int $0x80\n\t"
// "mov %1,%%ebx\n\t"
"mov %%eax,%0\n\t"
:"=m"(i)
:"c"(j)
); asm volatile(
"mov $0,%%ebx\n\t"
"mov $0x18,%%eax\n\t"
"int $0x80\n\t"
"mov %%eax,%0\n\t"
:"=m"(k)
);
printf("after change user id is:%d\n",k); return 0;
} int main()
{
PrintMenuOS();
SetPrompt("MenuOS>>");
MenuConfig("version","MenuOS V1.0(Based on Linux 3.18.6)",NULL);
MenuConfig("quit","Quit from MenuOS",Quit);
MenuConfig("time","Show System Time",Time);
MenuConfig("time-asm","Show System Time(asm)",TimeAsm);
MenuConfig("uid","Show user id",uid_c); //添加的部分
MenuConfig("uid-asm","Show user id(asm)",uid_asm); //添加的部分
ExecuteMenu();
}

  重新编译执行:在原程序的基础上添加了两条命令uid和uid-asm,如下图

下面使用gdb工具进行调试:

1. 设置断点

输入c执行:

程序停在start_kernel;

继续执行:

程序停在rest_init;

接着执行:

接下来输入自己添加的命令uid和uid_asm

程序停在sys_getuid16函数的地方,执行就显示结果:

显示的结果:

二  system_call 过程分析

附上代码:

ENTRY(system_call)
RING0_INT_FRAME # can't unwind into user space anyway
ASM_CLAC
pushl_cfi %eax # save orig_eax
SAVE_ALL
GET_THREAD_INFO(%ebp)
# system call tracing in operation / emulation
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
jnz syscall_trace_entry
cmpl $(NR_syscalls), %eax
jae syscall_badsys
syscall_call:
call *sys_call_table(,%eax,4)
syscall_after_call:
movl %eax,PT_EAX(%esp) # store the return value
syscall_exit:
LOCKDEP_SYS_EXIT
DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt
# setting need_resched or sigpending
# between sampling and the iret
TRACE_IRQS_OFF
movl TI_flags(%ebp), %ecx
testl $_TIF_ALLWORK_MASK, %ecx # current->work
jne syscall_exit_work restore_all:
TRACE_IRQS_IRET
restore_all_notrace:
#ifdef CONFIG_X86_ESPFIX32
movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
# Warning: PT_OLDSS(%esp) contains the wrong/random values if we
# are returning to the kernel.
# See comments in process.c:copy_thread() for details.
movb PT_OLDSS(%esp), %ah
movb PT_CS(%esp), %al
andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
CFI_REMEMBER_STATE
je ldt_ss # returning to user-space with LDT SS
#endif
restore_nocheck:
RESTORE_REGS 4 # skip orig_eax/error_code
irq_return:
INTERRUPT_RETURN
.section .fixup,"ax"
ENTRY(iret_exc)
pushl $0 # no error code
pushl $do_iret_error
jmp error_code
.previous
_ASM_EXTABLE(irq_return,iret_exc) #ifdef CONFIG_X86_ESPFIX32
CFI_RESTORE_STATE
ldt_ss:
#ifdef CONFIG_PARAVIRT
/*
* The kernel can't run on a non-flat stack if paravirt mode
* is active. Rather than try to fixup the high bits of
* ESP, bypass this code entirely. This may break DOSemu
* and/or Wine support in a paravirt VM, although the option
* is still available to implement the setting of the high
* 16-bits in the INTERRUPT_RETURN paravirt-op.
*/
cmpl $0, pv_info+PARAVIRT_enabled
jne restore_nocheck
#endif /*
* Setup and switch to ESPFIX stack
*
* We're returning to userspace with a 16 bit stack. The CPU will not
* restore the high word of ESP for us on executing iret... This is an
* "official" bug of all the x86-compatible CPUs, which we can work
* around to make dosemu and wine happy. We do this by preloading the
* high word of ESP with the high word of the userspace ESP while
* compensating for the offset by changing to the ESPFIX segment with
* a base address that matches for the difference.
*/
#define GDT_ESPFIX_SS PER_CPU_VAR(gdt_page) + (GDT_ENTRY_ESPFIX_SS * 8)
mov %esp, %edx /* load kernel esp */
mov PT_OLDESP(%esp), %eax /* load userspace esp */
mov %dx, %ax /* eax: new kernel esp */
sub %eax, %edx /* offset (low word is 0) */
shr $16, %edx
mov %dl, GDT_ESPFIX_SS + 4 /* bits 16..23 */
mov %dh, GDT_ESPFIX_SS + 7 /* bits 24..31 */
pushl_cfi $__ESPFIX_SS
pushl_cfi %eax /* new kernel esp */
/* Disable interrupts, but do not irqtrace this section: we
* will soon execute iret and the tracer was already set to
* the irqstate after the iret */
DISABLE_INTERRUPTS(CLBR_EAX)
lss (%esp), %esp /* switch to espfix segment */
CFI_ADJUST_CFA_OFFSET -8
jmp restore_nocheck
#endif
CFI_ENDPROC
ENDPROC(system_call)

  凭着自己的理解,简要的画了一张流程图:

三   总结

对系统调用过程的理解:从上次课我们了解到系统调用是通过用户态进程发出int $0x80,cpu从用户态切换到内核态,从这次课我们可以了解到确切的说是从system_call处开始执行。首先进行地址空间的切换和堆栈的切换,对用户空间的数据进行保存,接着根据作为参数传递的系统调用号找到对应的系统调用服务例程,在例程处理完后,对返回值进行保存,当要返回用户空间时,仍然要执行很多检测,因为一般的现代操作系听都是多任务系统,返回时就要检测申请系统调用的用户进程是否拥有执行时间,所以就有一些检测信号量,检测调度等等操作,当发生调度时,恢复的现场就是其他用户进程以前某个时刻保存的现场。就这样循环。。。。可以说,系统调用过程就是中断处理过程的典型应用实例。。。。

by:方龙伟

原创作品 转载请注明出处

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

linux 内核学习之五 system_call过程分析的更多相关文章

  1. linux 内核学习之八 进程调度过程分析

    一  关于进程的补充 进程调度的时机 中断处理过程(包括时钟中断.I/O中断.系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule() ...

  2. Linux内核分析——Linux内核学习总结

    马悦+原创作品转载请注明出处+<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 Linux内核学习总结 一 ...

  3. 关于Linux内核学习的一点点总结

    关于Linux内核学习的一点点总结 关键词:Linux, 操作系统,内核 博客列表 由反汇编C程序来理解计算机是如何工作的 通过分析一个简化版时间片轮转多道程序内核代码来认识操作系统中的进程调度 通过 ...

  4. Linux 内核学习的经典书籍及途径

    from:http://www.zhihu.com/question/19606660 知乎 Linux 内核学习的经典书籍及途径?修改 修改 写补充说明 举报   添加评论 分享 • 邀请回答   ...

  5. 关于Linux内核学习的误区以及相关书籍介绍

    http://www.hzlitai.com.cn/article/ARM9-article/system/1605.html 写给Linux内核新手-关于Linux内核学习的误区 先说句正经的:其实 ...

  6. linux内核学习之二:编译内核

    在linux内核学习系列的第一课中讲述了搭建学习环境的过程(http://www.cnblogs.com/xiongyuanxiong/p/3523306.html),环境搭好后,马上就进入到下一环节 ...

  7. linux内核学习之一:环境搭建--安装Debian7.3

    本系列文章假设读者已对linux有一定的了解,其实学习linux内核不需要有很深的关于linux的知识,只需要了解以下内容:linux基础知识及基本shell命令:现代操作系统的基本概念:C语言和gc ...

  8. Linux内核学习笔记-2.进程管理

    原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

  9. Linux内核学习笔记-1.简介和入门

    原创文章,转载请注明:Linux内核学习笔记-1.简介和入门 By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

随机推荐

  1. stst

    静态代码块如果不要static 那么只要生成新的该对象,则会执行{}内的代码 super.onDestroy() 先后顺序问题 Ctrl + Alt + F refromat code目前看来不能对代 ...

  2. rgb转16进制 简单实现

    function rgbToHex(r, g, b) { return ((r << 16) | (g << 8) | b).toString(16); }

  3. 解决iscroll5在手机页面上onclick事件失效

    Iscroll.js使用之后页面上面A标签的onclick事件无效了   解决办法 实例化IScroll的时候把preventDefault设为false,默认为true var myScroll; ...

  4. 【Java】变量类接口_学习笔记

    变量.类和接口 1.变量的类型 实例变量(不以static修饰) 成员变量 类变量(以static修饰) 所有变量 形参(方法签名中定义的变量) 局部变量         方法局部变量(在方法内定义) ...

  5. function方法中this的用法

    jsp<select class="mokuai2" onchange="Mokuai2Change(this.value)"></selec ...

  6. 误删除libc.so.6 恢复

    一.我是怎样一步一步毁掉系统的 最近在centos 7上进行开发.由于需要使用高版本linux内核的特性,需要将linux内核升级.按照教程:centos 7升级内核 进行升级的时候发现在安装elre ...

  7. Hibernate连数据库

    1.建数据库,建表(一定要设主码) create database Hibernate create table Students( sno char(10) primary key, sna cha ...

  8. Appium 服务关键字

    Appium 服务关键字 关键字 描述 实例 automationName 你想使用的自动化测试引擎 Appium (默认) 或 Selendroid platformName 你要测试的手机操作系统 ...

  9. AX2012单元格显示颜色 displayOption

    public void displayOption(HV_WMSLocationStatusHistory _record, FormRowDisplayOption _options){    #d ...

  10. idea安装