es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

No se puede mapear después de cambiar al modo de 64 bits en un proceso de espacio de usuario de Linux que se inició como 32 bits.

Intenté hacer una llamada al sistema mmap después de cambiar al modo de 64 bits en Linux x86 (versión de Linux 5.15.6), pero la llamada al sistema devuelve ENOMEM. Un ejemplo mínimo y reproducible se muestra en el siguiente código en ensamblador:

.text
.global _start

_start:
.code32

jmp $0x33, $start64 // jmp a start64 y cambiar al modo de 64 bits

.code64
start64:

mov $9, %rax // mmap
mov $0, %rdi // NULL
mov $0x1000, %rsi // tamaño
mov $1, %rdx // PROT_READ
mov $0x22, %r10
mov $0, %r8
mov $0, %r9
syscall

mov $60, %rax // salida estilo de 64 bits
mov $0, %rdi
syscall

La salida correspondiente de strace es:

code
execve("./mmap_test32", ["./mmap_test32"], 0x7ffe0ccd7920 /* 60 vars */) = 0
mmap(NULL, 4096, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) = -1 ENOMEM (No se puede asignar memoria)
exit(0) = ?
+++ exited with 0 +++

¿Alguien tiene idea de por qué esto no funciona?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El problema es que el código está cambiando al modo de 64 bits pero aún utiliza registros de 32 bits en la llamada al sistema mmap. Específicamente, la instrucción mov $0x22, %r10 intenta establecer el parámetro flags (quinto parámetro) de la llamada al sistema mmap, pero %r10 es un registro de 64 bits y no se establece correctamente la bandera de 32 bits MAP_PRIVATE|MAP_ANONYMOUS.

    Para solucionar esto, cambie la instrucción mov $0x22, %r10 a mov $0x22, %r10w para que solo se establezcan los 16 bits inferiores de %r10. Esto establecerá correctamente el parámetro flags en MAP_PRIVATE|MAP_ANONYMOUS.

    El código de ensamblador corregido sería:

    .text
    .global _start
    
    _start:
    .code32
    
    jmp $0x33, $start64 // Salta a start64 y cambia al modo de 64 bits
    
    .code64
    start64:
    
    mov $9, %rax // mmap
    mov $0, %rdi // NULL
    mov $0x1000, %rsi // tamaño
    mov $1, %rdx // PROT_READ
    mov $0x22, %r10w // Establece el parámetro flags a MAP_PRIVATE|MAP_ANONYMOUS
    mov $0, %r8
    mov $0, %r9
    syscall
    
    mov $60, %rax // salida en estilo de 64 bits
    mov $0, %rdi
    syscall
    

Comments are closed.