causando uma reinicialização do espaço do usuário

0

Este programa, escrito para o Gnu Assembler em um sistema linux x86, deve causar uma falha tripla e depois reinicializar.

.text
.global _start
_start:
# write our string to stdout

    movl    $len,%edx   # third argument: message length
    movl    $msg,%ecx   # second argument: pointer to message to write
    movl    $1,%ebx     # first argument: file handle (stdout)
    movl    $4,%eax     # system call number (sys_write)
    int $0x80       # call kernel
# Triple Fault -- reboot
    movq    $1, %rsp    # Load the stack pointer with a one
    pushq    %rax       # Push the A register, should cause a triple fault.

# and exit

    movl    $0,%ebx     # first argument: exit code
    movl    $1,%eax     # system call number (sys_exit)
    int $0x80       # call kernel

.data                   # section declaration

msg:
    .ascii  "Will reboot by triple fault!\n"    # our dear string
    len = . - msg           # length of our dear string

Causa uma falha de segmentação. É possível fazer isso funcionar no modo de usuário, Se correr como root?

    
por Thomas Bodine 10.08.2012 / 21:24

4 respostas

5

O kernel do Linux não permite que o usuário faça coisas que possam afetar outros usuários. Como root, você pode fazer algo assim, mas o kernel ainda pode impedir tal controle direto; afinal, um processo raiz ainda é um processo userland, mas que tem acesso irrestrito às chamadas do sistema do kernel.

Uma abordagem mais correta / UNIXy é executar esse tipo de ação no kernel e expor uma interface que os processos de userland podem usar para invocá-lo. Em seguida, seu código será executado no contexto do kernel e terá acesso total aos recursos de hardware / sistema aos quais os usuários normalmente não devem ter acesso.

    
por 10.08.2012 / 22:04
4

Falhas de CPU como esta são tratadas pelos manipuladores de interrupção do modo kernel. O código do kernel é bom e, se ocorrer uma falha na terra do usuário (como dividir por zero ou acessar a memória inválida), o primeiro manipulador de interrupção deve manipulá-lo corretamente. Qualquer outra coisa é um bug no kernel - se houver uma falha em um manipulador de interrupção, basicamente a única coisa sã a fazer é descarregar registradores e empilhar, e cair em um depurador (como o OpenBSD faz) ou HCF para que a mensagem de pânico possa ser escrito. Existem falhas triplas porque, a essa altura, o seu código não está funcionando.

TL; DR: Para que isso funcione, você precisa encontrar um bug no código de tratamento de falhas no Linux.

Você pode fazer isso em um módulo do kernel que destrua intencionalmente os manipuladores de interrupção, mas também é muito provável que você bloqueie o sistema. Não é o mesmo efeito que shutdown -r now !

    
por 10.08.2012 / 22:43
1

No Linux, você pode usar a chamada do sistema reboot :

#include <unistd.h>
#include <sys/reboot.h>

int main(void) {
    return reboot(LINUX_REBOOT_CMD_RESTART);
}
    
por 10.08.2012 / 23:01
0

Se você realmente precisa de assembler (?!), isso costumava funcionar a partir do root (com nasm, eu acho):

BITS    32
    mov eax, 88
    mov ebx, 0xfee1dead
    mov ecx, 85072278
    mov edx, 0x01234567
    int  0x80
    
por 10.08.2012 / 23:08