Bug 1456203 - Take patch from upstream lss to fix use of disallowed syscalls on Android r=ted
authorJames Willcox <snorp@snorp.net>
Mon, 23 Apr 2018 11:58:31 -0500
changeset 415337 6bf69d965bbe697e69fc0df014e7f326aa423385
parent 415336 5336e6fd895be772cf603dbd8a6580be723829aa
child 415338 31dd07dd000efefc62ae97317ac336aec085ef79
push id102559
push userjwillcox@mozilla.com
push dateTue, 24 Apr 2018 19:22:41 +0000
treeherdermozilla-inbound@6bf69d965bbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs1456203, 699213
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1456203 - Take patch from upstream lss to fix use of disallowed syscalls on Android r=ted https://chromium-review.googlesource.com/c/linux-syscall-support/+/699213 MozReview-Commit-ID: 7hjCWfwcuHR
toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h
--- 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")