# The idea of sys .linux is to define an near-isomorphic yet # elymas-style interface to syscalls # argument order tends to follow kernel API < 43 ==:ACCEPT # 288 ==:ACCEPT64 21 ==:ACCESS # TODO: not implemented here # 163 ==:ACCT # 248 ==:ADDKEY # 159 ==:ADJTIMEX # 183 ==:AFSSYSCALL # 37 ==:ALARM 158 ==:ARCHPRCTL 49 ==:BIND # 12 ==:BRK # 125 ==:CAPGET # 126 ==:CAPSET # 80 ==:CHDIR # 90 ==:CHMOD # 92 ==:CHOWN # 161 ==:CHROOT # 229 ==:CLOCKGETRES 228 ==:CLOCKGETTIME # TODO: not implemented here # 230 ==:CLOCKNANOSLEEP # 227 ==:CLOCKSETTIME # 56 ==:CLONE 3 ==:CLOSE 42 ==:CONNECT # 85 ==:CREAT # 174 ==:CREATEMODULE # 176 ==:DELETEMODULE # 32 ==:DUP 33 ==:DUP2 # 292 ==:DUP3 213 ==:EPOLLCREATE # 291 ==:EPOLLCREATE1 233 ==:EPOLLCTL # 214 ==:EPOLLCTLOLD # 281 ==:EPOLLPWAIT 232 ==:EPOLLWAIT # 215 ==:EPOLLWAITOLD # 284 ==:EVENTFD # 290 ==:EVENTFD2 59 ==:EXECVE # 60 ==:EXIT # 231 ==:EXITGROUP # 269 ==:FACCESSAT # 221 ==:FADVISE64 # 285 ==:FALLOCATE # 300 ==:FANOTIFYINIT # 301 ==:FANOTIFYMARK # 81 ==:FCHDIR # 91 ==:FCHMOD # 268 ==:FCHMODAT # 93 ==:FCHOWN # 260 ==:FCHOWNAT 72 ==:FCNTL # TODO: not implemented here # 75 ==:FDATASYNC # 193 ==:FGETXATTR # 196 ==:FLISTXATTR # 73 ==:FLOCK 57 ==:FORK # 199 ==:FREMOVEXATTR # 190 ==:FSETXATTR 5 ==:FSTAT # 138 ==:FSTATFS # 74 ==:FSYNC # 77 ==:FTRUNCATE # 202 ==:FUTEX # 261 ==:FUTIMESAT # 177 ==:GETKERNELSYMS # 239 ==:GETMEMPOLICY # 274 ==:GETROBUSTLIST # 211 ==:GETTHREADAREA # 79 ==:GETCWD # 78 ==:GETDENTS 217 ==:GETDENTS64 # 108 ==:GETEGID # 107 ==:GETEUID # 104 ==:GETGID # 115 ==:GETGROUPS # 36 ==:GETITIMER 52 ==:GETPEERNAME # TODO: not implemented here # 121 ==:GETPGID # 111 ==:GETPGRP 39 ==:GETPID # 181 ==:GETPMSG # 110 ==:GETPPID # 140 ==:GETPRIORITY # 120 ==:GETRESGID # 118 ==:GETRESUID # 97 ==:GETRLIMIT # 98 ==:GETRUSAGE # 124 ==:GETSID 51 ==:GETSOCKNAME # TODO: not implemented here # 55 ==:GETSOCKOPT # 186 ==:GETTID 96 ==:GETTIMEOFDAY # 102 ==:GETUID # 191 ==:GETXATTR # 175 ==:INITMODULE # 254 ==:INOTIFYADDWATCH # 253 ==:INOTIFYINIT # 294 ==:INOTIFYINIT1 # 255 ==:INOTIFYRMWATCH # 210 ==:IOCANCEL # 207 ==:IODESTROY # 208 ==:IOGETEVENTS # 206 ==:IOSETUP # 209 ==:IOSUBMIT 16 ==:IOCTL # 173 ==:IOPERM # 172 ==:IOPL # 252 ==:IOPRIOGET # 251 ==:IOPRIOSET # 246 ==:KEXECLOAD # 250 ==:KEYCTL 62 ==:KILL # 94 ==:LCHOWN # 192 ==:LGETXATTR # 86 ==:LINK # 265 ==:LINKAT 50 ==:LISTEN # 194 ==:LISTXATTR # 195 ==:LLISTXATTR # 212 ==:LOOKUPDCOOKIE # 198 ==:LREMOVEXATTR # 8 ==:LSEEK # 189 ==:LSETXATTR # 6 ==:LSTAT # 28 ==:MADVISE # 237 ==:MBIND # 256 ==:MIGRATEPAGES # 27 ==:MINCORE 83 ==:MKDIR # 258 ==:MKDIRAT # 133 ==:MKNOD # 259 ==:MKNODAT # 149 ==:MLOCK # 151 ==:MLOCKALL 9 ==:MMAP # 154 ==:MODIFYLDT # 165 ==:MOUNT # 279 ==:MOVEPAGES # 10 ==:MPROTECT # 245 ==:MQGETSETATTR # 244 ==:MQNOTIFY # 240 ==:MQOPEN # 243 ==:MQTIMEDRECEIVE # 242 ==:MQTIMEDSEND # 241 ==:MQUNLINK # 25 ==:MREMAP # 71 ==:MSGCTL # 68 ==:MSGGET # 70 ==:MSGRCV # 69 ==:MSGSND # 26 ==:MSYNC # 150 ==:MUNLOCK # 152 ==:MUNLOCKALL 11 ==:MUNMAP # 35 ==:NANOSLEEP # 262 ==:NEWFSTATAT # 180 ==:NFSSERVCTL 2 ==:OPEN # 257 ==:OPENAT # 34 ==:PAUSE # 298 ==:PERFEVENTOPEN # 135 ==:PERSONALITY # 22 ==:PIPE 293 ==:PIPE2 # 155 ==:PIVOTROOT 7 ==:POLL # TODO: not implemented here # 271 ==:PPOLL # 157 ==:PRCTL # 17 ==:PREAD64 # 295 ==:PREADV # 302 ==:PRLIMIT64 # 270 ==:PSELECT6 101 ==:PTRACE # 182 ==:PUTPMSG # 18 ==:PWRITE64 # 296 ==:PWRITEV # 178 ==:QUERYMODULE # 179 ==:QUOTACTL 0 ==:READ # 187 ==:READAHEAD # 89 ==:READLINK # 267 ==:READLINKAT # 19 ==:READV # 169 ==:REBOOT 45 ==:RECVFROM # TODO: not implemented here # 299 ==:RECVMMSG # 47 ==:RECVMSG # 216 ==:REMAPFILEPAGES # 197 ==:REMOVEXATTR 82 ==:RENAME # 264 ==:RENAMEAT # 249 ==:REQUESTKEY # 219 ==:RESTARTSYSCALL # 84 ==:RMDIR 13 ==:RTSIGACTION # TODO: not implemented here # 127 ==:RTSIGPENDING # 14 ==:RTSIGPROCMASK # 129 ==:RTSIGQUEUEINFO # 15 ==:RTSIGRETURN # 130 ==:RTSIGSUSPEND # 128 ==:RTSIGTIMEDWAIT # 297 ==:RTTGSIGQUEUEINFO # 146 ==:SCHEDGETPRIORITYMAX # 147 ==:SCHEDGETPRIORITYMIN # 204 ==:SCHEDGETAFFINITY # 143 ==:SCHEDGETPARAM # 145 ==:SCHEDGETSCHEDULER # 148 ==:SCHEDRRGETINTERVAL # 203 ==:SCHEDSETAFFINITY # 142 ==:SCHEDSETPARAM # 144 ==:SCHEDSETSCHEDULER # 24 ==:SCHEDYIELD # 185 ==:SECURITY # 23 ==:SELECT # 66 ==:SEMCTL # 64 ==:SEMGET # 65 ==:SEMOP # 220 ==:SEMTIMEDOP # 40 ==:SENDFILE # 46 ==:SENDMSG # 44 ==:SENDTO # 238 ==:SETMEMPOLICY # 273 ==:SETROBUSTLIST # 205 ==:SETTHREADAREA # 218 ==:SETTIDADDRESS # 171 ==:SETDOMAINNAME # 123 ==:SETFSGID # 122 ==:SETFSUID # 106 ==:SETGID # 116 ==:SETGROUPS # 170 ==:SETHOSTNAME # 38 ==:SETITIMER # 109 ==:SETPGID # 141 ==:SETPRIORITY # 114 ==:SETREGID # 119 ==:SETRESGID # 117 ==:SETRESUID # 113 ==:SETREUID # 160 ==:SETRLIMIT # 112 ==:SETSID 54 ==:SETSOCKOPT # 164 ==:SETTIMEOFDAY # 105 ==:SETUID # 188 ==:SETXATTR # 30 ==:SHMAT # 31 ==:SHMCTL # 67 ==:SHMDT # 29 ==:SHMGET 48 ==:SHUTDOWN # TODO: not implemented here # 131 ==:SIGALTSTACK # 282 ==:SIGNALFD # 289 ==:SIGNALFD4 41 ==:SOCKET # 53 ==:SOCKETPAIR # 275 ==:SPLICE 4 ==:STAT # 137 ==:STATFS # 168 ==:SWAPOFF # 167 ==:SWAPON 88 ==:SYMLINK # 266 ==:SYMLINKAT # 162 ==:SYNC # 277 ==:SYNCFILERANGE # 156 ==:SYSCTL # 139 ==:SYSFS # 99 ==:SYSINFO # 103 ==:SYSLOG # 276 ==:TEE # 234 ==:TGKILL # 201 ==:TIME # 222 ==:TIMERCREATE # 226 ==:TIMERDELETE # 225 ==:TIMERGETOVERRUN # 224 ==:TIMERGETTIME # 223 ==:TIMERSETTIME # 283 ==:TIMERFDCREATE # 287 ==:TIMERFDGETTIME # 286 ==:TIMERFDSETTIME # 100 ==:TIMES # 200 ==:TKILL # 76 ==:TRUNCATE # 184 ==:TUXCALL # 95 ==:UMASK # 166 ==:UMOUNT2 63 ==:UNAME # TODO: not implemented here 87 ==:UNLINK # 263 ==:UNLINKAT # 272 ==:UNSHARE # 134 ==:USELIB # 136 ==:USTAT # 132 ==:UTIME # 280 ==:UTIMENSAT # 235 ==:UTIMES # 58 ==:VFORK # 153 ==:VHANGUP # 278 ==:VMSPLICE # 236 ==:VSERVER 61 ==:WAIT4 # 247 ==:WAITID 1 ==:WRITE 20 ==:WRITEV # TODO: not implemented here 0 ==errno 11 _ ==:EAGAIN ==:EWOULDBLOCK bin .scan "->" via bin .print "<-" via # defines a syscall which has identical argument order # to kernel API and returns the raw return value { # ==name ==f -01 { sys .asm .syscall -- _ 0 ge { 0 =errno } { neg =errno 1 neg } ? * } ; -01 deffd }' /defStdSyscall deff { 0 0 0 0 0 ACCEPT } /accept defStdSyscall { 4098 -01 0 0 0 0 ARCHPRCTL } /archSetFs defStdSyscall { _ len 0 0 0 BIND } /bind defStdSyscall { 0 0 0 0 0 CLOSE } /close defStdSyscall { _ len 0 0 0 CONNECT } /connect defStdSyscall { 0 0 0 0 DUP2 } /dup2 defStdSyscall # { 0 0 0 0 0 EXECVE } /exec defStdSyscall # 0 -> an array of strings determining the environment # 1 -> an array of strings determining argv # 2 -> path to executable # 0 <- raw return value (if it returns at all, naturally) { ==env ==arg ==path path arg env { [ -01 { sys .asm .rawAddress 24 add bin .produce .u64 } each "\0\0\0\0\0\0\0\0" ] |cat fold } -20*10* 0 0 0 EXECVE } /execve defStdSyscall { 0 0 0 0 0 0 FORK } /fork defStdSyscall 1 ==:FGETFD 2 ==:FSETFD 3 ==:FGETFL 4 ==:FSETFL { 0 0 0 FCNTL } /fcntl defStdSyscall { 0 0 0 0 0 0 GETPID } /getpid defStdSyscall # 0 -> open directory file descriptor # 0 <- raw return value # 1 <- an array of scopes resembling linux_dirent structures (unless return value zero or less) # actually only defines members d_ino, d_name, and d_type (because all others just help decoding the result buffer) { 8192 str .alloc ==buf buf 8192 0 0 0 GETDENTS64 sys .asm .syscall =errno _ ==ret ==toparse 0 ==doff 0 ==dreclen toparse 0 gt { [ { toparse 0 gt } { < buf ->u64 ==dino ->u64 =doff # this is essentially garbage (man 2 getdents is just not very clear about this) ->u16 =dreclen ->u8 ==dtype -- 0 19 dreclen 1 sub buf str .infix "\0" str .split * ==dname dreclen buf str .postfix =buf toparse dreclen sub =toparse > } loop ] } rep ret } /getdents64 deffd # 0 <- raw return value # 1 <- seconds since 1970 # 2 <- microseconds since 1970 { # struct timeval takes 16 bytes on a x64 16 str .alloc ==buf buf 0 0 0 0 0 GETTIMEOFDAY sys .asm .syscall =errno buf ->u64 -01 ->u64 -023 } /gettimeofday deffd < 1 ==:EPOLLCTLADD 3 ==:EPOLLCTLMOD 2 ==:EPOLLCTLDEL 1 ==:EPOLLIN 4 ==:EPOLLOUT 8192 ==:EPOLLRDHUP 2 ==:EPOLLPRI 8 ==:EPOLLERR 16 ==:EPOLLHUP 2147483648 ==:EPOLLLET 1073741824 ==:EPOLLONESHOT # 0 <- raw return value, i.e. epoll file descriptor { 1 0 0 0 0 0 EPOLLCREATE sys .asm .syscall =errno } /create deffd # 0 -> callback data # 1 -> event mask # 2 -> fd to modify # 3 -> what to do (i.e. EPOLLCTLADD and friends) # 4 -> epoll fd # 0 <- raw return value { ==callbackData ==eventMask ==fd ==action ==epollFd # struct epoll_event takes 16 bytes on a x86 "" eventMask <-u32 callbackData <-u64 ==buf epollFd action fd buf 0 0 EPOLLCTL sys .asm .syscall =errno } /ctl deffd # 0 -> timeout # 1 -> maxevents # 2 -> epollfd # 0 <- raw return value, i.e. number of file descriptors returned # 1 <- [ < ==events ==data > ... ] (possibly empty if no file descriptors were returned) # (not existing if raw return value -1) { ==timeout ==maxevents ==epollFd maxevents 16 mul str .alloc ==buf epollFd buf maxevents timeout 0 0 EPOLLWAIT sys .asm .syscall =errno ==ret [ buf ret { < ->u32 ==events ->u64 ==data > -01 } rep -- ] ret } /wait deffd > /epoll defvd { < ->u64 ==dev ->u64 ==ino ->u32 ==nlink ->u32 ==what0 ->u32 ==mode ->u32 ==gid ->u32 ==uid ->u32 ==what1 ->u64 ==rdev ->u64 ==size ->u32 ==blksize ->u32 ==what3 ->u64 ==blocks ->u64 ==atime ->u64 ==atimensec ->u64 ==mtime ->u64 ==mtimensec ->u64 ==ctime ->u64 ==ctimensec ->u32 -- ->u32 -- > } /parseStatStruct deffd # 0 -> fd to stat # 0 <- raw return value # 1 <- (struct stat)-like scope { # ==filename # struct stat takes 144 bytes on a x64 128 str .alloc ==buf buf 0 0 0 0 FSTAT sys .asm .syscall =errno buf parseStatStruct -02 } /fstat deffd < { IOCTL sys .asm .syscall =errno } /raw deffd 2 ==:ICANON 8 ==:ECHO 21505 ==:TCGETS 21506 ==:TCSETS # 0 -> file descriptor # 0 <- raw return value # 1 <- current attributes { # ==fd TCGETS 60 str .alloc _ ==buf 0 0 0 raw buf < ->u32 ==iflag ->u32 ==oflag ->u32 ==cflag ->u32 ==lflag ->u8 ==line _ 32 -01 str .prefix ==cc 32 -01 str .postfix ->u8 -- ->u8 -- ->u8 -- ->u32 ==ispeed ->u32 ==ospeed > -02 } /tcgets deffd # 0 -> new attributes # 1 -> file descriptor # 0 <- raw return value { ":" via # ==fd TCSETS "" :iflag <-u32 :oflag <-u32 :cflag <-u32 :lflag <-u32 :line <-u8 :cc cat 0 <-u8 0 <-u8 0 <-u8 :ispeed <-u32 :ospeed <-u32 0 0 0 raw } /tcsets deffd > /ioctl defvd { 0 0 0 0 KILL } /kill defStdSyscall { 0 0 0 0 LISTEN } /listen defStdSyscall { 0 0 0 0 MKDIR } /mkdir defStdSyscall 1 ==:PROTREAD 2 ==:PROTWRITE 4 ==:PROTEXEC 1 ==:MAPSHARED 2 ==:MAPPRIVATE 16 ==:MAPFIXED 32 ==:MAPANONYMOUS 256 ==:MAPGROWSDOWN 8192 ==:MAPLOCKED 16384 ==:MAPNORESERVE 32768 ==:MAPPOPULATE 65536 ==:MAPNONBLOCK 262144 ==:MAPHUGETLB # 0 -> offset (in file) # 1 -> fd # 2 -> flags # 3 -> protection # 4 -> length # 5 -> address { MMAP } /mmap defStdSyscall # 0 -> addr # 1 -> length { 0 0 0 0 MUNMAP } /munmap defStdSyscall { 0 0 0 0 RENAME } /rename defStdSyscall 1 ==:AFUNIX 1 ==:AFLOCAL 2 ==:AFINET 10 ==:AFINET6 4 ==:AFIPX 16 ==:AFNETLINK 9 ==:AFX25 3 ==:AFAX25 8 ==:AFATMPVC 5 ==:AFAPPLETALK 17 ==:AFPACKET 1 ==:SOCKSTREAM 2 ==:SOCKDGRAM 3 ==:SOCKRAW 4 ==:SOCKRDM 5 ==:SOCKSEQPACKET 524288 ==:SOCKCLOEXEC 2048 ==:SOCKNONBLOCK 6 ==:IPPROTOTCP 17 ==:IPPROTOUDP # 0 -> domain # 1 -> type # 2 -> protocol (or use zero if the protocol is already determined by domain and type) { 0 0 0 SOCKET } /socket defStdSyscall # 0 -> path to stat # 0 <- raw return value # 1 <- (struct stat)-like scope { # ==filename # struct stat takes 144 bytes on a x64 144 str .alloc ==buf buf 0 0 0 0 STAT sys .asm .syscall =errno buf parseStatStruct -02 } /stat deffd 0 ==:ORDONLY 1 ==:OWRONLY 2 ==:ORDWR 64 ==:OCREAT 128 ==:OEXCL 256 ==:ONOCTTY 512 ==:OTRUNC 1024 ==:OAPPEND 2048 ==:ONONBLOCK 8192 ==:OASYNC 16384 ==:ODIRECT 32768 ==:OLARGEFILE 65536 ==:ODIRECTORY 131072 ==:ONOFOLLOW 262144 ==:ONOATIME 524288 ==:OCLOEXEC 1052672 ==:OSYNC { 0 0 0 OPEN } /open defStdSyscall # 0 <- raw return value # 1 <- read end (possibly invalid) # 2 <- write end (possibly invalid) { 16 str .alloc ==buf buf 0 0 0 0 0 PIPE2 sys .asm .syscall =errno buf ->u32 -01 ->u32 -023 } /pipe deffd < 2 ==:PTRACEPEEKDATA 3 ==:PTRACEPEEKUSER 16 ==:PTRACEATTACH 17 ==:PTRACEDETACH { ==pid PTRACEATTACH pid 0 0 0 0 PTRACE sys .asm .syscall =errno } /attach deffd { ==pid PTRACEDETACH pid 0 0 0 0 PTRACE sys .asm .syscall =errno } /detach deffd # 0 <- raw return value # 1 <- peeked data { ==addr ==pid 8 str .alloc ==buf PTRACEPEEKDATA pid addr buf 0 0 PTRACE sys .asm .syscall =errno buf ->u64 -02 } /peek deffd < { deffd }' /defPeekUser deff [ /r15 /r14 /r13 /r12 /rbp /rbx /r11 /r10 /r9 /r8 /rax /rcx /rdx /rsi /rdi /origRax /rip /cs /eflags /rsp /ss /fs_base /gs_base /ds /es /fs /gs ] =*:userAreaNames 0 |userAreaNames len range { ==i # 0 <- raw return value # 1 <- peeked data { ==pid 8 str .alloc ==buf PTRACEPEEKUSER pid i 8 mul buf 0 0 PTRACE sys .asm .syscall =errno buf ->u64 -02 } i userAreaNames defPeekUser } each > /peekUser defvd > /ptrace defvd { 0 0 0 READ } /read defStdSyscall < 1 ==:SOLSOCKET # TODO: support more options 2 ==:SOREUSEADDR # 0 -> socket fd # 1 -> turn it on (1) or off (0) # 0 <- raw return value { ==fd ==value fd SOLSOCKET SOREUSEADDR "" value <-u32 4 0 SETSOCKOPT sys .asm .syscall =errno } /reuseAddr deffd > /setsockopt defvd { 0 0 0 0 SYMLINK } /symlink defStdSyscall { 0 0 0 0 0 UNLINK } /unlink defStdSyscall # 0 -> options # 1 -> pid to wait for # 0 <- raw return value # 1 <- returned status { ==options ==pid # status is returned into an int buffer 8 str .alloc ==buf pid buf options 0 0 0 WAIT4 sys .asm .syscall =errno buf ->u64 -02 } /waitpid deffd { 0 0 0 WRITE } /write defStdSyscall > /linux sys .defv # vim: syn=elymas