Throughout this book we have used several system calls. We gather the information about them in this appendix.

FormalPara Note

It is always a good idea to read the man pages first, for example, man -s 2 write.

The exact flag and parameter values vary from system to system and should never be used in the immediate form. If you write in C, use the relevant headers (shown in man pages for the system call of interest). If you write in assembly, you will have to use LXR or another online system with annotated kernel code or look through these C headers yourself and create your own, corresponding %define’s.

The values provided are valid for the following system:

> uname -a Linux 3.16-2-amd64 #1 SMP Debian 3.16.3-2 (2014-09-20) x86_64 GNU/Linux

Issuing a system call in assembly is simple: just initialize the relevant registers into correct parameter values (in any order) and execute syscall instruction. If you need flags, you should define them on your own first; we provided you with their exact values.

Remember, that NASM can also compute constant expressions, such as O_TRUNC|O_RDWR.

Issuing a system call in C is usually done like calling a function, whose declaration is provided in some include files.

FormalPara Note

In C, never use the flags values directly, like, substituting O_APPEND with 0x1000. Use the defines provided in the header files, because they are both more readable and portable. Since we will have no corresponding assembly headers, we have to define them by hand in the assembly files.

1 read

ssize_t read(int fd, void *buf, size_t count);

Description Read from a file descriptor.

rax

rdi

rsi

rdx

r10

r8

r9

0

int fd

void* buf

size_t count

   

1.1 Arguments

  1. 1.

    fdFile descriptor by which we read. 0 for stdin ; use open system call to open a file by name.

  2. 2.

    bufThe address of the first byte in a sequence of bytes. The received bytes will be placed there.

  3. 3.

    count We will attempt to read that many bytes.

Returns rax = number of bytes successfully read, -1 on error.

Includes to use in C:

#include <unistd.h>

2 write

ssize_t write(int fd, const void *buf, size_t count);

Description Write to a file descriptor.

rax

rdi

rsi

rdx

r10

r8

r9

1

int fd

const void* buf

size_t count

   

2.1 Arguments

  1. 1.

    fdFile descriptor by which we write. 1 for stdout , 2 for stderr ; use open system call to open a file by name.

  2. 2.

    bufThe address of the first byte in a sequence of bytes to be written.

  3. 3.

    countWe will attempt to write that many bytes.

Returns rax = number of bytes successfully written, -1 on error.

Includes to use in C:

#include <unistd.h>

3 open

int open(const char *pathname, int flags, mode_t mode);

Description Opens the file with a given name (null-terminated string)

rax

rdi

rsi

rdx

r10

r8

r9

2

const char* filename

int flags

int mode

   

3.1 Arguments

  1. 1.

    filenameName of the file to be opened (null-terminated string).

  2. 2.

    flagsAre described below. They can be combined using |, for example, O_CREAT| O_WRONLY|O_TRUNC.

  3. 3.

    modeIs an integer number encoding user, group, and all others’ permissions. They are similar to ones used by chmod command.

Returns rax = new file descriptor for the given file, -1 on error.

Includes to use in C:

#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>

3.2 Flags

  • O_APPEND = 0x1000

    Append to a file on each write.

  • O_CREAT = 0x40

    Create a new file.

  • O_TRUNC = 0x200

    If the file already exists and is a regular file and the access mode allows writing it will be truncated to length 0.

  • O_RDWR = 2

    Read and write.

  • O_WRONLY = 1

    Write only.

  • O_RDONLY = 0

Read only.

4 close

int close(int fd);

Description Close the file with a given name (null-terminated string)

rax

rdi

rsi

rdx

r10

r8

r9

2

const char* filename

int flags

int mode

   

4.1 Arguments

  1. 1.

    fda valid file descriptor that should be closed.

Returns rax = zero un success, -1 on error. Global variable errno holds the error code.

Includes to use in C:

#include <unistd.h>

5 mmap

void *mmap(    void *addr, size_t length,    int prot, int flags,    int fd, off_t offset);

Description Map pages in virtual address space to something. It can be anything that lies behind a “file” (devices, files on disk, etc.) or just physical memory. In the latter case, the pages are anonymous, they bear no correspondence to anything present in file system. Such pages hold the heap and stacks of a process.

rax

rdi

rsi

rdx

r10

r8

r9

9

void* addr

size_t len

int prot

int flags

int fd

off_t off

5.1 Arguments

  1. 1.

    addr A hint for the starting virtual address of the freshly mapped region. We try to map at this address, and if we can’t, we let the operating system (OS) choose it. If 0, will always be chosen by OS.

  2. 2.

    len Length of a mapped region in bytes.

  3. 3.

    prot Protection flags (see below). They can be combined using |.

  4. 4.

    flags Behavior flags (see later). They can be combined using |.

  5. 5.

    fd A valid file descriptor for the file to be mapped, ignored if MAP_ANONYMOUS behavior flag is used.

  6. 6.

    off Starting offset in the file fd. We skip all bytes prior to this offset and map the file starting with it. Ignored if MAP_ANONYMOUS behavior flag is used.

Returns rax = pointer to the mapped area, -1 on error.

Includes to use in C:

#include <sys/mman.h>

5.2 Protection Flags

  • PROT_EXEC = 0x4 Pages may be executed.

  • PROT_READ = 0x1 Pages may be read.

  • PROT_WRITE = 0x2 Pages may be written.

  • PROT_NONE = 0x0 Pages may not be accessed.

5.3 Behavior Flags

  • MAP_SHARED = 0x1 Pages can be shared between processes.

  • MAP_PRIVATE = 0x2 Pages are not shared with other processes.

  • MAP_ANONYMOUS = 0x20 Pages do not correspond to any file in the filesystem.

  • MAP_FIXED = 0x10 Do not interpret addr as a hint but as an order. If we cannot map pages starting at this address, fail.

Note

To be able to use MAP_ANONYMOUS flag you might need to define _DEFAULT_SOURCE flag immediately before including the relevant header file, as follows:

#define _DEFAULT_SOURCE #include <sys/mman.h>

6 munmap

int munmap(void *addr, size_t length);

Description Unmaps a region of memory of a given length. You can map a huge region using mmap and then unmap a fraction of it using munmap.

rax

rdi

rsi

rdx

r10

r8

r9

11

void* addr

size_t len

    

6.1 Arguments

  1. 1.

    addr Start of the region to unmap.

  2. 2.

    length Length of the region to unmap.

Returns rax = zero un success , -1 on error. Global variable errno holds the error code.

Includes to use in C:

#include <sys/mman.h>

7 exit

void _exit(int status);

Description Exit process.

rax

rdi

rsi

rdx

r10

r8

r9

60

int status

     

7.1 Arguments

  1. 1.

    status Exit code. It is stored into $? environmental variable.

    Returns Nothing.

    Includes to use in C:

    #include <unistd.h>