GNU/Linux >> Tutoriales Linux >  >> Linux

¿Por qué este código falla con la aleatorización de direcciones activada?

sub rsp, <size> para reservar espacio de pila antes de tocarlo, si está utilizando más de 128 bytes por debajo de RSP.

Cuando falla, mira tu mapa de memoria de proceso. Es posible que esté usando memoria tan por debajo de RSP que el núcleo no aumenta la asignación de pila y, por lo tanto, es solo un acceso normal a una página no asignada =falla de página no válida => el núcleo entrega SIGSEGV.

(La ABI solo define una zona roja de 128 bytes, pero en la práctica lo único que puede destruir esa memoria es un controlador de señal (que no instaló) o GDB que ejecuta print some_func() usando la pila de su programa para llamar a una función en su programa.)

Normalmente, Linux está bastante dispuesto a hacer crecer el mapeo de la pila sin tocar las páginas intermedias, pero aparentemente verifica el valor de RSP. Normalmente mueves RSP en lugar de simplemente usar la memoria muy por debajo del puntero de la pila (porque no hay garantía de que sea seguro). Consulte ¿Cómo se asigna la memoria de pila cuando se usan instrucciones x86 'push' o 'sub'?

Otro duplicado:¿Qué excepción se puede generar al restar el registro ESP o RSP? (crecimiento de la pila) donde se usa sub rsp, 5555555 antes de tocar nueva memoria de pila fue suficiente.

Apilar ASLR podría iniciar RSP en diferentes lugares en relación con un límite de página , por lo que es posible que a veces apenas te salgas con la tuya. Linux asigna inicialmente 132 kiB de espacio de pila , y eso incluye espacio para el entorno y argumentos en la pila al ingresar a _start . Tus 128 kiB están muy cerca de eso, por lo que es totalmente plausible que a veces funcione aleatoriamente.

Y, por cierto, no hay ninguna razón para copiar la memoria en el espacio del usuario, especialmente no 1 byte a la vez. Solo pasa la misma dirección a write .

O al menos filtre en el lugar si es posible, para que su huella de caché sea más pequeña.

Además, la forma normal de cargar un byte es movzx eax, byte [mem] . Solo usa mov al, [mem] si desea fusionar específicamente con el antiguo valor de RAX. En algunas CPU, mov a al tiene una dependencia falsa en el valor anterior que puede romper escribiendo el registro completo.

Y, por cierto, si su programa siempre utiliza este espacio, también podría asignarlo estáticamente en el BSS. Eso hace posible un direccionamiento indexado más eficiente si elige ensamblar un ejecutable dependiente de la posición (no PIE).


La zona roja en amd64 tiene solo 128 bytes, pero está usando 131072 bytes por debajo de rsp. Mueva el puntero de la pila hacia abajo para abarcar los búferes que desea almacenar en la pila.


Linux
  1. ¿Por qué Tomcat funciona con el puerto 8080 pero no con el 80?

  2. ¿Por qué salir del código 141 con grep -q?

  3. La aplicación C++ termina con el código de salida 143. ¿Qué significa?

  4. ¿Por qué este ciclo de retardo comienza a ejecutarse más rápido después de varias iteraciones sin dormir?

  5. ¿Por qué clang todavía necesita libgcc.a para compilar mi código?

¿Por qué la sustitución del proceso Bash no funciona con algunos comandos?

¿Por qué agregar dos puntos rompe este patrón Grep?

¿Por qué Ping -f actúa así?

¿Por qué mi $LD_LIBRARY_PATH se desarma cuando uso screen con bash?

¿Por qué esta expresión regular no funciona en Linux?

¿Por qué mi nombre de host aparece con la dirección 127.0.1.1 en lugar de 127.0.0.1 en /etc/hosts?