Author Topic: Flags for Linux sys_open in 64-bit NASM  (Read 23830 times)

Offline paml27

  • Jr. Member
  • *
  • Posts: 37
Flags for Linux sys_open in 64-bit NASM
« on: December 05, 2019, 12:35:24 AM »
I created a file in 64-bit NASM on Linux.  Now I want to open it and write data into it.  The file is created, but no data are written.  My code follows:

File_Name: db '/opt/Test_Output_Files/Linux_File_Test',0
File_Mode: dq 754
Write_Buffer: db 'This is what I want to write',0

; Create file
mov rax,85 ; sys_creat
mov rdi,File_Name
mov rsi,File_Mode  ; mode (permissions)
syscall

mov rax,1 ; sys_open
mov rdi,File_Name
mov rsi,2 ;read-write
mov rdx,754
syscall

mov rax,1 ; sys_write
mov rdi,File_Name
mov rsi,Write_Buffer
mov rdx,29
syscall

mov rax,3 ; sys_close
mov rdi,File_Name
syscall

My questions are:
1.  When I create a file in 64-bit Linux is it open for reading and writing, or do I need to issue an open command as well? 

2.  When I open a file in 64-bit Linux, what are the flags?  According to the Linux man page at https://linux.die.net/man/3/open, there are three options: 

O_RDONLY - Open for reading only.
O_WRONLY - Open for writing only.
O_RDWR - Open for reading and writing. The result is undefined if this flag is applied to a FIFO.

I know that read-only is zero, so I assumed write only and read-write are 1 and 2, but I haven't found any listing of the numeric values that we would use in assembly language, unlike the mode which is based on chmod. 

3.  I am doing all of this as a superuser, not as root.  Any special considerations for file handling by a superuser? 

Thanks very much for any help on this. 


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Flags for Linux sys_open in 64-bit NASM
« Reply #1 on: December 05, 2019, 04:41:43 AM »
Hi Pam127,
I don't know much 64 bit code, but a few observations...

I think mode is supposed to be octal. C takes a leading zero to be octal, Nasm does not. You probably want "754q".

Code: [Select]
mov rax, 1 ; sys_open
Code: [Select]
mov rax, 1 ; sys_write
These can't both be right.

sys_create and/or sys_open should return a file descriptor in rax. Use that instead of filename from then on.

1) Dunno. What happens?
2) Dunno. I think "2" is correct. What happens?
3) Is there a difference? I don't think so.

Don't forget to exit cleanly when you're done.

Good luck. Let us know how it comes out.

Best,
Frank


Offline paml27

  • Jr. Member
  • *
  • Posts: 37
Re: Flags for Linux sys_open in 64-bit NASM
« Reply #2 on: December 05, 2019, 06:26:10 PM »
Thanks for your reply, Frank.  Yes, sys_open is 2, not 1.  I've tried your other suggestions, but still no luck.  I'm still working on this, so I'll let you know what happens. 


Offline paml27

  • Jr. Member
  • *
  • Posts: 37
Re: Flags for Linux sys_open in 64-bit NASM
« Reply #3 on: December 05, 2019, 07:38:02 PM »
A little more info.  Sys_creat (as shown above) returns a positive value, and sys_write works with that.  But I'm still having problems with sys_open.  The flags may be the problem.  The Linux man pages at http://man7.org/linux/man-pages/man2/open.2.html don't help much, and I haven't found any definitive source yet.  The following code works, but sys_open still does not. 

; Create file
mov rax,85 ; sys_creat
mov rdi,File_Name
mov rsi,File_Mode  ; mode (permissions)
syscall

mov rdi,rax ; return code from sys_open
mov rax,1 ; sys_write
;mov rdi,File_Name
mov rsi,Write_Buffer
mov rdx,29
syscall


Offline paml27

  • Jr. Member
  • *
  • Posts: 37
Re: Flags for Linux sys_open in 64-bit NASM
« Reply #4 on: December 09, 2019, 10:28:27 PM »
The answer to this question is:

; Create file
mov rax,85 ; sys_creat
mov rdi,File_Name
mov rsi,[File_Mode]  ; mode (permissions)
syscall

The File_Mode variable must be passed by value (enclosed on brackets), not by reference, as it was before. 

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Flags for Linux sys_open in 64-bit NASM
« Reply #5 on: December 09, 2019, 10:56:21 PM »

Offline j40

  • Jr. Member
  • *
  • Posts: 4
Re: Flags for Linux sys_open in 64-bit NASM
« Reply #6 on: December 07, 2020, 12:33:08 AM »
I was trying to do this and crossed this topic a couple of days ago. Today I managed to do it, and I know this thread is old, but I created an account just to leave the answer here for future students. After a lot of trial and error I figured 2 things:
  • The flags starting with O_ are somewhere in the asm files, I don't remember which file, but can be found with a simple searching script looking for the same names that appear in the docs. The equivalent to creat() is 1101o, in octal.
  • The mode flags shown in the documentation are also in octal, the default would be 644o, as in I can read and write and the rest can read.
Imma leave a little working program here as an example, hope it helps someone!
https://github.com/JaoCR/asm-examples/blob/master/file/file.asm

EDIT: corrected flags, see replies bellow
« Last Edit: December 07, 2020, 05:51:56 PM by j40 »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Flags for Linux sys_open in 64-bit NASM
« Reply #7 on: December 07, 2020, 01:58:01 AM »
Hi j40.

Welcome to the forum!

Thanks for the working example. Always welcome!

One observation:
Code: [Select]
fd_new: resb 1
... sounds a little short to me. I"d reserve at least a dword for a file descriptor. Since it"s the last variable in your program it won't cause a problem, but if you added another it would.

Best,
Frank


Offline j40

  • Jr. Member
  • *
  • Posts: 4
Re: Flags for Linux sys_open in 64-bit NASM
« Reply #8 on: December 07, 2020, 01:42:32 PM »
Thanks Frank! Changed the example to reserve a quad just to make sure.

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Flags for Linux sys_open in 64-bit NASM
« Reply #9 on: December 07, 2020, 03:34:40 PM »
Tip: glibc have wrapers around syscalls like, open(), read(), write(), create(), close()... The list of arguments are the same as the regular syscalls and follows the same calling convenction (except RCX is substituted by R10). If you take a look at 'man creat' and 'man open' you'll see that creat() is the same as open(), except the flags O_CREAT|O_WRONLY|O_TRUNC is assumed for the last one... Both functions will return a positive value (file descriptor) or negative (-1) in case of error (in EAX)...

Then, you can use open() to open/create a file using O_CREAT|O_RDWR|O_TRUNC if you want to be able to read/write the "new" file... and, take a look at the function prototype:

Code: [Select]
int open( const char *fname, int flags, mode_t mode );Where `mode_t` is a typedef to 'int`... Using 'int' means you don't need the upper half of R?? registers, so you can write:
Code: [Select]
; test.asm
;
; Compiling and linking:
;
;   nasm -felf64 -o test.o test.asm
;   ld -s -o test test.o
;
  bits  64
  default rel

%define SYS_WRITE 1
%define SYS_OPEN  2
%define SYS_CLOSE 3
%define SYS_EXIT  60

%define STDERR_FILENO 2

; See with 'gcc -dM -E -include unistd.h - < /dev/null | grep O_'
%define O_CREAT 0o100
%define O_TRUNC 0o1000
%define O_RDWR  0o02

  section .rodata

fname:
  db  "myfile.txt",0

errmsg1:
  db  `Cannot open/create file.\n`
errmsg1_len equ $ - errmsg1

errmsg2:
  db  `Error writing to file.\n`
errmsg2_len equ $ - errmsg2

buffer:
  db `This should be writen to the file.\n`
buffer_len equ $ - buffer

  section .text

  global _start
_start:
  ; Try to open/create a file...
  mov   eax,SYS_OPEN
  lea   rdi,[fname]                     ; fname
  mov   esi,O_CREAT | O_RDWR | O_TRUNC  ; flags
  mov   edx,0o0644                      ; permission (in octal).
  syscall

  test  eax,eax                         ; is the file descriptro negative?
  jns   .continue                       ; no? continue. yes? then...

  ; ... print error message...
  lea   rsi,[errmsg1]
  mov   edx,errmsg1_len
.printerr_exit:
  mov   edi,STDERR_FILENO
  mov   eax,SYS_WRITE
  syscall

  ; ...and exit with error 1.
  mov   eax,SYS_EXIT
  mov   edi,1
  syscall

.continue:
  mov   ebx,eax                         ; store fd in EBX (Preserved bewteen calls).

  ; Try to write a string to the file.
  mov   edi,eax                         ; Put file descriptor in EDI. 
  mov   eax,SYS_WRITE
  lea   rsi,[buffer]
  mov   edx,buffer_len
  syscall

  test  eax,eax                         ; write retuns -1 in case of error. Is it negative?
  jns   .continue2                      ; no? continue. yes, then...

  ; ...close the file...
  mov   eax,SYS_CLOSE
  mov   edi,ebx
  syscall

  ; ... and print error messgae and exit with 1.
  lea   rsi,[errmsg2]
  mov   edx,errmsg2_len
  jmp   .printerr_exit

.continue2:
  ; Close the file and exit with 0.
  mov   eax,SYS_CLOSE
  mov   edi,ebx
  syscall

  mov   eax,SYS_EXIT
  xor   edi,edi
  syscall
« Last Edit: December 07, 2020, 03:53:58 PM by fredericopissarra »

Offline j40

  • Jr. Member
  • *
  • Posts: 4
Re: Flags for Linux sys_open in 64-bit NASM
« Reply #10 on: December 07, 2020, 05:49:15 PM »
Valeu Pissarra! You made me realize I was thinking wrong about the flags. I was using decimal base, but accidentally placed an extra zero which somehow managed to generate the same result as the correct flags. The command you shown did not show the flags in my system, but I changed to the correct one in octal, 1101o as in your function, and it also works fine. Should be the correct way to do this. I updated the example on my github already, thanks guys!

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Flags for Linux sys_open in 64-bit NASM
« Reply #11 on: December 07, 2020, 07:46:58 PM »
Valeu Pissarra! You made me realize I was thinking wrong about the flags. I was using decimal base, but accidentally placed an extra zero which somehow managed to generate the same result as the correct flags.

"Valeu"? Are you brazilian? I am from Vitória/ES!

Anyway... glad to help! :)

Offline j40

  • Jr. Member
  • *
  • Posts: 4
Re: Flags for Linux sys_open in 64-bit NASM
« Reply #12 on: December 07, 2020, 08:32:59 PM »
Yep, Sao Carlos, SP. Valeu mesmo! To entregando o trabalho agora inclusive kkkkk

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Flags for Linux sys_open in 64-bit NASM
« Reply #13 on: December 08, 2020, 05:52:20 PM »
Yep, Sao Carlos, SP. Valeu mesmo! To entregando o trabalho agora inclusive kkkkk
Jóia... Eu também tive esse problema com octal no NASM (prefixando com 0, como em C) até ver a documentação.
Quanto às permissões... tenha em mente que pode ser necessário manipular umask também.

To the benefict of the english readers: "Nice... I had this problem with octals in NASM too (using que 0 prefix, as in C) until I read the documentation. As for the permissions... keep in mind that it could be necessary to deal with umask too."

[]s
Fred