--- a/toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h
@@ -138,16 +138,39 @@ extern "C" {
# pragma push_macro("stat64")
# pragma push_macro("fstat64")
# pragma push_macro("lstat64")
# undef stat64
# undef fstat64
# undef lstat64
#endif
+#if defined(__ANDROID__) && defined(__x86_64__)
+// A number of x86_64 syscalls are blocked by seccomp on recent Android;
+// undefine them so that modern alternatives will be used instead where
+// possible.
+// The alternative syscalls have been sanity checked against linux-3.4+;
+// older versions might not work.
+# undef __NR_getdents
+# undef __NR_dup2
+# undef __NR_fork
+# undef __NR_getpgrp
+# undef __NR_open
+# undef __NR_poll
+# undef __NR_readlink
+# undef __NR_stat
+# undef __NR_unlink
+# undef __NR_pipe
+#endif
+
+#if defined(__ANDROID__)
+// waitpid is blocked by seccomp on all architectures on recent Android.
+# undef __NR_waitpid
+#endif
+
/* As glibc often provides subtly incompatible data structures (and implicit
* wrapper functions that convert them), we provide our own kernel data
* structures for use by the system calls.
* These structures have been developed by using Linux 2.6.23 headers for
* reference. Note though, we do not care about exact API compatibility
* with the kernel, and in fact the kernel often does not have a single
* API that works across architectures. Instead, we try to mimic the glibc
* API where reasonable, and only guarantee ABI compatibility with the
@@ -177,18 +200,18 @@ struct kernel_dirent64 {
unsigned long long d_ino;
long long d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[256];
};
/* include/linux/dirent.h */
-#if defined(__aarch64__)
-// aarch64 only defines dirent64, just uses that for dirent too.
+#if !defined(__NR_getdents)
+// when getdents is not available, getdents64 is used for both.
#define kernel_dirent kernel_dirent64
#else
struct kernel_dirent {
long d_ino;
long d_off;
unsigned short d_reclen;
char d_name[256];
};
@@ -1064,16 +1087,17 @@ struct kernel_statfs {
#endif
#ifndef __NR_quotactl
#define __NR_quotactl 60
#endif
#ifndef __NR_getdents64
#define __NR_getdents64 61
#endif
#ifndef __NR_getdents
+// when getdents is not available, getdents64 is used for both.
#define __NR_getdents __NR_getdents64
#endif
#ifndef __NR_pread64
#define __NR_pread64 67
#endif
#ifndef __NR_pwrite64
#define __NR_pwrite64 68
#endif
@@ -1172,16 +1196,20 @@ struct kernel_statfs {
#endif
#ifndef __NR_sched_setaffinity
#define __NR_sched_setaffinity 203
#define __NR_sched_getaffinity 204
#endif
#ifndef __NR_getdents64
#define __NR_getdents64 217
#endif
+#ifndef __NR_getdents
+// when getdents is not available, getdents64 is used for both.
+#define __NR_getdents __NR_getdents64
+#endif
#ifndef __NR_set_tid_address
#define __NR_set_tid_address 218
#endif
#ifndef __NR_fadvise64
#define __NR_fadvise64 221
#endif
#ifndef __NR_clock_gettime
#define __NR_clock_gettime 228
@@ -3331,29 +3359,32 @@ struct kernel_statfs {
LSS_INLINE _syscall1(void *, brk, void *, e)
LSS_INLINE _syscall1(int, chdir, const char *,p)
LSS_INLINE _syscall1(int, close, int, f)
LSS_INLINE _syscall2(int, clock_getres, int, c,
struct kernel_timespec*, t)
LSS_INLINE _syscall2(int, clock_gettime, int, c,
struct kernel_timespec*, t)
LSS_INLINE _syscall1(int, dup, int, f)
- #if !defined(__aarch64__)
- // The dup2 syscall has been deprecated on aarch64. We polyfill it below.
+ #if defined(__NR_dup2)
+ // dup2 is polyfilled below when not available.
LSS_INLINE _syscall2(int, dup2, int, s,
int, d)
#endif
+ #if defined(__NR_dup3)
+ LSS_INLINE _syscall3(int, dup3, int, s, int, d, int, f)
+ #endif
LSS_INLINE _syscall3(int, execve, const char*, f,
const char*const*,a,const char*const*, e)
LSS_INLINE _syscall1(int, _exit, int, e)
LSS_INLINE _syscall1(int, exit_group, int, e)
LSS_INLINE _syscall3(int, fcntl, int, f,
int, c, long, a)
- #if !defined(__aarch64__)
- // The fork syscall has been deprecated on aarch64. We polyfill it below.
+ #if defined(__NR_fork)
+ // fork is polyfilled below when not available.
LSS_INLINE _syscall0(pid_t, fork)
#endif
LSS_INLINE _syscall2(int, fstat, int, f,
struct kernel_stat*, b)
LSS_INLINE _syscall2(int, fstatfs, int, f,
struct kernel_statfs*, b)
#if defined(__x86_64__)
/* Need to make sure off_t isn't truncated to 32-bits under x32. */
@@ -3368,18 +3399,17 @@ struct kernel_statfs {
int, o, int, v,
struct kernel_timespec*, t)
LSS_INLINE _syscall3(int, getdents, int, f,
struct kernel_dirent*, d, int, c)
LSS_INLINE _syscall3(int, getdents64, int, f,
struct kernel_dirent64*, d, int, c)
LSS_INLINE _syscall0(gid_t, getegid)
LSS_INLINE _syscall0(uid_t, geteuid)
- #if !defined(__aarch64__)
- // The getgprp syscall has been deprecated on aarch64.
+ #if defined(__NR_getpgrp)
LSS_INLINE _syscall0(pid_t, getpgrp)
#endif
LSS_INLINE _syscall0(pid_t, getpid)
LSS_INLINE _syscall0(pid_t, getppid)
LSS_INLINE _syscall2(int, getpriority, int, a,
int, b)
LSS_INLINE _syscall3(int, getresgid, gid_t *, r,
gid_t *, e, gid_t *, s)
@@ -3430,43 +3460,54 @@ struct kernel_statfs {
LSS_INLINE _syscall6(long, move_pages, pid_t, p,
unsigned long, n, void **,g, int *, d,
int *, s, int, f)
LSS_INLINE _syscall3(int, mprotect, const void *,a,
size_t, l, int, p)
LSS_INLINE _syscall5(void*, _mremap, void*, o,
size_t, os, size_t, ns,
unsigned long, f, void *, a)
- #if !defined(__aarch64__)
- // The open and poll syscalls have been deprecated on aarch64. We polyfill
- // them below.
+ #if defined(__NR_open)
+ // open is polyfilled below when not available.
LSS_INLINE _syscall3(int, open, const char*, p,
int, f, int, m)
+ #endif
+ #if defined(__NR_poll)
+ // poll is polyfilled below when not available.
LSS_INLINE _syscall3(int, poll, struct kernel_pollfd*, u,
unsigned int, n, int, t)
#endif
+ #if defined(__NR_ppoll)
+ LSS_INLINE _syscall5(int, ppoll, struct kernel_pollfd *, u,
+ unsigned int, n, const struct kernel_timespec *, t,
+ const struct kernel_sigset_t *, sigmask, size_t, s)
+ #endif
LSS_INLINE _syscall5(int, prctl, int, option,
unsigned long, arg2,
unsigned long, arg3,
unsigned long, arg4,
unsigned long, arg5)
LSS_INLINE _syscall4(long, ptrace, int, r,
pid_t, p, void *, a, void *, d)
#if defined(__NR_quotactl)
// Defined on x86_64 / i386 only
LSS_INLINE _syscall4(int, quotactl, int, cmd, const char *, special,
int, id, caddr_t, addr)
#endif
LSS_INLINE _syscall3(ssize_t, read, int, f,
void *, b, size_t, c)
- #if !defined(__aarch64__)
- // The readlink syscall has been deprecated on aarch64. We polyfill below.
+ #if defined(__NR_readlink)
+ // readlink is polyfilled below when not available.
LSS_INLINE _syscall3(int, readlink, const char*, p,
char*, b, size_t, s)
#endif
+ #if defined(__NR_readlinkat)
+ LSS_INLINE _syscall4(int, readlinkat, int, d, const char *, p, char *, b,
+ size_t, s)
+ #endif
LSS_INLINE _syscall4(int, rt_sigaction, int, s,
const struct kernel_sigaction*, a,
struct kernel_sigaction*, o, size_t, c)
LSS_INLINE _syscall2(int, rt_sigpending, struct kernel_sigset_t *, s,
size_t, c)
LSS_INLINE _syscall4(int, rt_sigprocmask, int, h,
const struct kernel_sigset_t*, s,
struct kernel_sigset_t*, o, size_t, c)
@@ -3493,29 +3534,29 @@ struct kernel_statfs {
LSS_INLINE _syscall2(int, setrlimit, int, r,
const struct kernel_rlimit*, l)
LSS_INLINE _syscall0(pid_t, setsid)
LSS_INLINE _syscall2(int, sigaltstack, const stack_t*, s,
const stack_t*, o)
#if defined(__NR_sigreturn)
LSS_INLINE _syscall1(int, sigreturn, unsigned long, u)
#endif
- #if !defined(__aarch64__)
- // The stat syscall has been deprecated on aarch64. We polyfill it below.
+ #if defined(__NR_stat)
+ // stat is polyfilled below when not available.
LSS_INLINE _syscall2(int, stat, const char*, f,
struct kernel_stat*, b)
#endif
LSS_INLINE _syscall2(int, statfs, const char*, f,
struct kernel_statfs*, b)
LSS_INLINE _syscall3(int, tgkill, pid_t, p,
pid_t, t, int, s)
LSS_INLINE _syscall2(int, tkill, pid_t, p,
int, s)
- #if !defined(__aarch64__)
- // The unlink syscall has been deprecated on aarch64. We polyfill it below.
+ #if defined(__NR_unlink)
+ // unlink is polyfilled below when not available.
LSS_INLINE _syscall1(int, unlink, const char*, f)
#endif
LSS_INLINE _syscall3(ssize_t, write, int, f,
const void *, b, size_t, c)
LSS_INLINE _syscall3(ssize_t, writev, int, f,
const struct kernel_iovec*, v, size_t, c)
#if defined(__NR_getcpu)
LSS_INLINE _syscall3(long, getcpu, unsigned *, cpu,
@@ -3603,31 +3644,33 @@ struct kernel_statfs {
union { loff_t off; unsigned w[2]; } o = { offset }, l = { len };
return LSS_NAME(_fallocate)(fd, mode, o.w[0], o.w[1], l.w[0], l.w[1]);
}
#else
LSS_INLINE _syscall4(int, fallocate,
int, f, int, mode, loff_t, offset, loff_t, len)
#endif
#endif
+ #if defined(__NR_newfstatat)
+ LSS_INLINE _syscall4(int, newfstatat, int, d,
+ const char *, p,
+ struct kernel_stat*, b, int, f)
+ #endif
#if defined(__x86_64__) || defined(__s390x__)
LSS_INLINE int LSS_NAME(getresgid32)(gid_t *rgid,
gid_t *egid,
gid_t *sgid) {
return LSS_NAME(getresgid)(rgid, egid, sgid);
}
LSS_INLINE int LSS_NAME(getresuid32)(uid_t *ruid,
uid_t *euid,
uid_t *suid) {
return LSS_NAME(getresuid)(ruid, euid, suid);
}
- LSS_INLINE _syscall4(int, newfstatat, int, d,
- const char *, p,
- struct kernel_stat*, b, int, f)
LSS_INLINE int LSS_NAME(setfsgid32)(gid_t gid) {
return LSS_NAME(setfsgid)(gid);
}
LSS_INLINE int LSS_NAME(setfsuid32)(uid_t uid) {
return LSS_NAME(setfsuid)(uid);
}
@@ -3670,27 +3713,20 @@ struct kernel_statfs {
struct kernel_sigset_t *oldset) {
return LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8);
}
LSS_INLINE int LSS_NAME(sigsuspend)(const struct kernel_sigset_t *set) {
return LSS_NAME(rt_sigsuspend)(set, (KERNEL_NSIG+7)/8);
}
#endif
- #if defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
- defined(__ARM_EABI__) || defined(__aarch64__) || \
- (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32) || \
- defined(__s390__)
+ #if defined(__NR_wait4)
LSS_INLINE _syscall4(pid_t, wait4, pid_t, p,
int*, s, int, o,
struct kernel_rusage*, r)
-
- LSS_INLINE pid_t LSS_NAME(waitpid)(pid_t pid, int *status, int options){
- return LSS_NAME(wait4)(pid, status, options, 0);
- }
#endif
#if defined(__NR_openat)
LSS_INLINE _syscall4(int, openat, int, d, const char *, p, int, f, int, m)
#endif
#if defined(__NR_unlinkat)
LSS_INLINE _syscall3(int, unlinkat, int, d, const char *, p, int, f)
#endif
#if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \
@@ -4186,18 +4222,18 @@ struct kernel_statfs {
return LSS_NAME(socketcall)(8, d, type, protocol, sv);
}
#endif
#if defined(__NR_fstatat64)
LSS_INLINE _syscall4(int, fstatat64, int, d,
const char *, p,
struct kernel_stat64 *, b, int, f)
#endif
- #if defined(__i386__) || defined(__PPC__) || \
- (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32)
+ #if defined(__NR_waitpid)
+ // waitpid is polyfilled below when not available.
LSS_INLINE _syscall3(pid_t, waitpid, pid_t, p,
int*, s, int, o)
#endif
#if defined(__mips__)
/* sys_pipe() on MIPS has non-standard calling conventions, as it returns
* both file handles through CPU registers.
*/
LSS_INLINE int LSS_NAME(pipe)(int *p) {
@@ -4214,20 +4250,23 @@ struct kernel_statfs {
LSS_ERRNO = __errnovalue;
return -1;
} else {
p[0] = __v0;
p[1] = __v1;
return 0;
}
}
- #elif !defined(__aarch64__)
- // The unlink syscall has been deprecated on aarch64. We polyfill it below.
+ #elif defined(__NR_pipe)
+ // pipe is polyfilled below when not available.
LSS_INLINE _syscall1(int, pipe, int *, p)
#endif
+ #if defined(__NR_pipe2)
+ LSS_INLINE _syscall2(int, pipe2, int *, pipefd, int, flags)
+ #endif
/* TODO(csilvers): see if ppc can/should support this as well */
#if defined(__i386__) || defined(__ARM_ARCH_3__) || \
defined(__ARM_EABI__) || \
(defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64) || \
(defined(__s390__) && !defined(__s390x__))
#define __NR__statfs64 __NR_statfs64
#define __NR__fstatfs64 __NR_fstatfs64
LSS_INLINE _syscall3(int, _statfs64, const char*, p,
@@ -4394,72 +4433,84 @@ struct kernel_statfs {
}
LSS_INLINE int LSS_NAME(readahead)(int fd, loff_t off, int len) {
union { loff_t off; unsigned arg[2]; } o = { off };
return LSS_NAME(_readahead)(fd, LSS_LLARG_PAD o.arg[0], o.arg[1], len);
}
#endif
#endif
-#if defined(__aarch64__)
- LSS_INLINE _syscall3(int, dup3, int, s, int, d, int, f)
- LSS_INLINE _syscall4(int, newfstatat, int, dirfd, const char *, pathname,
- struct kernel_stat *, buf, int, flags)
- LSS_INLINE _syscall2(int, pipe2, int *, pipefd, int, flags)
- LSS_INLINE _syscall5(int, ppoll, struct kernel_pollfd *, u,
- unsigned int, n, const struct kernel_timespec *, t,
- const struct kernel_sigset_t *, sigmask, size_t, s)
- LSS_INLINE _syscall4(int, readlinkat, int, d, const char *, p, char *, b,
- size_t, s)
-#endif
-
/*
* Polyfills for deprecated syscalls.
*/
-#if defined(__aarch64__)
+#if !defined(__NR_dup2)
LSS_INLINE int LSS_NAME(dup2)(int s, int d) {
return LSS_NAME(dup3)(s, d, 0);
}
+#endif
+#if !defined(__NR_open)
LSS_INLINE int LSS_NAME(open)(const char *pathname, int flags, int mode) {
return LSS_NAME(openat)(AT_FDCWD, pathname, flags, mode);
}
+#endif
+#if !defined(__NR_unlink)
LSS_INLINE int LSS_NAME(unlink)(const char *pathname) {
return LSS_NAME(unlinkat)(AT_FDCWD, pathname, 0);
}
+#endif
+#if !defined(__NR_readlink)
LSS_INLINE int LSS_NAME(readlink)(const char *pathname, char *buffer,
size_t size) {
return LSS_NAME(readlinkat)(AT_FDCWD, pathname, buffer, size);
}
+#endif
+#if !defined(__NR_pipe)
LSS_INLINE pid_t LSS_NAME(pipe)(int *pipefd) {
return LSS_NAME(pipe2)(pipefd, 0);
}
+#endif
+#if !defined(__NR_poll)
LSS_INLINE int LSS_NAME(poll)(struct kernel_pollfd *fds, unsigned int nfds,
int timeout) {
struct kernel_timespec timeout_ts;
struct kernel_timespec *timeout_ts_p = NULL;
if (timeout >= 0) {
timeout_ts.tv_sec = timeout / 1000;
timeout_ts.tv_nsec = (timeout % 1000) * 1000000;
timeout_ts_p = &timeout_ts;
}
return LSS_NAME(ppoll)(fds, nfds, timeout_ts_p, NULL, 0);
}
+#endif
+#if !defined(__NR_stat)
LSS_INLINE int LSS_NAME(stat)(const char *pathname,
struct kernel_stat *buf) {
return LSS_NAME(newfstatat)(AT_FDCWD, pathname, buf, 0);
}
+#endif
+#if !defined(__NR_waitpid)
+ LSS_INLINE pid_t LSS_NAME(waitpid)(pid_t pid, int *status, int options) {
+ return LSS_NAME(wait4)(pid, status, options, 0);
+ }
+#endif
+
+#if !defined(__NR_fork)
+// TODO: define this in an arch-independant way instead of inlining the clone
+// syscall body.
+
+# if defined(__aarch64__)
LSS_INLINE pid_t LSS_NAME(fork)(void) {
// No fork syscall on aarch64 - implement by means of the clone syscall.
// Note that this does not reset glibc's cached view of the PID/TID, so
// some glibc interfaces might go wrong in the forked subprocess.
int flags = SIGCHLD;
void *child_stack = NULL;
void *parent_tidptr = NULL;
void *newtls = NULL;
@@ -4468,16 +4519,33 @@ struct kernel_statfs {
LSS_REG(0, flags);
LSS_REG(1, child_stack);
LSS_REG(2, parent_tidptr);
LSS_REG(3, newtls);
LSS_REG(4, child_tidptr);
LSS_BODY(pid_t, clone, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3),
"r"(__r4));
}
+# elif defined(__x86_64__)
+ LSS_INLINE pid_t LSS_NAME(fork)(void) {
+ // Android disallows the fork syscall on x86_64 - implement by means of the
+ // clone syscall as above for aarch64.
+ int flags = SIGCHLD;
+ void *child_stack = NULL;
+ void *parent_tidptr = NULL;
+ void *newtls = NULL;
+ void *child_tidptr = NULL;
+
+ LSS_BODY(5, pid_t, clone, LSS_SYSCALL_ARG(flags),
+ LSS_SYSCALL_ARG(child_stack), LSS_SYSCALL_ARG(parent_tidptr),
+ LSS_SYSCALL_ARG(newtls), LSS_SYSCALL_ARG(child_tidptr));
+ }
+# else
+# error missing fork polyfill for this architecture
+# endif
#endif
#ifdef __ANDROID__
/* These restore the original values of these macros saved by the
* corresponding #pragma push_macro near the top of this file. */
# pragma pop_macro("stat64")
# pragma pop_macro("fstat64")
# pragma pop_macro("lstat64")