0

I'm asking because my code is not working, and I'm at a loss as to why.

To give further context, here's my code:

section .data
p dw 'helloworld.txt'
section .text
global _start
_start:
        mov rax, 85
        mov rdi, p
        mov rsi, 0777o
        mov rdx, 68
        syscall
        mov rax, 60
        syscall

Here's my output:

-rwxrwxr-x

Here's what my output should be:

-rwxrwxrwx

And here's what my code should be:

section .data
p dw 'helloworld.txt'
section .text
global _start
_start:
        mov rax, 85
        mov rdi, p
        mov rsi, 68
        mov rdx, 0777o
        syscall
        mov rax, 60
        syscall

I've done research on this elsewhere, but I've not found a detailed answer.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • For your reference, the code block uses backticks (\`\`\`), not apostrophes ('''). – Thomas Jager Jun 19 '20 at 21:03
  • 2
    What's your `umask`? The result you got is what it would be with `umask 002` – Barmar Jun 19 '20 at 21:06
  • The registers are args to the system call selected by the call number in RAX. Use `strace ./a.out` to have it decode your syscalls. – Peter Cordes Jun 19 '20 at 21:08
  • How does your assembly program produce any output? It never prints anything. I guess you mean it's the output of `ls -l helloworld.txt` – Barmar Jun 19 '20 at 21:10
  • See https://linux.die.net/man/2/umask .`Umask` contains the permissions that are turned **off** when you use `creat`. – Seva Alekseyev Jun 19 '20 at 21:10
  • What do you mean "And here's what my code should be:"? That uses the same call number with the mode in a different register. They can't both be right. Also, use `db` for strings, with a terminating 0 like `"foo", 0`, not `dw`. – Peter Cordes Jun 19 '20 at 21:12
  • So, the umask explains the weird file permissions, but it doesn't explain why my code requires RSI, and RDX to be switched. When I say it's what my code should be, RSI is supposed to be the file flag, while RDX is supposed to handle file permissions. – I'mNotSure Jun 19 '20 at 21:14
  • @I'mNotSure The OS has no way of knowing your intent. The registers just hold values. You've got to put every argument where the OS expects them to be. – Thomas Jager Jun 19 '20 at 21:21
  • 1
    @ThomasJager I don't know where the OS expects the values to come from. According to every source I've found, RSI takes the file flags, and RDX handles the file permissions, but experimentation has demonstrated that the opposite is true. Is my compiler broken, am I just an idiot? I don't know, but I'd like to find out. – I'mNotSure Jun 19 '20 at 21:33
  • 2
    Works for me with RSI=0777o, RDX still unset (0 in a static executable). rax=85 is `creat`, https://man7.org/linux/man-pages/man2/creat.2.html. `int creat(const char *pathname, mode_t mode)`. It's not an alias for `open` or something that would take `path, flags, mode` args. Of course **the mode only applies if the file didn't already exist**, otherwise it just truncates the existing file without generating a new inode or updating the mode in the existing inode. I'm testing on Arch GNU/Linux, BTW. Use `strace ./a.out` to test decode the args you're passing. – Peter Cordes Jun 19 '20 at 22:10
  • Your 2nd version copy/pasted to my system runs as `creat("helloworld.txt", 0104) = 3`, producing `---x---r-- 1 peter peter 0 Jun 19 19:12 helloworld.txt`. (I removed the old helloworld.txt first so this version could create a new one). Again, as expected, because `68` decimal is `0104` octal. – Peter Cordes Jun 19 '20 at 22:14
  • Only applying to file *creation*, not reopening (which I assume is what led you to conclude that your 2nd version worked), is covered by [Writing to existing file and changing permissions](https://stackoverflow.com/q/26448503), although that's a perl question and this question already has 5 duplicates so I'd have to drop one of the existing ones to add it. – Peter Cordes Jun 19 '20 at 22:27
  • 1
    `85` is `creat`, with signature `int creat(const char *pathname, mode_t mode)`, so it indeed takes the mode in `rsi` and ignores `rdx`. You seem to be under the false impression that it's `open` with signature `int open(const char *pathname, int flags, mode_t mode)`, which does work the way you're expecting. If you want to use `open`, then pass `2` in `rax` instead of `85`. – Joseph Sible-Reinstate Monica Jun 20 '20 at 01:32

0 Answers0