How to determine if code is running in signal-handler context?

前端 未结 6 1305
一生所求
一生所求 2021-02-03 11:11

I just found out that someone is calling - from a signal handler - a definitely not async-signal-safe function that I wrote.

So, now I\'m curious: how to circumvent this

6条回答
  •  暖寄归人
    2021-02-03 11:14

    Apparently, newer Linux/x86 (probably since some 2.6.x kernel) calls signal handlers from the vdso. You could use this fact to inflict the following horrible hack upon the unsuspecting world:

    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include 
    
    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.

提交回复
热议问题