Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
6ff539e
Setup project for IA2 rewriter
randomPoison Mar 26, 2025
7913095
Initial rewriter changes
randomPoison Apr 1, 2025
0f5fee6
Only rewrite specified files
randomPoison Apr 2, 2025
31d1292
Rename functions to avoid name collisions
randomPoison Apr 2, 2025
f9ab515
Wrap callback fns in nsJPEGEncoder.cpp
randomPoison Apr 2, 2025
b93b556
Include ia2.h in mjpeg_decoder.cc
randomPoison Apr 3, 2025
a26bdfa
Move compartment initialization to nsBrowserApp.cpp
randomPoison Apr 3, 2025
09c076f
Enable IA2 in image/decoders build
randomPoison Apr 7, 2025
18f6bd9
Add compile/link flags to main app build
randomPoison Apr 7, 2025
a90bd35
Copy __wrap_main into nsBrowserApp.cpp and also use dlsym for loading…
randomPoison Apr 8, 2025
f8c2d40
Generate some missing stuff in wrapper.h
randomPoison Apr 8, 2025
660e7f1
Init runtime in nsJPEGDecoder.cpp
randomPoison Apr 8, 2025
240df33
Update wrappers after rewriter fixes
randomPoison Apr 8, 2025
b310646
Move ia2_stackptr_0 into nsBrowserApp.cpp
randomPoison Apr 8, 2025
956b12e
Fixes in nsJPEGDecoder.cpp
randomPoison Apr 8, 2025
ada4ec3
Various many changes to get things working
randomPoison May 2, 2025
d6ffdaf
Ignore libia2 and libcallgates
randomPoison May 2, 2025
41168a3
Remove GH workflow
randomPoison May 2, 2025
468188e
Setup partition-alloc through the replace-malloc functionality
randomPoison May 8, 2025
0f3706f
Don't printf before we've set the pkru
randomPoison May 8, 2025
3ac3bc2
Disable jemalloc-specific functionality
randomPoison May 13, 2025
7cdf941
Disable custom operator new/delete overrides
randomPoison May 27, 2025
3bf3f7a
Enable the various --wrap=malloc linker args
randomPoison May 28, 2025
063204c
Add partition-alloc to include path
randomPoison May 28, 2025
e6c624e
Force deallocation to go through __real_free when allocation comes fr…
randomPoison May 29, 2025
62b2f5e
Add script for modifying .mozbuild sysroot
randomPoison Jul 8, 2025
0b42981
Commit mozconfig
randomPoison Jul 8, 2025
2fd8c6b
Allocate nsJPEGDecoder on the shared heap
randomPoison Jul 15, 2025
df0f9db
Print dlerror if we fail to open libxul.so
randomPoison Jul 15, 2025
8f3abe6
Put environment variables on the shared heap
randomPoison Jul 15, 2025
7b74860
Move jpeg buffers to shared heap
randomPoison Jul 22, 2025
912b45a
Add a simple demo case
randomPoison Jul 22, 2025
d15befc
Add "exploit" jpeg
randomPoison Aug 12, 2025
4627bb4
Inject synthetic vulnerability into libjpeg
randomPoison Aug 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions .github/workflows/README

This file was deleted.

20 changes: 0 additions & 20 deletions .github/workflows/close-pr.yml

This file was deleted.

3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ ID
/.clang-tidy
/.clangd
/.mozconfig*
/mozconfig*
/.moz-fast-forward
/.moz-vendoring
/old-configure
Expand Down Expand Up @@ -362,3 +361,5 @@ toolkit/crashreporter/minidump-analyzer/analyzer-test/target/

# Ignore mozperftest artifacts folder
/artifacts/
third_party/ia2/liblibia2.a
libcallgates.so
44 changes: 44 additions & 0 deletions browser/app/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,47 @@ for icon in ("firefox", "document", "newwindow", "newtab", "pbmode", "document_p
CONFIG["MOZ_BRANDING_DIRECTORY"],
icon,
)

CXXFLAGS += [
"-DIA2_ENABLE=1",
# "-DIA2_ENABLE=0",
"-DIA2_DEBUG=1",
"-DIA2_DEBUG_LOG=1",
"-ftls-model=initial-exec",
]

LDFLAGS += [
"-Wl,--wrap=calloc",
"-Wl,--wrap=free",
"-Wl,--wrap=malloc",
"-Wl,--wrap=memalign",
"-Wl,--wrap=posix_memalign",
"-Wl,--wrap=pvalloc",
"-Wl,--wrap=realloc",
"-Wl,--wrap=valloc",
"-Wl,--wrap=malloc_usable_size",
"-Wl,--wrap=realpath",
"-Wl,--wrap=strdup",
"-Wl,--wrap=strndup",
"-Wl,--wrap=getcwd",
"-Wl,--wrap=asprintf",
"-Wl,--wrap=vasprintf",

"-Wl,--wrap=main",
# "-Wl,--wrap=pthread_create",
"-pthread",
"-Wl,-z,now",
"-Wl,-z,relro",
"-Wl,-T/home/legare/IA2-Phase2/runtime/libia2/padding.ld",
"-Wl,--dynamic-list=/home/legare/IA2-Phase2/runtime/libia2/dynsym.syms",
"-Wl,--export-dynamic",
"-L/home/legare/IA2-Phase2/build/runtime/libia2",
"-L/home/legare/IA2-Phase2/build/runtime/partition-alloc",
"-L/home/legare/ff-rewritten",
"-llibia2",
"-lpartition-alloc",
"-Wl,@/home/legare/ff-rewritten/wrapper_1.ld",
"-Wl,--export-dynamic-symbol=ia2_stackptr_0",
"-Wl,--trace-symbol=ia2_stackptr_0",
"-Wl,--version-script=/home/legare/ff-rewritten/browser/app/version.script",
]
155 changes: 155 additions & 0 deletions browser/app/nsBrowserApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,161 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

extern "C" {
#define _GNU_SOURCE
#undef NDEBUG
#include <assert.h>

#include <ia2.h>

// INIT_RUNTIME(1);

// // This must be defined before including the following line
// #define IA2_COMPARTMENT 1

// #include <ia2_compartment_init.inc>

#include <dlfcn.h>

__attribute__((visibility("default"))) __thread void *ia2_stackptr_0[PAGE_SIZE / sizeof(void *)] __attribute__((aligned(4096)));

__attribute__((visibility("default"))) void *ia2_init_stackptr;

void *ia2_get_stackptr_1(void) {
void *handle = dlopen("libxul.so", RTLD_NOW | RTLD_GLOBAL | RTLD_NOLOAD);
printf("ia2_get_stackptr_1: %s\n", dlerror());
assert(handle);
void **res = (void**)dlsym(handle, "ia2_stackptr_1");
ia2_init_stackptr = *res;
return *res;
}

void ia2_init_libxul(void) {
void *handle = dlopen("libxul.so", RTLD_NOW | RTLD_GLOBAL);
if (!handle) {
printf("ia2_init_libxul: %s\n", dlerror());
}
assert(handle);
}

#if 1
/* Stores the stack pointer to return to after main() is called. */
static void *main_sp __attribute__((used)) = 0;

/* XXX: Assumes main compartment has pkey 1. */
/* clang-format off */
int __wrap_main(int argc, char **argv);
__asm__(
".global __wrap_main\n"
"__wrap_main:\n"
#if defined(__x86_64__)
"pushq %rbp\n"
"movq %rsp, %rbp\n"

"push %rdx\n"
"push %rdi\n"
"push %rsi\n"
"push %rcx\n"
"call ia2_init_libxul\n"
"pop %rcx\n"
"pop %rsi\n"
"pop %rdi\n"
"pop %rdx\n"

// Switch pkey to the appropriate compartment.
"xor %ecx,%ecx\n"
"mov %ecx,%edx\n"
"mov_pkru_eax 1\n"
"wrpkru\n"
// Save the old stack pointer in main_sp.
"movq %rsp, main_sp(%rip)\n"

"push %rdx\n"
"push %rdi\n"
"push %rsi\n"
"push %rcx\n"
"call ia2_get_stackptr_1\n"
"pop %rcx\n"
"pop %rsi\n"
"pop %rdi\n"
"pop %rdx\n"
"movq %rax, %rsp\n"

// Load the stack pointer for this compartment's stack.
// "mov ia2_stackptr_1@GOTTPOFF(%rip), %r11\n"
// "mov %fs:(%r11), %rsp\n"

// Align the stack before calling main.
"subq $8, %rsp\n"
// Call the real main function.
"call __real_main\n"
// Restore the old stack pointer before returning.
"mov main_sp(%rip), %rsp\n"
// Save return value
"mov %rax,%r10\n"
// Switch pkey to untrusted compartment
"xor %ecx,%ecx\n"
"xor %edx,%edx\n"
"mov_pkru_eax 0\n"
"wrpkru\n"
// Restore return value
"mov %r10,%rax\n"
"popq %rbp\n"
"ret\n"
#elif defined(__aarch64__)
// prologue
"stp x29, x30, [sp, #-16]!\n"
"mov x29, sp\n"

// Save old stack pointer in main_sp
"adrp x9, main_sp\n"
"add x9, x9, #:lo12:main_sp\n"
// Tag x9 with compartment 1
"orr x9, x9, #0x100000000000000\n"

"str x29, [x9]\n"

// Load the new stack pointer
// Since this accesses a TLS in the same DSO it's simpler than the TLS reference in ia2_internal.h
"mrs x9, tpidr_el0\n"
"add x9, x9, #:tprel_hi12:ia2_stackptr_1\n"
"add x9, x9, #:tprel_lo12_nc:ia2_stackptr_1\n"

// Tag x9 with compartment 1
"orr x9, x9, #0x100000000000000\n"

"ldr x9, [x9]\n"
"mov sp, x9\n"

// Set x18 tag to 1
"movz_shifted_tag_x18 1\n"

// Call the real main function
"bl __real_main\n"

// Set x18 tag to 0
"movz_shifted_tag_x18 0\n"

// Restore the old stack pointer
"adrp x9, main_sp\n"
"add x9, x9, #:lo12:main_sp\n"

// Tag x9 with compartment 1
"orr x9, x9, #0x100000000000000\n"

"ldr x9, [x9]\n"
"mov sp, x9\n"

"ldp x29, x30, [sp], #16\n"
"ret"
#endif
);

__attribute((tls_model("initial-exec"))) __attribute__((__unused__)) __attribute__((visibility ("default"))) extern __thread void *ia2_stackptr_1;
#endif
}


#include "nsXULAppAPI.h"
#include "mozilla/XREAppData.h"
#include "XREChildData.h"
Expand Down
4 changes: 4 additions & 0 deletions browser/app/version.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
global:
ia2_stackptr_0;
};
6 changes: 3 additions & 3 deletions build/moz.configure/flags.configure
Original file line number Diff line number Diff line change
Expand Up @@ -385,9 +385,9 @@ def add_gnu_specific_dso_flags(
# linked against executables, so we must allow undefined
# symbols for shared objects in some cases.
if not use_sanitizer_runtime:
if target.os != "WINNT":
# Don't allow undefined symbols in libraries
ldopts.append("-Wl,-z,defs")
# if target.os != "WINNT":
# # Don't allow undefined symbols in libraries
# ldopts.append("-Wl,-z,defs")

# BSDs need `environ' exposed for posix_spawn (bug 753046)
if target.os in ("DragonFly", "FreeBSD", "NetBSD", "OpenBSD"):
Expand Down
14 changes: 7 additions & 7 deletions build/moz.configure/memory.configure
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ option(
)


set_config("MOZ_MEMORY", True, when="--enable-jemalloc")
set_define("MOZ_MEMORY", True, when="--enable-jemalloc")
# set_config("MOZ_MEMORY", True, when="--enable-jemalloc")
# set_define("MOZ_MEMORY", True, when="--enable-jemalloc")


@depends("--enable-jemalloc", moz_debug, win32_redist_dir)
Expand Down Expand Up @@ -104,14 +104,14 @@ option(
"Also enables frame pointers when needed",
)

set_config("MOZ_PHC", True, when="--enable-phc")
# set_config("MOZ_PHC", True, when="--enable-phc")


# PHC parses stacks using frame pointers on these systems.
# # PHC parses stacks using frame pointers on these systems.
@depends("--enable-phc", target, have_unwind, when="--enable-jemalloc")
def phc_implies_frame_pointers(phc, target, have_unwind):
if not phc:
return False
# if not phc:
return False

# This should be kept in sync with the ifdefs in memory/build/PHC.cpp
# that control stack walking.
Expand All @@ -123,7 +123,7 @@ def phc_implies_frame_pointers(phc, target, have_unwind):
if (target.cpu in ("x86", "ppc")) and (target.kernel in ("Darwin", "Linux")):
return not have_unwind

return False
# return False


imply_option("--enable-frame-pointers", True, when=phc_implies_frame_pointers)
Expand Down
37 changes: 37 additions & 0 deletions cpsysroot.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Hacky script to setup the .mozbuild sysroot to use versions of libc and
# related libraries that are needed by libpartition-alloc.so.
#
# Firefox's build process downloads a custom sysroot rather than using the
# system version of the necessary libraries. When building partition-alloc, it
# links against the system version of these libraries, which are newer than the
# ones present in the .mozbuild sysroot. This causes issues when we try to link
# PA into Firefox, as the libraries in .mozbuild are too old and do not have all
# of the symbols PA needs.
#
# To work around this, we copy the necessary system libraries into .mozbuild,
# backing up the original one for debugging purposes. This is hardcoded to
# assume .mozbuild is in the current user's home directory, and uses the system
# library paths on donna (Ubuntu 24.04).

# Check if ~/.mozbuild exists
if [ ! -d ~/.mozbuild ]; then
echo "Error: ~/.mozbuild directory does not exist"
exit 1
fi

# Create backup if it doesn't exist
if [ ! -d ~/.mozbuild.orig ]; then
echo "Creating backup: copying ~/.mozbuild to ~/.mozbuild.orig"
cp -r ~/.mozbuild ~/.mozbuild.orig
fi

cd ~/.mozbuild/sysroot-x86_64-linux-gnu

# Copy the shared objects needed by partition-alloc.
cp /lib/x86_64-linux-gnu/libc.so.6 lib/x86_64-linux-gnu/libc-2.19.so
cp /lib/x86_64-linux-gnu/libstdc++.so.6 usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
cp /lib/x86_64-linux-gnu/libm.so.6 lib/x86_64-linux-gnu/libm-2.19.so
cp /lib/x86_64-linux-gnu/libdl.so.2 lib/x86_64-linux-gnu/libdl-2.19.so
cp /lib/x86_64-linux-gnu/libpthread.so.0 lib/x86_64-linux-gnu/libpthread-2.19.so
cp /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 lib/x86_64-linux-gnu/ld-2.19.so
cp /lib/x86_64-linux-gnu/librt.so.1 lib/x86_64-linux-gnu/librt-2.19.so
6 changes: 5 additions & 1 deletion dom/bindings/BindingUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4265,7 +4265,11 @@ JS::Handle<JSObject*> GetPerInterfaceObjectHandle(
const JS::Heap<JSObject*>& entrySlot =
protoAndIfaceCache.EntrySlotMustExist(aSlotId);
JS::AssertObjectIsNotGray(entrySlot);
return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.unsafeAddress());
auto address = entrySlot.unsafeAddress();
int hasEntry = protoAndIfaceCache.HasEntryInSlot(aSlotId);
// printf("GetPerInterfaceObjectHandle: Unsafe address: %p, has slot: %d\n", address, hasEntry);
auto handle = JS::Handle<JSObject*>::fromMarkedLocation(address);
return handle;
}

namespace binding_detail {
Expand Down
5 changes: 3 additions & 2 deletions dom/workers/MessageEventRunnable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ bool MessageEventRunnable::WorkerRun(JSContext* aCx,
MOZ_ASSERT(aWorkerPrivate->GlobalScope());

// If the worker start shutting down, don't dispatch the message event.
if (NS_FAILED(
aWorkerPrivate->GlobalScope()->CheckCurrentGlobalCorrectness())) {
auto *scope = aWorkerPrivate->GlobalScope();
auto result = scope->CheckCurrentGlobalCorrectness();
if (NS_FAILED(result)) {
return true;
}

Expand Down
Binary file added exploit.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 10 additions & 1 deletion gfx/thebes/gfxFcPlatformFontList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ using namespace mozilla::intl;
#define LOG_CMAPDATA_ENABLED() \
MOZ_LOG_TEST(gfxPlatform::GetLog(eGfxLog_cmapdata), LogLevel::Debug)

extern "C" {
__attribute__((visibility("default"), noinline))
void __real_free(void*);
}

static const FcChar8* ToFcChar8Ptr(const char* aStr) {
return reinterpret_cast<const FcChar8*>(aStr);
}
Expand Down Expand Up @@ -1828,7 +1833,11 @@ void gfxFcPlatformFontList::InitSharedFontListForPlatform() {

char* s = (char*)FcNameUnparse(aPattern);
nsAutoCString descriptor(s);
free(s);
// IA2 HACK: libfontconfig uses malloc and we can't shim it directly since
// it's a system library and is not built as part of the ff build process,
// so we need to deallocate through the real free instead of the partition-alloc
// free shim.
__real_free(s);

if (fcCharsetParseBug) {
// Escape any leading space in charset to work around FcNameParse bug.
Expand Down
Loading