¿Cómo determinar si el código se está ejecutando en el contexto del manejador de señales?

smcdow:

Me acabo de enterar de que alguien está llamando, desde un controlador de señales, una función que no es segura para señales asíncronas y que escribí.

Entonces, ahora tengo curiosidad: ¿cómo evitar que esta situación vuelva a suceder? Me gustaría poder determinar fácilmente si mi código se está ejecutando en el contexto del controlador de señales (el lenguaje es C, pero ¿no se aplicaría la solución a ningún idioma?):

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

Esto es bajo Linux. Espero que no sea una respuesta fácil o me sentiré como un idiota.

ninjalj:

Aparentemente, el Linux / x86 más nuevo (probablemente desde algunos kernel 2.6.x) llama a los controladores de señales desde vdso. Podrías usar este hecho para infligir el siguiente truco horrible al mundo desprevenido:

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

Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.

En caso de infracción, por favor [email protected] Eliminar

Editado en
0

Déjame decir algunas palabras

0Comentarios
Iniciar sesiónRevisión de participación posterior

Artículos relacionados

Detectar si el código se está ejecutando en el contexto del comando migrate / makemigrations

Cómo determinar si flutter se está ejecutando en el simulador

Cómo determinar si flutter se está ejecutando en el simulador

En ColdFusion, ¿hay alguna forma de determinar en qué servidor se está ejecutando el código?

Cómo comprobar si el código se está ejecutando en sitios web de Azure

¿Cómo puedo determinar mediante programación si mi aplicación se está ejecutando en el simulador de iPhone?

¿Cómo cambiar el manejador de señales en proceso hijo?

¿Cómo cambiar el manejador de señales en proceso hijo?

El código del script de contenido no se está ejecutando

¿Cómo comprobar si el código se está ejecutando en segundo plano o no?

¿Cómo puedo determinar si existe una variable dentro del código Groovy se ejecuta en el motor de scripting?

¿Cómo puedo comprobar en tiempo de ejecución si una aplicación de rails se está ejecutando en el contexto de un trabajador sidekiq?

¿Cómo verificar si el código se está ejecutando dentro de eval ()?

No se encontró el manejador de señales

Cómo determinar si un código Swift se está ejecutando dentro de XCode Playground

VuePress: determina si se está ejecutando en contexto de pre-renderizado o en el navegador

¿Cómo determinar en qué navegador se está ejecutando el script de fondo de su extensión?

¿Cómo determinar en qué navegador se está ejecutando el script de fondo de su extensión?

¿Cómo obtener el nombre del nodo en el que se está ejecutando mi código en el servicio de tejido azul?

¿Cómo determinar si un complemento de Office se está ejecutando en Excel o Excel Online?

Compruebe si el hilo se está ejecutando o no en c #

En Scala.js, ¿cómo puede el código detectar si se está ejecutando en una ventana del navegador o en un WebWorker?

El manejador de señales SIGTERM no imprime en una consola

Cómo cerrar correctamente un archivo con el manejador de señales

printf interbloqueo: algunos mensajes de printf se ignoran si se usa printf en el manejador de señales

El manejador de señales QML no responde a la señal C ++

Clojure: ¿cómo saber si el código se está ejecutando en REPL o en un JAR?

¿Cómo puedo ver si el depurador GoLand se está ejecutando en el programa?

iOS WatchKit: cómo determinar si su código se está ejecutando en la extensión del reloj o en la aplicación