• Uncategorized

About linux : Signal-handling-in-asm-Why-am-I-receiving-SIGSEGV-when-invoking-the-syspause-syscall

Question Detail

I am trying to create an x86_64 assembly program that displays “SIGTERM received” whenever the SIGTERM signal is sent. My application is using Linux syscalls directly:

%define sys_write        0x01
%define sys_rt_sigaction 0x0d
%define sys_pause        0x22
%define sys_exit         0x3c

%define SIGTERM 0x0f

%define STDOUT 0x01


; Definition of sigaction struct for sys_rt_sigaction
struc sigaction
    .sa_handler  resq 1
    .sa_flags    resq 1
    .sa_restorer resq 1
    .sa_mask     resq 1
endstruc


section .data

    ; Message shown when a syscall fails
    error_msg     db  'syscall error', 0x0a
    error_msg_len equ $ - error_msg

    ; Message shown when SIGTERM is received
    sigterm_msg     db  'SIGTERM received', 0x0a
    sigterm_msg_len equ $ - sigterm_msg


section .bss

    act resb sigaction_size
    val resd 1


section .text
global _start

_start:

    ; Initialize act
    lea rax, [handler]
    mov [act + sigaction.sa_handler], rax

    ; Set the handler
    mov rax, sys_rt_sigaction
    mov rdi, SIGTERM
    lea rsi, [act]
    mov rdx, 0x00
    mov r10, 0x08
    syscall

    ; Ensure the syscall succeeded
    cmp rax, 0
    jne error

    ; Pause until a signal is received
    mov rax, sys_pause
    syscall

    ; Upon success, jump to exit
    jmp exit

error:

    ; Display an error message
    mov rax, sys_write
    mov rdi, STDOUT
    mov rsi, error_msg
    mov rdx, error_msg_len
    syscall

    ; Set the return value to one
    mov dword [val], 0x01

exit:

    ; Terminate the application gracefully
    mov rax, sys_exit
    mov rdi, [val]
    syscall

handler:

    ; Display a message
    mov rax, sys_write
    mov rdi, STDOUT
    mov rsi, sigterm_msg
    mov rdx, sigterm_msg_len
    syscall

    ret

When I run the application, it hangs (as expected) at the sys_pause syscall but when I send the SIGTERM signal, it crashes with a segmentation fault.

So I loaded the application into GDB to figure out what was happening:

(gdb) break _start
Breakpoint 1 at 0x4000b0
(gdb) run
Starting program: [...] 

Breakpoint 1, 0x00000000004000b0 in _start ()
(gdb) info proc
process 9639
(gdb) continue
Continuing.

The GDB session hung and I then opened another terminal and ran kill SIGTERM 9639. This resulted in the following output:

Program received signal SIGTERM, Terminated.
0x00000000004000ec in _start ()

I then ran:

(gdb) disas _start
Dump of assembler code for function _start:
   0x00000000004000b0 <+0>:     lea    0x400123,%rax
   0x00000000004000b8 <+8>:     mov    %rax,0x600160
   0x00000000004000c0 <+16>:    mov    $0xd,%eax
   0x00000000004000c5 <+21>:    mov    $0xf,%edi
   0x00000000004000ca <+26>:    lea    0x600160,%rsi
   0x00000000004000d2 <+34>:    mov    $0x0,%edx
   0x00000000004000d7 <+39>:    mov    $0x8,%r10d
   0x00000000004000dd <+45>:    syscall 
   0x00000000004000df <+47>:    cmp    $0x0,%rax
   0x00000000004000e3 <+51>:    jne    0x4000ee <error>
   0x00000000004000e5 <+53>:    mov    $0x22,%eax
   0x00000000004000ea <+58>:    syscall 
=> 0x00000000004000ec <+60>:    jmp    0x400114 <exit>
End of assembler dump.

Then I continued the application:

(gdb) continue
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x00000000004000ec in _start ()

The signal handler is never invoked and the application has crashed.

What am I doing wrong?

Question Answer

You may also like...

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.