gpt4 book ai didi

linux - 如何确定代码是否在信号处理程序上下文中运行?

转载 作者:IT王子 更新时间:2023-10-29 00:00:40 24 4
gpt4 key购买 nike

我刚刚发现有人正在调用 - 从信号处理程序 - 我编写的绝对不是异步信号安全的函数。

所以,现在我很好奇:如何避免这种情况再次发生?我希望能够轻松确定我的代码是否在信号处理程序上下文中运行(语言是 C,但该解决方案是否适用于任何语言?):

int myfunc( void ) {
if( in_signal_handler_context() ) { return(-1) }
// rest of function goes here
return( 0 );
}

这是在 Linux 下。希望这不是一个简单的答案,否则我会觉得自己像个白痴。

最佳答案

显然,较新的 Linux/x86(可能自某些 2.6.x 内核起)从 vdso 调用信号处理程序。您可以利用这一事实对毫无戒心的世界造成以下可怕的黑客攻击:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>

#include <unistd.h>

uintmax_t vdso_start = 0;
uintmax_t vdso_end = 0; /* actually, next byte */

int check_stack_for_vdso(uint32_t *esp, size_t len)
{
size_t i;

for (i = 0; i < len; i++, esp++)
if (*esp >= vdso_start && *esp < vdso_end)
return 1;

return 0;
}

void handler(int signo)
{
uint32_t *esp;

__asm__ __volatile__ ("mov %%esp, %0" : "=r"(esp));
/* XXX only for demonstration, don't call printf from a signal handler */
printf("handler: check_stack_for_vdso() = %d\n", check_stack_for_vdso(esp, 20));
}

void parse_maps()
{
FILE *maps;
char buf[256];
char path[7];
uintmax_t start, end, offset, inode;
char r, w, x, p;
unsigned major, minor;

maps = fopen("/proc/self/maps", "rt");
if (maps == NULL)
return;

while (!feof(maps) && !ferror(maps)) {
if (fgets(buf, 256, maps) != NULL) {
if (sscanf(buf, "%jx-%jx %c%c%c%c %jx %u:%u %ju %6s",
&start, &end, &r, &w, &x, &p, &offset,
&major, &minor, &inode, path) == 11) {
if (!strcmp(path, "[vdso]")) {
vdso_start = start;
vdso_end = end;
break;
}
}
}
}

fclose(maps);

printf("[vdso] at %jx-%jx\n", vdso_start, vdso_end);
}

int main()
{
struct sigaction sa;
uint32_t *esp;

parse_maps();
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = handler;
sa.sa_flags = SA_RESTART;

if (sigaction(SIGUSR1, &sa, NULL) < 0) {
perror("sigaction");
exit(1);
}

__asm__ __volatile__ ("mov %%esp, %0" : "=r"(esp));
printf("before kill: check_stack_for_vdso() = %d\n", check_stack_for_vdso(esp, 20));

kill(getpid(), SIGUSR1);

__asm__ __volatile__ ("mov %%esp, %0" : "=r"(esp));
printf("after kill: check_stack_for_vdso() = %d\n", check_stack_for_vdso(esp, 20));

return 0;
}

SCNR.

关于linux - 如何确定代码是否在信号处理程序上下文中运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4832743/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com