diff --git a/testing/firefox/build b/testing/firefox/build
new file mode 100755
index 00000000..3e279a7b
--- /dev/null
+++ b/testing/firefox/build
@@ -0,0 +1,39 @@
+#!/bin/sh -e
+
+# Build autoconf 2.13 for Firefox's sole use.
+# See: https://bugzilla.mozilla.org/show_bug.cgi?id=104642
+(
+    cd autoconf2.13
+    ./configure --prefix="$PWD/../autoconf" --program-suffix=-2.13
+    make
+    make install
+)
+export PATH="$PWD/autoconf/bin:$PATH"
+
+# Fix linker errors at runtime.
+export LDFLAGS="$LDFLAGS -Wl,-rpath=/usr/lib/firefox"
+
+unset  MOZ_TELEMETRY_REPORTING
+export MOZ_NOSPAM=1
+
+cd firefox
+
+# Fix OOM errors.
+cores=$(nproc)
+printf '%s\n' "mk_add_options MOZ_MAKE_FLAGS=\"-j$cores -l$cores\"" >> mozconfig
+
+for patch in *.patch; do
+    patch -p1 < "$patch"
+done
+
+./mach build
+DESTDIR="$1" ./mach install
+
+rm -rf "$1/usr/include"
+rm -rf "$1/usr/lib/firefox-devel"
+rm -rf "$1/usr/share/idl"
+rm -rf "$1/usr/lib/firefox/gtk2"
+
+# Install Ghack's user.js.
+mkdir -p "$1/usr/lib/firefox/browser/defaults/preferences/"
+cp -f ./user.js "$1/usr/lib/firefox/browser/defaults/preferences/vendor.js"
diff --git a/testing/firefox/checksums b/testing/firefox/checksums
new file mode 100644
index 00000000..3be93350
--- /dev/null
+++ b/testing/firefox/checksums
@@ -0,0 +1,13 @@
+f56f5fa5a4744be0b9acf259cb991254d708a50b9a0a12d1d846ffa5a6c409ac  firefox-68.1.0esr.source.tar.xz
+f0611136bee505811e9ca11ca7ac188ef5323a8e2ef19cffd3edb3cf08fd791e  autoconf-2.13.tar.gz
+8355ff012e7380f9eec70f8e2c02d256f097943438c9cfba968cd06401c443df  user.js
+143c5f3348713eaa0850c9ba5b0233603a85764feda9fa5b267f9f4424d03f4c  mozconfig
+960d82bbfdc88c95f5cb4f2e1c1bf23dae7519b3b7203914d7b3ddbff1ba4c28  stab.h
+315880530f09175788dfa48a1915bfa1e190bfd3e267988b9100cb93006c808c  fix-fortify-system-wrappers.patch
+026e778105ed4921d61b6f9935a861b7e9ba9ac8cc44d8516883c3b5bd7590c4  fix-musl.patch
+418a2a9f80c41ee004cb640968617cab283b99f3d109aaf6180b0088d60c84b0  fix-sandbox-membarrier.patch
+14f281ee323aa682e04479019171bde243ac6227820856aa03b162179b14bfd9  fix-seccomp-bpf.patch
+b19aaae7fc45db643f8d2540d96919c745ea341e36d9aea2df40e3e90eb951f0  fix-toolkit.patch
+e24f71a6a0d8d4637b2081780c66b01be4eeb4dd496031270d0ae0b898be94d2  fix-tools.patch
+5e0fcfde375837074baad21a8ab26aa442a7940617ebd074a6b238a48f2ceb63  fix-webrtc-glibcisms.patch
+1d4a8f110d34da478f5597727eda9acacebd443dd86cce5bb64f898c01feabce  mallinfo.patch
diff --git a/testing/firefox/depends b/testing/firefox/depends
new file mode 100644
index 00000000..35a0b17f
--- /dev/null
+++ b/testing/firefox/depends
@@ -0,0 +1,28 @@
+alsa-lib
+bzip2
+cbindgen      make
+clang         make
+ffmpeg
+freetype-harfbuzz make
+gtk+2         make
+gtk+3
+hicolor-icon-theme
+libSM
+libXcomposite
+libXcursor
+libXrender
+libXt
+libjpeg-turbo
+libffi
+libpng
+libvpx
+llvm          make
+nasm          make
+nodejs        make
+perl          make
+pixman
+python        make
+python2       make
+rust          make
+yasm          make
+zip           make
diff --git a/testing/firefox/files/mozconfig b/testing/firefox/files/mozconfig
new file mode 100644
index 00000000..3bf11ef8
--- /dev/null
+++ b/testing/firefox/files/mozconfig
@@ -0,0 +1,58 @@
+ac_add_options --prefix=/usr
+ac_add_options --libdir=/usr/lib
+
+ac_add_options --enable-official-branding
+ac_add_options --enable-optimize="$CFLAGS"
+ac_add_options --enable-install-strip
+ac_add_options --enable-strip
+
+ac_add_options --without-system-nspr
+ac_add_options --without-system-nss
+ac_add_options --with-system-jpeg
+ac_add_options --with-system-zlib
+ac_add_options --with-system-bz2
+ac_add_options --with-system-png
+
+# System 'libvpx' is too new.
+ac_add_options --without-system-libvpx
+
+ac_add_options --with-system-pixman
+ac_add_options --with-system-ffi
+
+ac_add_options --disable-gconf
+ac_add_options --disable-profiling
+ac_add_options --disable-accessibility
+ac_add_options --disable-tests
+ac_add_options --disable-system-extension-dirs
+ac_add_options --disable-parental-controls
+ac_add_options --disable-debug-symbols
+ac_add_options --disable-callgrind
+ac_add_options --disable-vtune
+
+# musl
+ac_add_options --disable-elf-hack
+ac_add_options --disable-gold
+ac_add_options --disable-jemalloc
+ac_add_options --enable-release
+
+# ALSA/PulseAudio (removed in 70)
+ac_add_options --disable-pulseaudio
+ac_add_options --enable-alsa
+
+ac_add_options --disable-startup-notification
+
+# Respect the user.
+export MOZ_SERVICES_METRICS=0
+export MOZ_PAY=0
+export MOZ_SERVICES_HEALTHREPORTER=0
+export MOZ_SERVICES_FXACCOUNTS=0
+export MOZ_SERVICES_METRICS=0
+export MOZ_DATA_REPORTING=0
+export MOZ_DEVICES=0
+export MOZ_REQUIRE_SIGNING=0
+ac_add_options --disable-crashreporter
+ac_add_options --disable-updater
+ac_add_options --disable-dbus
+ac_add_options --disable-eme
+ac_add_options --disable-necko-wifi
+ac_add_options --disable-webrtc
diff --git a/testing/firefox/files/stab.h b/testing/firefox/files/stab.h
new file mode 100644
index 00000000..6f70af39
--- /dev/null
+++ b/testing/firefox/files/stab.h
@@ -0,0 +1,71 @@
+/*	$OpenBSD: stab.h,v 1.3 2003/06/02 19:34:12 millert Exp $	*/
+/*	$NetBSD: stab.h,v 1.4 1994/10/26 00:56:25 cgd Exp $	*/
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)stab.h	5.2 (Berkeley) 4/4/91
+ */
+
+#ifndef _STAB_H_
+#define _STAB_H_
+
+/*
+ * The following are symbols used by various debuggers and by the Pascal
+ * compiler.  Each of them must have one (or more) of the bits defined by
+ * the N_STAB mask set.
+ */
+
+#define	N_GSYM		0x20	/* global symbol */
+#define	N_FNAME		0x22	/* F77 function name */
+#define	N_FUN		0x24	/* procedure name */
+#define	N_STSYM		0x26	/* data segment variable */
+#define	N_LCSYM		0x28	/* bss segment variable */
+#define	N_MAIN		0x2a	/* main function name */
+#define	N_PC		0x30	/* global Pascal symbol */
+#define	N_RSYM		0x40	/* register variable */
+#define	N_SLINE		0x44	/* text segment line number */
+#define	N_DSLINE	0x46	/* data segment line number */
+#define	N_BSLINE	0x48	/* bss segment line number */
+#define	N_SSYM		0x60	/* structure/union element */
+#define	N_SO		0x64	/* main source file name */
+#define	N_LSYM		0x80	/* stack variable */
+#define	N_BINCL		0x82	/* include file beginning */
+#define	N_SOL		0x84	/* included source file name */
+#define	N_PSYM		0xa0	/* parameter variable */
+#define	N_EINCL		0xa2	/* include file end */
+#define	N_ENTRY		0xa4	/* alternate entry point */
+#define	N_LBRAC		0xc0	/* left bracket */
+#define	N_EXCL		0xc2	/* deleted include file */
+#define	N_RBRAC		0xe0	/* right bracket */
+#define	N_BCOMM		0xe2	/* begin common */
+#define	N_ECOMM		0xe4	/* end common */
+#define	N_ECOML		0xe8	/* end common (local name) */
+#define	N_LENG		0xfe	/* length of preceding entry */
+
+#endif /* !_STAB_H_ */
diff --git a/testing/firefox/patches/fix-fortify-system-wrappers.patch b/testing/firefox/patches/fix-fortify-system-wrappers.patch
new file mode 100644
index 00000000..17cf7e30
--- /dev/null
+++ b/testing/firefox/patches/fix-fortify-system-wrappers.patch
@@ -0,0 +1,13 @@
+The wrapper features.h gets pulled in by system headers causing thigns to
+break. We work around it by simply not wrap features.h
+
+--- ./config/system-headers.mozbuild.orig
++++ ./config/system-headers.mozbuild
+@@ -229,7 +229,6 @@
+     'execinfo.h',
+     'extras.h',
+     'fcntl.h',
+-    'features.h',
+     'fenv.h',
+     'ffi.h',
+     'fibdef.h',
diff --git a/testing/firefox/patches/fix-musl.patch b/testing/firefox/patches/fix-musl.patch
new file mode 100644
index 00000000..996a45f1
--- /dev/null
+++ b/testing/firefox/patches/fix-musl.patch
@@ -0,0 +1,11 @@
+--- a/tools/profiler/core/platform-linux-android.cpp	2019-07-09 22:58:30.039475686 +0200
++++ b/tools/profiler/core/platform-linux-android.cpp	2019-07-09 22:58:39.331437677 +0200
+@@ -73,7 +73,7 @@
+ 
+ int profiler_current_thread_id() {
+   // glibc doesn't provide a wrapper for gettid().
+-#if defined(__GLIBC__)
++#if defined(__linux__)
+   return static_cast<int>(static_cast<pid_t>(syscall(SYS_gettid)));
+ #else
+   return static_cast<int>(gettid());
diff --git a/testing/firefox/patches/fix-rust-target.patch b/testing/firefox/patches/fix-rust-target.patch
new file mode 100644
index 00000000..8c4b6739
--- /dev/null
+++ b/testing/firefox/patches/fix-rust-target.patch
@@ -0,0 +1,24 @@
+--- a/build/moz.configure/rust.configure
++++ b/build/moz.configure/rust.configure
+@@ -280,9 +280,11 @@
+             die("Don't know how to translate {} for rustc".format(
+                 host_or_target.alias))
+ 
++        fixed_alias = rustc_target.alias.replace("-unknown-", "-alpine-").replace("-gnu", "-musl")
++
+         # Check to see whether our rustc has a reasonably functional stdlib
+         # for our chosen target.
+-        target_arg = '--target=' + rustc_target.alias
++        target_arg = '--target=' + fixed_alias
+         in_fd, in_path = mkstemp(prefix='conftest', suffix='.rs')
+         out_fd, out_path = mkstemp(prefix='conftest', suffix='.rlib')
+         os.close(out_fd)
+@@ -319,7 +321,7 @@
+             os.remove(out_path)
+ 
+         # This target is usable.
+-        return rustc_target.alias
++        return fixed_alias
+ 
+     return rust_target
+ 
diff --git a/testing/firefox/patches/fix-sandbox-membarrier.patch b/testing/firefox/patches/fix-sandbox-membarrier.patch
new file mode 100644
index 00000000..4bd3b80d
--- /dev/null
+++ b/testing/firefox/patches/fix-sandbox-membarrier.patch
@@ -0,0 +1,54 @@
+allow usage of SYS_membarrier, needed since musl-1.1.22
+
+Taken from voidlinux: https://github.com/void-linux/void-packages/commit/4198411ac3b9e2620e171c662df82008da0faebb
+
+--- a/security/sandbox/linux/SandboxFilter.cpp
++++ b/security/sandbox/linux/SandboxFilter.cpp
+@@ -572,6 +572,8 @@
+       case __NR_set_tid_address:
+         return Allow();
+ #endif
++      case __NR_membarrier:
++        return Allow();
+ 
+         // prctl
+       case __NR_prctl: {
+
+--- a/security/sandbox/chromium/sandbox/linux/system_headers/arm_linux_syscalls.h
++++ b/security/sandbox/chromium/sandbox/linux/system_headers/arm_linux_syscalls.h
+@@ -1385,6 +1385,10 @@
+ #define __NR_memfd_create (__NR_SYSCALL_BASE+385)
+ #endif
+ 
++#if !defined(__NR_membarrier)
++#define __NR_membarrier (__NR_SYSCALL_BASE+389)
++#endif
++
+ // ARM private syscalls.
+ #if !defined(__ARM_NR_BASE)
+ #define __ARM_NR_BASE (__NR_SYSCALL_BASE + 0xF0000)
+
+--- a/security/sandbox/chromium/sandbox/linux/system_headers/x86_64_linux_syscalls.h
++++ b/security/sandbox/chromium/sandbox/linux/system_headers/x86_64_linux_syscalls.h
+@@ -1290,5 +1290,9 @@
+ #define __NR_memfd_create 319
+ #endif
+ 
++#if !defined(__NR_membarrier)
++#define __NR_membarrier 324
++#endif
++
+ #endif  // SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_SYSCALLS_H_
+ 
+--- a/security/sandbox/chromium/sandbox/linux/system_headers/x86_32_linux_syscalls.h
++++ b/security/sandbox/chromium/sandbox/linux/system_headers/x86_32_linux_syscalls.h
+@@ -1490,5 +1490,9 @@
+ #define __NR_shutdown 373
+ #endif
+ 
++#if !defined(__NR_membarrier)
++#define __NR_membarrier 375
++#endif
++
+ #endif  // SANDBOX_LINUX_SYSTEM_HEADERS_X86_32_LINUX_SYSCALLS_H_
+ 
diff --git a/testing/firefox/patches/fix-seccomp-bpf.patch b/testing/firefox/patches/fix-seccomp-bpf.patch
new file mode 100644
index 00000000..da102b46
--- /dev/null
+++ b/testing/firefox/patches/fix-seccomp-bpf.patch
@@ -0,0 +1,14 @@
+--- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc
++++ b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc
+@@ -25,6 +25,11 @@
+ #include "sandbox/linux/system_headers/linux_seccomp.h"
+ #include "sandbox/linux/system_headers/linux_signal.h"
+ 
++// musl libc defines siginfo_t __si_fields instead of _sifields
++#if defined(OS_LINUX) && !defined(__GLIBC__)
++#define _sifields __si_fields
++#endif
++
+ namespace {
+ 
+ struct arch_sigsys {
diff --git a/testing/firefox/patches/fix-toolkit.patch b/testing/firefox/patches/fix-toolkit.patch
new file mode 100644
index 00000000..414734df
--- /dev/null
+++ b/testing/firefox/patches/fix-toolkit.patch
@@ -0,0 +1,90 @@
+diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
+index 4222ce3..4d40c6a 100644
+--- a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
+@@ -46,6 +46,7 @@
+ #include <sys/mman.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
++#include <libgen.h>
+ 
+ #include <iostream>
+ #include <set>
+diff --git a/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.cc b/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.cc
+index 6019fc7..5953e32 100644
+--- a/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.cc
++++ b/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.cc
+@@ -41,6 +41,10 @@
+ 
+ #include "common/using_std_string.h"
+ 
++#ifndef N_UNDF
++#define N_UNDF 0
++#endif
++
+ using std::vector;
+ 
+ namespace google_breakpad {
+diff --git a/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.h b/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.h
+index 98ee2dd..d57aa68 100644
+--- a/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.h
++++ b/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.h
+@@ -55,7 +55,7 @@
+ 
+ #ifdef HAVE_MACH_O_NLIST_H
+ #include <mach-o/nlist.h>
+-#elif defined(HAVE_A_OUT_H)
++#elif 0
+ #include <a.out.h>
+ #endif
+ 
+diff --git 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
+index 93fdad7..f34e5e0 100644
+--- 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
+@@ -1239,6 +1239,12 @@ struct kernel_statfs {
+ #ifndef __NR_fallocate
+ #define __NR_fallocate          285
+ #endif
++
++#undef __NR_pread
++#define __NR_pread __NR_pread64
++#undef __NR_pwrite
++#define __NR_pwrite __NR_pwrite64
++
+ /* End of x86-64 definitions                                                 */
+ #elif defined(__mips__)
+ #if _MIPS_SIM == _MIPS_SIM_ABI32
+diff --git a/toolkit/mozapps/update/common/updatedefines.h b/toolkit/mozapps/update/common/updatedefines.h
+index 79276f7..4c67976 100644
+--- a/toolkit/mozapps/update/common/updatedefines.h
++++ b/toolkit/mozapps/update/common/updatedefines.h
+@@ -87,7 +87,7 @@ static inline int mywcsprintf(WCHAR* dest, size_t count, const WCHAR* fmt,
+
+ #  ifdef SOLARIS
+ #    include <sys/stat.h>
+-#  else
++#  elif !defined(__linux__) || defined(__GLIBC__)
+ #    include <fts.h>
+ #  endif
+ #  include <dirent.h>
+diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp
+index 257ccb4..01314e4 100644
+--- a/toolkit/mozapps/update/updater/updater.cpp
++++ b/toolkit/mozapps/update/updater/updater.cpp
+@@ -3978,6 +3978,7 @@
+ 
+ int add_dir_entries(const NS_tchar* dirpath, ActionList* list) {
+   int rv = OK;
++#if !defined(__linux__) || defined(__GLIBC__)
+   FTS* ftsdir;
+   FTSENT* ftsdirEntry;
+   mozilla::UniquePtr<NS_tchar[]> searchpath(get_full_path(dirpath));
+@@ -4085,6 +4086,7 @@
+   }
+ 
+   fts_close(ftsdir);
++#endif
+ 
+   return rv;
+ }
diff --git a/testing/firefox/patches/fix-tools.patch b/testing/firefox/patches/fix-tools.patch
new file mode 100644
index 00000000..93b9d19c
--- /dev/null
+++ b/testing/firefox/patches/fix-tools.patch
@@ -0,0 +1,37 @@
+diff --git a/tools/profiler/core/platform-linux-android.cpp b/tools/profiler/core/platform-linux-android.cpp
+index 19d0a5c56d..b64b543066 100644
+--- a/tools/profiler/core/platform-linux-android.cpp
++++ b/tools/profiler/core/platform-linux-android.cpp
+@@ -506,8 +506,10 @@ static void PlatformInit(PSLockRef aLock) {}
+ ucontext_t sSyncUContext;
+ 
+ void Registers::SyncPopulate() {
+-  if (!getcontext(&sSyncUContext)) {
+-    PopulateRegsFromContext(*this, &sSyncUContext);
+-  }
++  #if defined(__GLIBC__)
++    if (!getcontext(&sSyncUContext)) {
++      PopulateRegsFromContext(*this, &sSyncUContext);
++    }
++  #endif
+ }
+ #endif
+diff --git a/tools/profiler/lul/LulElf.cpp b/tools/profiler/lul/LulElf.cpp
+index 9998d04d0d..348a7086fc 100644
+--- a/tools/profiler/lul/LulElf.cpp
++++ b/tools/profiler/lul/LulElf.cpp
+@@ -469,10 +469,10 @@ string FormatIdentifier(unsigned char identifier[16]) {
+ // Return the non-directory portion of FILENAME: the portion after the
+ // last slash, or the whole filename if there are no slashes.
+ string BaseFileName(const string& filename) {
+-  // Lots of copies!  basename's behavior is less than ideal.
+-  char* c_filename = strdup(filename.c_str());
+-  string base = basename(c_filename);
+-  free(c_filename);
++  // basename's behavior is less than ideal so avoid it
++  const char *c_filename = filename.c_str();
++  const char *p = strrchr(c_filename, '/');
++  string base = p ? p+1 : c_filename;
+   return base;
+ }
+ 
diff --git a/testing/firefox/patches/fix-webrtc-glibcisms.patch b/testing/firefox/patches/fix-webrtc-glibcisms.patch
new file mode 100644
index 00000000..658b076d
--- /dev/null
+++ b/testing/firefox/patches/fix-webrtc-glibcisms.patch
@@ -0,0 +1,20 @@
+--- ./media/webrtc/trunk/webrtc/system_wrappers/source/cpu_features_linux.c.orig	2018-05-09 23:48:44.677389171 +0200
++++ ./media/webrtc/trunk/webrtc/system_wrappers/source/cpu_features_linux.c	2018-05-09 23:48:56.254373557 +0200
+@@ -14,7 +14,7 @@
+ #ifndef __GLIBC_PREREQ
+ #define __GLIBC_PREREQ(a, b) 0
+ #endif
+-#if __GLIBC_PREREQ(2, 16)
++#if !__GLIBC__ || __GLIBC_PREREQ(2, 16)
+ #include <sys/auxv.h>
+ #else
+ #include <fcntl.h>
+@@ -32,7 +32,7 @@
+   int architecture = 0;
+   unsigned long hwcap = 0;
+   const char* platform = NULL;
+-#if __GLIBC_PREREQ(2, 16)
++#if !__GLIBC__ || __GLIBC_PREREQ(2, 16)
+   hwcap = getauxval(AT_HWCAP);
+   platform = (const char*)getauxval(AT_PLATFORM);
+ #else
diff --git a/testing/firefox/patches/mallinfo.patch b/testing/firefox/patches/mallinfo.patch
new file mode 100644
index 00000000..0649413c
--- /dev/null
+++ b/testing/firefox/patches/mallinfo.patch
@@ -0,0 +1,34 @@
+--- a/xpcom/base/nsMemoryReporterManager.cpp.orig	2019-03-19 17:12:20.844810044 +0100
++++ b/xpcom/base/nsMemoryReporterManager.cpp	2019-03-19 17:13:32.505133615 +0100
+@@ -123,6 +123,7 @@
+   return GetProcSelfSmapsPrivate(aN);
+ }
+
++#ifdef __GLIBC__
+ #  ifdef HAVE_MALLINFO
+ #    define HAVE_SYSTEM_HEAP_REPORTER 1
+ static MOZ_MUST_USE nsresult SystemHeapSize(int64_t* aSizeOut) {
+@@ -142,6 +143,7 @@
+   return NS_OK;
+ }
+ #  endif
++#endif // __GLIBC__
+
+ #elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
+     defined(__OpenBSD__) || defined(__FreeBSD_kernel__)
+@@ -642,6 +644,7 @@
+   return NS_OK;
+ }
+
++#ifdef __GLIBC__
+ #  define HAVE_SYSTEM_HEAP_REPORTER 1
+ // Windows can have multiple separate heaps. During testing there were multiple
+ // heaps present but the non-default ones had sizes no more than a few 10s of
+@@ -698,6 +701,7 @@
+   *aSizeOut = heapsSize;
+   return NS_OK;
+ }
++#endif // __GLIBC__
+
+ struct SegmentKind {
+   DWORD mState;
diff --git a/testing/firefox/sources b/testing/firefox/sources
new file mode 100644
index 00000000..0e6d8ba0
--- /dev/null
+++ b/testing/firefox/sources
@@ -0,0 +1,13 @@
+https://archive.mozilla.org/pub/firefox/candidates/68.1.0esr-candidates/build1/source/firefox-68.1.0esr.source.tar.xz firefox/
+https://ftp.gnu.org/gnu/autoconf/autoconf-2.13.tar.gz autoconf2.13/
+https://raw.githubusercontent.com/ghacksuserjs/ghacks-user.js/6618bf5f7693a15c77f863b6c5d9dabd5f72972a/user.js firefox/
+files/mozconfig firefox/
+files/stab.h firefox/toolkit/crashreporter/google-breakpad/src/
+patches/fix-fortify-system-wrappers.patch firefox/
+patches/fix-musl.patch firefox/
+patches/fix-sandbox-membarrier.patch firefox/
+patches/fix-seccomp-bpf.patch firefox/
+patches/fix-toolkit.patch firefox/
+patches/fix-tools.patch firefox/
+patches/fix-webrtc-glibcisms.patch firefox/
+patches/mallinfo.patch firefox/
diff --git a/testing/firefox/version b/testing/firefox/version
new file mode 100644
index 00000000..2ec14b49
--- /dev/null
+++ b/testing/firefox/version
@@ -0,0 +1 @@
+68.1.0 1