分享
 
 
 

内核处理信号对应用层堆栈的影响

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

本文着重点在内核信号处理对应用层堆栈的影响上,其他的一些在处理信号细节上被忽略。

至于本文是否跟安全相关,那就是仁者见仁智者见智了。

1 发送信号过程:

发送信号的过程比接收信号的过程简单的多。当应用层用KILL命令向某个进程发送进程的时候,内核只在进程task_struct的sigpending结构中安排一个信号位。

2 接收信号过程

信号处理的时机。

当某个进程有悬而未决的信号的时候,内核就会调用do_signal函数

do_signal做一些其他功能上的事情,真正递送一个信号是在handle_signal函数。于是在最后do_signal函数调用了handle_signal真正递送一个信号。当然要想到达这一步需要一些条件。比如说应用层已经声明要处理该信号,信号不是些不可捕获的信号等等...

重点中的重点,我们来看看handle_signal函数

/*

* OK, we're invoking a handler

*/

static void

handle_signal(unsigned long sig, struct k_sigaction *ka,

siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)

{

....

/* Set up the stack frame */

if (ka-sa.sa_flags & SA_SIGINFO)

setup_rt_frame(sig, ka, info, oldset, regs);

else

setup_frame(sig, ka, oldset, regs);

.....

}

去掉一些我们不想关心的东西,代码就剩下上面这些。

以上函数setup_rt_frame和setup_frame就是内核在应用层的堆栈上安排信号堆栈帧的过程,就是我们所要关注的。setup_rt_frame和setup_frame雷同,我们就来分析下setup_frame函数。

static void setup_frame(int sig, struct k_sigaction *ka,

sigset_t *set, struct pt_regs * regs)

{

struct sigframe *frame;

int err = 0;

frame = get_sigframe(ka, regs, sizeof(*frame)); //决定要使用应用层堆栈的地址

if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) //判断是否可写

goto give_sigsegv;

err |= __put_user((current-exec_domain

&& current-exec_domain-signal_invmap

&& sig

? current-exec_domain-signal_invmap[sig]

: sig),

&frame-sig);

if (err)

goto give_sigsegv;

/*保存寄存器信号到&frame-sc和&frame-fpstate中*/

err |= setup_sigcontext(&frame-sc, &frame-fpstate, regs, set-sig[0]);

if (err)

goto give_sigsegv;

if (_NSIG_WORDS 1) {

err |= __copy_to_user(frame-extramask, &set-sig[1],

sizeof(frame-extramask));

}

if (err)

goto give_sigsegv;

/* Set up to return from userspace. If provided, use a stub

already in userspace. */

if (ka-sa.sa_flags & SA_RESTORER) {

err |= __put_user(ka-sa.sa_restorer, &frame-pretcode);

} else {

/*把frame-retcod的地址放到&frame-pretcode中,这样当信号处理函数返回时候就会*/

/*跳到frame-retcode地址去执行代码了*/

err |= __put_user(frame-retcode, &frame-pretcode);

/* This is popl %eax ; movl $,%eax ; int $0x80 */

err |= __put_user(0xb858, (short *)(frame-retcode+0));

err |= __put_user(__NR_sigreturn, (int *)(frame-retcode+2));

err |= __put_user(0x80cd, (short *)(frame-retcode+6));

/*以上在frame-retcode上安排了popl %eax ; movl $,%eax ; int $0x80指令*/

}

if (err)

goto give_sigsegv;

/* Set up registers for signal handler */

regs-esp = (unsigned long) frame; //让应用层的esp指向frame;

regs-eip = (unsigned long) ka-sa.sa_handler;//EIP为信号处理函数

set_fs(USER_DS);

regs-xds = __USER_DS;

regs-xes = __USER_DS;

regs-xss = __USER_DS;

regs-xcs = __USER_CS;

regs-eflags &= ~TF_MASK;

#if DEBUG_SIG

printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",

current-comm, current-pid, frame, regs-eip, frame-pretcode);

#endif

return;

give_sigsegv:

if (sig == SIGSEGV)

ka-sa.sa_handler = SIG_DFL;

force_sig(SIGSEGV, current);

}

到此,内核在应用层的堆栈上就安排了一个帧,我们来看一下一个实际的例子。

[alert7@redhat73 sigal]$ cat test.c

test ()

{

printf("test");

return;

}

int main(int argv,char **argc) {

char buf[256];

signal(10,test);

while(1);

}

[alert7@redhat73]

(gdb) b main

Breakpoint 1 at 0x8048501

(gdb) r dd dd

Starting program: /home/alert7/sigal/test dd dd

Breakpoint 1, 0x08048501 in main ()

(gdb)

Breakpoint 2 at 0x42029098

(gdb) c

Continuing.

(gdb) x/5i 0x42029098

0x42029098 : pop %eax

0x42029099 : mov $0x77,%eax

0x4202909e : int $0x80

0x420290a0 : mov (%esp,1),%ebx

0x420290a3 : ret

(gdb) i reg esp ebp eip

esp 0xbffff748 0xbffff748

ebp 0xbffffb38 0xbffffb38

eip 0x4202909e 0x4202909e

(gdb) x/50x $esp-8 //$esp-8就是内核构造的一个信号帧

0xbffff740: 0x42029098 0x0000000a 0x00000000 0x00000000

0xbffff750: 0x0000002b 0x0000002b 0xbffffba4 0x40013020

0xbffff760: 0xbffffb38 0xbffffa20 0x4213030c 0xbffffc00

0xbffff770: 0x08049752 0xbffffb2c 0x00000001 0x00000000

0xbffff780: 0x08048570 0x00000023 0x00000346 0xbffffa20

0xbffff790: 0x0000002b 0x00000000 0x00000000 0x00000000

0xbffff7a0: 0x4000083e 0x400005b8 0x40000218 0x400131e8

0xbffff7b0: 0x00000003 0x40013e48 0x00000003 0x42009e38

0xbffff7c0: 0x40013d68 0x0d1fc7ae 0x0d1fc7ae 0xbffff890

0xbffff7d0: 0x40013bc8 0x4200f624 0x00000000 0x00000000

0xbffff7e0: 0x42009e38 0x40013bc8 0x00000000 0x00000000

0xbffff7f0: 0x00000000 0x00000000 0x00000000 0x00000000

0xbffff800: 0x00000000 0x00000000

struct sigframe

{

char *pretcode; //这里为0x42029098,在该程序中,ka-sa.sa_flags 有 SA_RESTORER标志,

//所以没有在堆栈中安排指令,而是使用了一个现成的地址

int sig; //信号为10

struct sigcontext sc;

struct _fpstate fpstate;

unsigned long extramask[_NSIG_WORDS-1];

char retcode[8];

};

struct sigcontext {

unsigned short gs, __gsh;//0,0

unsigned short fs, __fsh;//0,0

unsigned short es, __esh;//0x2b,0

unsigned short ds, __dsh;//0x2b,0

unsigned long edi; //0xbffffba4

unsigned long esi; //0x40013020

unsigned long ebp; //0xbffffb38

unsigned long esp; //0xbffffa20

unsigned long ebx; //0x4213030c

unsigned long edx; //0xbffffc00

unsigned long ecx; //0x08049752

unsigned long eax; //0xbffffb2c

unsigned long trapno; //0x00000001

unsigned long err; //0x00000000

unsigned long eip; //0x08048570

unsigned short cs, __csh; //0x23,0

unsigned long eflags; //0x00000346

unsigned long esp_at_signal; //0xbffffa20

unsigned short ss, __ssh; //0x2b,0

struct _fpstate * fpstate; //0x00000000

unsigned long oldmask; //0x00000000

unsigned long cr2; //0x00000000

};

内核在应用层的堆栈上安了一个帧后,当一返回到应用态的时候就跳到信号处理函数test去执行了。

此时图一 ①,应用层的堆栈多了一个帧,如下:

**********************************************************************************

图一

(内存高址)

+--------------------------------------+

| ... |

+--------------------------------------+

| char retcode[8] | 8个字节

+--------------------------------------+

| long extramask[_NSIG_WORDS-1]; |

+--------------------------------------+

| struct _fpstate fpstate; |

+--------------------------------------+

| struct sigcontext sc; |

+--------------------------------------+

| int sig; |

+--------------------------------------+

| char *pretc

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有