Rob
Rob

Reputation: 97

accept() doesn't block the program execution

I'm starting to program network programs in asm (NASM) and technically, the accept function block the program (passive socket). Well, in my program I execute the program and the program finish. I've tested setting the backlog to 1 (listen function), but it's not the problem... What happen?

BITS 32

section .text
global _start
_start:
; Create the socket file descriptor
; int socket(int domain, int type, int protocol);

mov eax, 102  ; __NR_socketcall
mov ebx, 1    ; socketcall type (socket)

; socket parameters
push 0  ; IPPROTO_TCP
push 1  ; SOCK_STREAM
push 2  ; AF_INET

int 0x80  ; socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)

mov edx, eax  ; edx = socketfd


; Bind the socket with an address type
; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

mov eax, 102  ; __NR_socketcall
mov ebx, 2    ; socketcall type (bind)

; build the sockaddr_in struct
push 0            ; INADDR_ANY
push WORD 0x0457  ; port 1111
push WORD 2       ; AF_INET
mov ecx, esp      ; struct ptr

; bind parameters
push 16   ; sockaddr struct size = sizeof(struct sockaddr) = 16
push ecx  ; sockaddr_in struct ptr
push edx  ; socket fd

int 0x80  ; bind(sockfd, {AF_INET, 11111, INADDR_ANY}, 16)


; Prepare to listen the incoming connection (passive socket)
; int listen(int sockfd, int backlog);

mov eax, 102  ; __NR_socketcall
mov ebx, 4    ; socketcall type (listen)

; listen parameters
push 0    ; nº connections in the waiting queue (0 = accept and we haven't queue)
push edx  ; socket fd

int 0x80  ; listen(sockfd, 0);


; Accept the incoming connection
; int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

mov eax, 102  ; __NR_socketcall
mov ebx, 5    ; socketcall type (accept)

; accept parameters
push 0
push 0
push edx  ; socket fd

int 0x80  ; accept(sockfd, NULL, NULL)

; Exit
; int exit(int status)

mov eax, 1 ; __NR_exit
mov ebx, 0 ; exit code

int 0x80

Upvotes: 2

Views: 134

Answers (1)

Anya Shenanigans
Anya Shenanigans

Reputation: 94789

you're missing a mov ecx, esp after the last push for each of your argument pushes, as well as htons'ing the port number. A fixed version of you code should look like:

BITS 32

section .text
global _start
_start:
; Create the socket file descriptor
; int socket(int domain, int type, int protocol);

mov eax, 102  ; __NR_socketcall
mov ebx, 1    ; socketcall type (socket)

; socket parameters
push 6  ; IPPROTO_TCP
push 1  ; SOCK_STREAM
push 2  ; AF_INET
mov ecx, esp ; <<== uargs* in ecx

int 0x80  ; socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)

mov edx, eax  ; edx = socketfd


; Bind the socket with an address type
; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

mov eax, 102  ; __NR_socketcall
mov ebx, 2    ; socketcall type (bind)

; build the sockaddr_in struct
push 0            ; INADDR_ANY
push WORD 0x5704  ; port 1111 == htons(1111)
push WORD 2       ; AF_INET
mov ecx, esp      ; struct ptr

; bind parameters
push 16   ; sockaddr struct size = sizeof(struct sockaddr) = 16
push ecx  ; sockaddr_in struct ptr
push edx  ; socket fd
mov ecx, esp      ; <<== uargs* in ecx

int 0x80  ; bind(sockfd, {AF_INET, 11111, INADDR_ANY}, 16)


; Prepare to listen the incoming connection (passive socket)
; int listen(int sockfd, int backlog);

mov eax, 102  ; __NR_socketcall
mov ebx, 4    ; socketcall type (listen)

; listen parameters
push 0    ; nº connections in the waiting queue (0 = accept and we haven't queue)
push edx  ; socket fd
mov ecx, esp      ; <<== uargs* in ecx

int 0x80  ; listen(sockfd, 0);


; Accept the incoming connection
; int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

mov eax, 102  ; __NR_socketcall
mov ebx, 5    ; socketcall type (accept)

; accept parameters
push 0
push 0
push edx  ; socket fd
mov ecx, esp      ; struct ptr

int 0x80  ; accept(sockfd, NULL, NULL)

; Exit
; int exit(int status)

mov eax, 1 ; __NR_exit
mov ebx, 0 ; exit code

int 0x80

In this case it would have been important that you did an strace on your program to verify that you were seeing the correct parameters being processed in the system call.

If we strace your original program we get:

socket(PF_UNSPEC, 0, 0)                 = -1 EFAULT (Bad address)
bind(1459879938, NULL, 2)               = -1 EBADF (Bad file descriptor)
listen(1459879938, 0)                   = -1 EBADF (Bad file descriptor)
accept(1459879938, 0, 0x2)              = -1 EBADF (Bad file descriptor)

all of which looks like things went very badly.

If you look at the source for compat_sys_socketcall it shows:

asmlinkage long compat_sys_socketcall(int call, u32 __user *args)

which means EBX is the call and ECX points to the remainder of the arguments.

Upvotes: 2

Related Questions