platform_bionic/libc/SYSCALLS.TXT
Evgenii Stepanov 3031a7e45e memtag_stack: vfork and longjmp support.
With memtag_stack, each function is responsible for cleaning up
allocation tags for its stack frame. Allocation tags for anything below
SP must match the address tag in SP.

Both vfork and longjmp implement non-local control transfer which
abandons part of the stack without proper cleanup. Update allocation
tags:
* For longjmp, we know both source and destination values of SP.
* For vfork, save the value of SP before exit() or exec*() - the only
  valid ways of ending the child process according to POSIX - and reset
  tags from there to SP-in-parent.

This is not 100% solid and can be confused by a number of hopefully
uncommon conditions:
* Segmented stacks.
* Longjmp from sigaltstack into the main stack.
* Some kind of userspace thread implementation using longjmp (that's UB,
  longjmp can only return to the caller on the current stack).
* and other strange things.

This change adds a sanity limit on the size of the tag cleanup. Also,
this logic is only activated in the binaries that carry the
NT_MEMTAG_STACK note (set by -fsanitize=memtag-stack) which is meant as
a debugging configuration, is not compatible with pre-armv9 CPUs, and
should not be set on production code.

Bug: b/174878242
Test: fvp_mini with ToT LLVM (more test in a separate change)

Change-Id: Ibef8b2fc5a6ce85c8e562dead1019964d9f6b80b
2022-05-27 13:19:34 -07:00

370 lines
19 KiB
Text

# This file is used to automatically generate bionic's system call stubs.
#
# Each non-blank, non-comment line has the following format:
#
# return_type func_name[|alias_list][:syscall_name[:socketcall_id]]([parameter_list]) arch_list
#
# where:
# arch_list ::= "all" | arches
# arches ::= arch | arch "," arches
# arch ::= "arm" | "arm64" | "x86" | "x86_64" | "lp32" | "lp64"
#
# Note:
# - syscall_name corresponds to the name of the syscall, which may differ from
# the exported function name (example: the exit syscall is implemented by the _exit()
# function, which is not the same as the standard C exit() function which calls it)
#
# - alias_list is optional comma separated list of function aliases.
#
# - The call_id parameter, given that func_name and syscall_name have
# been provided, allows the user to specify dispatch style syscalls.
# For example, socket() syscall on i386 actually becomes:
# socketcall(__NR_socket, 1, *(rest of args on stack)).
#
# - Each parameter type is assumed to be stored in 32 bits.
#
# This file is processed by a python script named gensyscalls.py, run via
# genrules in Android.bp.
int __execve:execve(const char*, char* const*, char* const*) all
uid_t getuid:getuid32() lp32
uid_t getuid:getuid() lp64
gid_t getgid:getgid32() lp32
gid_t getgid:getgid() lp64
uid_t geteuid:geteuid32() lp32
uid_t geteuid:geteuid() lp64
gid_t getegid:getegid32() lp32
gid_t getegid:getegid() lp64
uid_t getresuid:getresuid32(uid_t* ruid, uid_t* euid, uid_t* suid) lp32
uid_t getresuid:getresuid(uid_t* ruid, uid_t* euid, uid_t* suid) lp64
gid_t getresgid:getresgid32(gid_t* rgid, gid_t* egid, gid_t* sgid) lp32
gid_t getresgid:getresgid(gid_t* rgid, gid_t* egid, gid_t* sgid) lp64
ssize_t readahead(int, off64_t, size_t) all
int getgroups:getgroups32(int, gid_t*) lp32
int getgroups:getgroups(int, gid_t*) lp64
pid_t getpgid(pid_t) all
pid_t getppid() all
pid_t getsid(pid_t) all
pid_t setsid() all
int setgid:setgid32(gid_t) lp32
int setgid:setgid(gid_t) lp64
int setuid:setuid32(uid_t) lp32
int setuid:setuid(uid_t) lp64
int setreuid:setreuid32(uid_t, uid_t) lp32
int setreuid:setreuid(uid_t, uid_t) lp64
int setresuid:setresuid32(uid_t, uid_t, uid_t) lp32
int setresuid:setresuid(uid_t, uid_t, uid_t) lp64
int setresgid:setresgid32(gid_t, gid_t, gid_t) lp32
int setresgid:setresgid(gid_t, gid_t, gid_t) lp64
void* __brk:brk(void*) all
int kill(pid_t, int) all
int tgkill(pid_t tgid, pid_t tid, int sig) all
int __ptrace:ptrace(int request, int pid, void* addr, void* data) all
# <sys/resource.h>
int getrusage(int, struct rusage*) all
int __getpriority:getpriority(int, id_t) all
int setpriority(int, id_t, int) all
# On LP64, rlimit and rlimit64 are the same.
# On 32-bit systems we use prlimit64 to implement the rlimit64 functions.
int getrlimit:ugetrlimit(int, struct rlimit*) lp32
int getrlimit|getrlimit64(int, struct rlimit*) lp64
int setrlimit(int, const struct rlimit*) lp32
int setrlimit|setrlimit64(int, const struct rlimit*) lp64
int prlimit64|prlimit(pid_t, int, struct rlimit64*, const struct rlimit64*) lp64
int prlimit64(pid_t, int, struct rlimit64*, const struct rlimit64*) lp32
int setgroups:setgroups32(int, const gid_t*) lp32
int setgroups:setgroups(int, const gid_t*) lp64
int setpgid(pid_t, pid_t) all
int setregid:setregid32(gid_t, gid_t) lp32
int setregid:setregid(gid_t, gid_t) lp64
int chroot(const char*) all
int prctl(int, unsigned long, unsigned long, unsigned long, unsigned long) all
long __arch_prctl:arch_prctl(int, unsigned long) x86_64
int capget(cap_user_header_t header, cap_user_data_t data) all
int capset(cap_user_header_t header, const cap_user_data_t data) all
int sigaltstack(const stack_t*, stack_t*) all
int acct(const char* filepath) all
# file descriptors
ssize_t read(int, void*, size_t) all
ssize_t write(int, const void*, size_t) all
ssize_t pread64(int, void*, size_t, off64_t) lp32
ssize_t pread64|pread(int, void*, size_t, off_t) lp64
ssize_t pwrite64(int, void*, size_t, off64_t) lp32
ssize_t pwrite64|pwrite(int, void*, size_t, off_t) lp64
# On LP32, preadv/pwritev don't use off64_t --- they use pairs of 32-bit
# arguments to avoid problems on architectures like arm32 where 64-bit arguments
# must be in a register pair starting with an even-numbered register.
# See linux/fs/read_write.c and https://lwn.net/Articles/311630/.
# Note that there's an unused always-0 second long even on LP64!
ssize_t __preadv64:preadv(int, const struct iovec*, int, long, long) all
ssize_t __pwritev64:pwritev(int, const struct iovec*, int, long, long) all
ssize_t __preadv64v2:preadv2(int, const struct iovec*, int, long, long, int) all
ssize_t __pwritev64v2:pwritev2(int, const struct iovec*, int, long, long, int) all
int __close:close(int) all
int close_range(unsigned int, unsigned int, int) all
ssize_t copy_file_range(int, off64_t*, int, off64_t*, size_t, unsigned int) all
pid_t __getpid:getpid() all
int memfd_create(const char*, unsigned) all
int munmap(void*, size_t) all
void* __mremap:mremap(void*, size_t, size_t, int, void*) all
int msync(const void*, size_t, int) all
int mprotect(const void*, size_t, int) all
int madvise(void*, size_t, int) all
ssize_t process_madvise(int, const struct iovec*, size_t, int, unsigned int) all
int mlock(const void* addr, size_t len) all
int mlock2(const void* addr, size_t len, int flags) all
int munlock(const void* addr, size_t len) all
int mlockall(int flags) all
int munlockall() all
int mincore(void* start, size_t length, unsigned char* vec) all
int __ioctl:ioctl(int, int, void*) all
ssize_t readv(int, const struct iovec*, int) all
ssize_t writev(int, const struct iovec*, int) all
int __fcntl64:fcntl64(int, int, void*) lp32
int __fcntl:fcntl(int, int, void*) lp64
int flock(int, int) all
int __fchmod:fchmod(int, mode_t) all
int __pipe2:pipe2(int*, int) all
int __dup:dup(int) all
int __dup3:dup3(int, int, int) all
int fsync(int) all
int fdatasync(int) all
int fchown:fchown32(int, uid_t, gid_t) lp32
int fchown:fchown(int, uid_t, gid_t) lp64
void sync(void) all
int syncfs(int) all
int __fsetxattr:fsetxattr(int, const char*, const void*, size_t, int) all
ssize_t __fgetxattr:fgetxattr(int, const char*, void*, size_t) all
ssize_t __flistxattr:flistxattr(int, char*, size_t) all
int fremovexattr(int, const char*) all
int __getdents64:getdents64(unsigned int, struct dirent*, unsigned int) all
int __openat:openat(int, const char*, int, mode_t) all
int __faccessat:faccessat(int, const char*, int) all
int __fchmodat:fchmodat(int, const char*, mode_t) all
int fchownat(int, const char*, uid_t, gid_t, int) all
int fstatat64|fstatat:fstatat64(int, const char*, struct stat*, int) lp32
int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int) lp64
int linkat(int, const char*, int, const char*, int) all
int mkdirat(int, const char*, mode_t) all
int mknodat(int, const char*, mode_t, dev_t) all
int readlinkat(int, const char*, char*, size_t) all
int renameat(int, const char*, int, const char*) all
int renameat2(int, const char*, int, const char*, unsigned) all
int symlinkat(const char*, int, const char*) all
int unlinkat(int, const char*, int) all
int utimensat(int, const char*, const struct timespec times[2], int) all
# Paired off_t/off64_t system calls. On 64-bit systems,
# sizeof(off_t) == sizeof(off64_t), so there we emit two symbols that are
# aliases. On 32-bit systems, we have two different system calls.
# That means that every system call in this section should take three lines.
off_t lseek(int, off_t, int) lp32
int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) lp32
off_t lseek|lseek64(int, off_t, int) lp64
int ftruncate64(int, off64_t) lp32
int ftruncate|ftruncate64(int, off_t) lp64
ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) lp32
ssize_t sendfile64(int out_fd, int in_fd, off64_t* offset, size_t count) lp32
ssize_t sendfile|sendfile64(int out_fd, int in_fd, off_t* offset, size_t count) lp64
int truncate(const char*, off_t) lp32
int truncate64(const char*, off64_t) lp32
int truncate|truncate64(const char*, off_t) lp64
# (mmap only gets two lines because we only used the 64-bit variant on 32-bit systems.)
void* __mmap2:mmap2(void*, size_t, int, int, int, long) lp32
void* mmap|mmap64(void*, size_t, int, int, int, off_t) lp64
# (fallocate only gets two lines because there is no 32-bit variant.)
int fallocate64:fallocate(int, int, off64_t, off64_t) lp32
int fallocate|fallocate64(int, int, off_t, off_t) lp64
# posix_fadvise64 is awkward: arm has shuffled arguments,
# the POSIX functions don't set errno, and no architecture has posix_fadvise.
int __arm_fadvise64_64:arm_fadvise64_64(int, int, off64_t, off64_t) arm
int __fadvise64:fadvise64_64(int, off64_t, off64_t, int) x86
int __fadvise64:fadvise64(int, off64_t, off64_t, int) lp64
int __fstatfs64:fstatfs64(int, size_t, struct statfs*) lp32
int __fstatfs:fstatfs(int, struct statfs*) lp64
int __statfs64:statfs64(const char*, size_t, struct statfs*) lp32
int __statfs:statfs(const char*, struct statfs*) lp64
int fstat64|fstat:fstat64(int, struct stat*) lp32
int fstat64|fstat:fstat(int, struct stat*) lp64
# file system
int chdir(const char*) all
int mount(const char*, const char*, const char*, unsigned long, const void*) all
int umount2(const char*, int) all
int __getcwd:getcwd(char* buf, size_t size) all
int fchdir(int) all
int setxattr(const char*, const char*, const void*, size_t, int) all
int lsetxattr(const char*, const char*, const void*, size_t, int) all
ssize_t getxattr(const char*, const char*, void*, size_t) all
ssize_t lgetxattr(const char*, const char*, void*, size_t) all
ssize_t listxattr(const char*, char*, size_t) all
ssize_t llistxattr(const char*, char*, size_t) all
int removexattr(const char*, const char*) all
int lremovexattr(const char*, const char*) all
int statx(int, const char*, int, unsigned, struct statx*) all
int swapon(const char*, int) all
int swapoff(const char*) all
# time
int settimeofday(const struct timeval*, const struct timezone*) all
clock_t times(struct tms*) all
int nanosleep(const struct timespec*, struct timespec*) all
int clock_settime(clockid_t, const struct timespec*) all
int __clock_nanosleep:clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*) all
int getitimer(int, struct itimerval*) all
int setitimer(int, const struct itimerval*, struct itimerval*) all
int __timer_create:timer_create(clockid_t clockid, struct sigevent* evp, __kernel_timer_t* timerid) all
int __timer_settime:timer_settime(__kernel_timer_t, int, const struct itimerspec*, struct itimerspec*) all
int __timer_gettime:timer_gettime(__kernel_timer_t, struct itimerspec*) all
int __timer_getoverrun:timer_getoverrun(__kernel_timer_t) all
int __timer_delete:timer_delete(__kernel_timer_t) all
int timerfd_create(clockid_t, int) all
int timerfd_settime(int, int, const struct itimerspec*, struct itimerspec*) all
int timerfd_gettime(int, struct itimerspec*) all
int adjtimex(struct timex*) all
int clock_adjtime(clockid_t, struct timex*) all
# signals
int __sigaction:sigaction(int, const struct sigaction*, struct sigaction*) lp32
int __rt_sigaction:rt_sigaction(int, const struct sigaction*, struct sigaction*, size_t) all
int __rt_sigpending:rt_sigpending(sigset64_t*, size_t) all
int __rt_sigprocmask:rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t) all
int __rt_sigsuspend:rt_sigsuspend(const sigset64_t*, size_t) all
int __rt_sigtimedwait:rt_sigtimedwait(const sigset64_t*, siginfo_t*, const timespec*, size_t) all
int __rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*) all
int __signalfd4:signalfd4(int, const sigset64_t*, size_t, int) all
# sockets
int __socket:socket(int, int, int) arm,lp64
int __socketpair:socketpair(int, int, int, int*) arm,lp64
int bind(int, struct sockaddr*, socklen_t) arm,lp64
int __connect:connect(int, struct sockaddr*, socklen_t) arm,lp64
int listen(int, int) arm,lp64
int __accept4:accept4(int, struct sockaddr*, socklen_t*, int) arm,lp64
int getsockname(int, struct sockaddr*, socklen_t*) arm,lp64
int getpeername(int, struct sockaddr*, socklen_t*) arm,lp64
ssize_t __sendto:sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t) arm,lp64
ssize_t recvfrom(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) arm,lp64
int shutdown(int, int) arm,lp64
int setsockopt(int, int, int, const void*, socklen_t) arm,lp64
int getsockopt(int, int, int, void*, socklen_t*) arm,lp64
ssize_t __recvmsg:recvmsg(int, struct msghdr*, unsigned int) arm,lp64
ssize_t __sendmsg:sendmsg(int, const struct msghdr*, unsigned int) arm,lp64
int __recvmmsg:recvmmsg(int, struct mmsghdr*, unsigned int, int, const struct timespec*) arm,lp64
int __sendmmsg:sendmmsg(int, struct mmsghdr*, unsigned int, int) arm,lp64
# sockets for x86. These are done as an "indexed" call to socketcall syscall.
int __socket:socketcall:1(int, int, int) x86
int bind:socketcall:2(int, struct sockaddr*, int) x86
int __connect:socketcall:3(int, struct sockaddr*, socklen_t) x86
int listen:socketcall:4(int, int) x86
int getsockname:socketcall:6(int, struct sockaddr*, socklen_t*) x86
int getpeername:socketcall:7(int, struct sockaddr*, socklen_t*) x86
int __socketpair:socketcall:8(int, int, int, int*) x86
ssize_t __sendto:socketcall:11(int, const void*, size_t, int, const struct sockaddr*, socklen_t) x86
ssize_t recvfrom:socketcall:12(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) x86
int shutdown:socketcall:13(int, int) x86
int setsockopt:socketcall:14(int, int, int, const void*, socklen_t) x86
int getsockopt:socketcall:15(int, int, int, void*, socklen_t*) x86
int __sendmsg:socketcall:16(int, const struct msghdr*, unsigned int) x86
int __recvmsg:socketcall:17(int, struct msghdr*, unsigned int) x86
int __accept4:socketcall:18(int, struct sockaddr*, socklen_t*, int) x86
int __recvmmsg:socketcall:19(int, struct mmsghdr*, unsigned int, int, const struct timespec*) x86
int __sendmmsg:socketcall:20(int, struct mmsghdr*, unsigned int, int) x86
# scheduler & real-time
int sched_setscheduler(pid_t pid, int policy, const struct sched_param* param) all
int sched_getscheduler(pid_t pid) all
int sched_yield(void) all
int sched_setparam(pid_t pid, const struct sched_param* param) all
int sched_getparam(pid_t pid, struct sched_param* param) all
int sched_get_priority_max(int policy) all
int sched_get_priority_min(int policy) all
int sched_rr_get_interval(pid_t pid, struct timespec* interval) all
int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) all
int setns(int, int) all
int unshare(int) all
int __sched_getaffinity:sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set) all
int __getcpu:getcpu(unsigned*, unsigned*, void*) all
# other
int uname(struct utsname*) all
mode_t umask(mode_t) all
int __reboot:reboot(int, int, int, void*) all
int init_module(void*, unsigned long, const char*) all
int delete_module(const char*, unsigned int) all
int klogctl:syslog(int, char*, int) all
int sysinfo(struct sysinfo*) all
int personality(unsigned long) all
int bpf(int, union bpf_attr *, unsigned int) all
ssize_t tee(int, int, size_t, unsigned int) all
ssize_t splice(int, off64_t*, int, off64_t*, size_t, unsigned int) all
ssize_t vmsplice(int, const struct iovec*, size_t, unsigned int) all
int __epoll_create1:epoll_create1(int) all
int epoll_ctl(int, int op, int, struct epoll_event*) all
int __epoll_pwait:epoll_pwait(int, struct epoll_event*, int, int, const sigset64_t*, size_t) all
int __eventfd:eventfd2(unsigned int, int) all
void __exit_group:exit_group(int) all
void __exit:exit(int) all
int inotify_init1(int) all
int inotify_add_watch(int, const char*, unsigned int) all
int inotify_rm_watch(int, unsigned int) all
int __pselect6:pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*) all
int __ppoll:ppoll(pollfd*, unsigned int, timespec*, const sigset64_t*, size_t) all
ssize_t process_vm_readv(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long) all
ssize_t process_vm_writev(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long) all
int quotactl(int, const char*, int, char*) all
int __set_tid_address:set_tid_address(int*) all
int setfsgid(gid_t) all
int setfsuid(uid_t) all
int setdomainname(const char*, size_t) all
int sethostname(const char*, size_t) all
int __sync_file_range:sync_file_range(int, off64_t, off64_t, unsigned int) x86,lp64
int __sync_file_range2:sync_file_range2(int, unsigned int, off64_t, off64_t) arm
pid_t wait4(pid_t, int*, int, struct rusage*) all
int __waitid:waitid(int, pid_t, siginfo_t*, int, void*) all
# ARM-specific
int __set_tls:__ARM_NR_set_tls(void*) arm
int cacheflush:__ARM_NR_cacheflush(long start, long end, long flags) arm
# x86-specific
int __set_thread_area:set_thread_area(void*) x86
# vdso stuff.
int __clock_getres:clock_getres(clockid_t, struct timespec*) all
int __clock_gettime:clock_gettime(clockid_t, struct timespec*) all
int __gettimeofday:gettimeofday(struct timeval*, struct timezone*) all
# <sys/random.h>
ssize_t getrandom(void*, size_t, unsigned) all
# <sys/pidfd.h>
int __pidfd_open:pidfd_open(pid_t, unsigned int) all
int __pidfd_getfd:pidfd_getfd(int, int, unsigned int) all
int pidfd_send_signal(int, int, siginfo_t*, unsigned int) all