Skip to content

Commit

Permalink
*some sensible commit message*
Browse files Browse the repository at this point in the history
  • Loading branch information
0drai committed Jul 25, 2024
1 parent e533143 commit 661ed0c
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 33 deletions.
7 changes: 7 additions & 0 deletions js/src/builtin/DataViewObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ DataViewObject* DataViewObject::create(
return nullptr;
}

obj->setReservedSlot(TAINT_SLOT, PrivateValue(new TaintFlow()));

if (arrayBuffer && arrayBuffer->isWasm()) {
obj->setTaint(
TaintFlow(TaintOperationFromContext(cx, "WASM Array taint source", true)));
}

return obj;
}

Expand Down
50 changes: 50 additions & 0 deletions js/src/builtin/String.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,55 @@ js::str_tainted(JSContext* cx, unsigned argc, Value* vp)
return true;
}

bool js::str_taintedFromArray(JSContext* cx, unsigned argc, Value* vp)
{
// String.taintedFromArray(string, operation, array, array.taint.length)
CallArgs args = CallArgsFromVp(argc, vp);

RootedString str(cx, ArgToLinearString(cx, args, 0));
if (!str || str->length() == 0) {
return false;
}

RootedString opName(cx, args[1].toString());
if (!opName) {
return false;
}

UniqueChars op_chars = JS_EncodeStringToUTF8(cx, opName);
if (!op_chars) {
return false;
}

TaintFlow op = TaintFlow(TaintOperationFromContext(cx,op_chars.get(), true));
printf("1\n");
TaintFlow arrayTaintFlow = JS::getValueTaint(args[2]);
printf("2\n");
TaintFlow combined = TaintFlow::append(op, arrayTaintFlow);
printf("3\n");

double taintFlowSize = 0;
printf("4\n");

if (!ToInteger(cx, args[3], &taintFlowSize)) {
return false;
}

SafeStringTaint taint(combined, taintFlowSize + 1);

JSString* tainted_str = NewDependentString(cx, str, 0, str->length());
if (!tainted_str) {
return false;
}

tainted_str->setTaint(taint);

MOZ_ASSERT(tainted_str->isTainted());

args.rval().setString(tainted_str);
return true;
}

/*
* TaintFox: taint property implementation.
*
Expand Down Expand Up @@ -4596,6 +4645,7 @@ static const JSFunctionSpec string_static_methods[] = {

// TaintFox: Helper function for manual taint sources.
JS_FN("tainted", str_tainted, 1,0),
JS_FN("taintedFromArray", str_taintedFromArray, 4,0),

JS_FS_END};

Expand Down
2 changes: 2 additions & 0 deletions js/src/builtin/String.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ extern bool str_fromCodePoint_one_arg(JSContext* cx, HandleValue code,
// TaintFox: Exported for the js shell: taint(str).
bool str_tainted(JSContext* cx, unsigned argc, Value* vp);

bool str_taintedFromArray(JSContext* cx, unsigned argc, Value* vp);

extern bool str_includes(JSContext* cx, unsigned argc, Value* vp);

extern bool str_indexOf(JSContext* cx, unsigned argc, Value* vp);
Expand Down
23 changes: 22 additions & 1 deletion js/src/builtin/TypedArray.js
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,10 @@ function TypedArrayJoin(separator) {
R += sep + ToString(element);
}

if (O && O.taint?.length > 0){
AddTaintOperationNative(R, "join", O.taint[0]);
}

// Step 9.
return R;
}
Expand Down Expand Up @@ -1039,6 +1043,8 @@ function TypedArraySlice(start, end) {

if (start && start.taint?.length > 0) {
AddTaintOperationToArray(A, "slice", start);
} else if (O && O.taint?.length > 0){
AddTaintOperationToArray(A, "slice", O);
}

// Step 16.
Expand Down Expand Up @@ -1294,12 +1300,23 @@ function TypedArraySubarray(begin, end) {
var beginByteOffset = srcByteOffset + beginIndex * elementSize;

// Steps 15-16.
return TypedArraySpeciesCreateWithBuffer(
var result = TypedArraySpeciesCreateWithBuffer(
obj,
buffer,
beginByteOffset,
newLength
);

if (begin?.taint?.length > 0) {
AddTaintOperationToArray(result, "subarray", begin);
} else if (end?.taint?.length > 0) {
AddTaintOperationToArray(result, "subarray", end);
}
else if (obj?.taint?.length > 0){
AddTaintOperationToArray(result, "subarray", obj);
}

return result;
}

// https://tc39.es/proposal-relative-indexing-method
Expand Down Expand Up @@ -1990,6 +2007,10 @@ function TypedArrayToReversed() {
A[k] = fromValue;
}

if (O?.taint?.length > 0){
AddTaintOperationToArray(A, "reversed", O);
}

// Step 7. Return A.
return A;
}
Expand Down
25 changes: 22 additions & 3 deletions js/src/jsapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include <algorithm>
#include <cstdarg>
#include <cstring>
#ifdef __linux__
# include <dlfcn.h>
#endif
Expand Down Expand Up @@ -4956,11 +4957,27 @@ JS_ReportTaintSink(JSContext* cx, JS::HandleString str, const char* sink, JS::Ha
// Print a message to stdout. Also include the current JS backtrace.
auto& firstRange = *str->taint().begin();

bool hasWasm = false;

// Check if the tainted string is a wasm string
for (TaintRange& range : str->taint()) {
for(TaintNode& node: range.flow()){
const auto *name = node.operation().name();
if (std::strstr(name, "WASM")){
hasWasm = true;
}
}
}

std::cerr << "!!! Tainted flow into " << sink << " from " << firstRange.flow().source().name() << " !!!" << std::endl;
// DumpBacktrace(cx);

// Report a warning to show up on the web console
if (hasWasm) {
JS_ReportWarningUTF8(cx, "WASM Tainted flow from %s into %s!", firstRange.flow().source().name(), sink);
} else {
JS_ReportWarningUTF8(cx, "Tainted flow from %s into %s!", firstRange.flow().source().name(), sink);
}

// Extend the taint flow to include the sink function
str->taint().extend(TaintOperationFromContext(cx, sink, true, arg, true));
Expand All @@ -4976,7 +4993,7 @@ JS_ReportTaintSink(JSContext* cx, JS::HandleString str, const char* sink, JS::Ha
RootedValue slot(cx, JS::GetReservedSlot(global, TAINT_REPORT_FUNCTION_SLOT));
if (slot.isUndefined()) {
// Need to compile.
const char* argnames[3] = {"str", "sink", "stack"};
const char* argnames[4] = {"str", "sink", "stack", "hasWasm"};
const char* funbody =
"if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n"
" var t = window;\n"
Expand All @@ -4995,6 +5012,7 @@ JS_ReportTaintSink(JSContext* cx, JS::HandleString str, const char* sink, JS::Ha
" loc: location.href,\n"
" parentloc: pl,\n"
" referrer: document.referrer,\n"
" hasWasm: hasWasm,\n"
" str: str,\n"
" sink: sink,\n"
" stack: stack\n"
Expand All @@ -5006,7 +5024,7 @@ JS_ReportTaintSink(JSContext* cx, JS::HandleString str, const char* sink, JS::Ha

RootedObjectVector emptyScopeChain(cx);
report = CompileFunctionUtf8(cx, emptyScopeChain,
options, "ReportTaintSink", 3,
options, "ReportTaintSink", 4,
argnames, funbody, strlen(funbody));
MOZ_ASSERT(report);

Expand All @@ -5023,14 +5041,15 @@ JS_ReportTaintSink(JSContext* cx, JS::HandleString str, const char* sink, JS::Ha
return;
}

JS::RootedValueArray<3> arguments(cx);
JS::RootedValueArray<4> arguments(cx);
arguments[0].setString(str);
arguments[1].setString(NewStringCopyZ<CanGC>(cx, sink));
if (stack) {
arguments[2].setObject(*stack);
} else {
arguments[2].setUndefined();
}
arguments[3].setBoolean(hasWasm);

RootedValue rval(cx);
JS_CallFunction(cx, nullptr, report, arguments, &rval);
Expand Down
1 change: 0 additions & 1 deletion js/src/jstaint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,6 @@ const TaintFlow& JS::getValueTaint(const Value& val)
return abvo.taint();
}
} else if (val.isString()) {
printf("isTaintedStr!!!!\n");
for (auto range: val.toString()->Taint()) {
return range.flow();
}
Expand Down
13 changes: 5 additions & 8 deletions js/src/vm/ArrayBufferViewObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,11 @@ bool js::Array_taintGetter(JSContext* cx, unsigned argc, Value* vp) {
}

// TaintFox: taint arrays manually using this method.
bool js::Array_tainted(JSContext* cx, unsigned argc, Value* vp) {
bool js::Array_taintMe(JSContext* cx, unsigned argc, Value* vp) {
MOZ_ASSERT(TypedArrayObject::is(args.thisv()));
CallArgs args = CallArgsFromVp(argc, vp);

RootedObject dataObj(cx, &args[0].toObject());

if (!dataObj->canUnwrapAs<ArrayBufferViewObject>()) {
JS_ReportErrorASCII(
cx, "Array_tainted can only be called on TypedArrayObjects");
return false;
}
RootedObject dataObj(cx, &args.thisv().toObject().as<TypedArrayObject>());

dataObj->as<ArrayBufferViewObject>().setTaint(TaintFlow(
TaintOperationFromContext(cx, "manual array taint source", true)));
Expand Down Expand Up @@ -147,6 +142,7 @@ void ArrayBufferViewObject::notifyBufferDetached() {
setFixedSlot(LENGTH_SLOT, PrivateValue(size_t(0)));
setFixedSlot(BYTEOFFSET_SLOT, PrivateValue(size_t(0)));
setFixedSlot(DATA_SLOT, UndefinedValue());
setReservedSlot(TAINT_SLOT, UndefinedValue());
}

void ArrayBufferViewObject::notifyBufferMoved(uint8_t* srcBufStart,
Expand Down Expand Up @@ -210,6 +206,7 @@ bool ArrayBufferViewObject::init(JSContext* cx,

initFixedSlot(BYTEOFFSET_SLOT, PrivateValue(byteOffset));
initFixedSlot(LENGTH_SLOT, PrivateValue(length));
initReservedSlot(TAINT_SLOT, PrivateValue(new TaintFlow()));
if (buffer) {
initFixedSlot(BUFFER_SLOT, ObjectValue(*buffer));
} else {
Expand Down
2 changes: 1 addition & 1 deletion js/src/vm/ArrayBufferViewObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

namespace js {

bool Array_tainted(JSContext* cx, unsigned argc, Value* vp);
bool Array_taintMe(JSContext* cx, unsigned argc, Value* vp);
bool Array_taintGetter(JSContext* cx, unsigned argc, Value* vp);
/*
* ArrayBufferViewObject
Expand Down
8 changes: 2 additions & 6 deletions js/src/vm/SelfHosting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1864,10 +1864,6 @@ taint_addTaintOperationToArray(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);

if (!isTaintedNumber(args[2])){
return false;
}

RootedObject dataObj(cx, &args[0].toObject());

if (!dataObj || !dataObj->canUnwrapAs<ArrayBufferViewObject>()) {
Expand All @@ -1884,9 +1880,9 @@ taint_addTaintOperationToArray(JSContext* cx, unsigned argc, Value* vp)
return false;
}

TaintFlow numberTaintFlow = getNumberTaint(args[2]);
TaintFlow anyTaintFlow = getValueTaint(args[2]);
TaintFlow sliceTaintFlow = TaintFlow(TaintOperationFromContext(cx,op_chars.get(), true));
TaintFlow combined = TaintFlow::append(numberTaintFlow, sliceTaintFlow);
TaintFlow combined = TaintFlow::append(anyTaintFlow, sliceTaintFlow);

dataObj->as<ArrayBufferViewObject>().setTaint(combined);

Expand Down
3 changes: 2 additions & 1 deletion js/src/vm/TypedArrayObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
if (!obj || !obj->init(cx, buffer, byteOffset, len, BYTES_PER_ELEMENT)) {
return nullptr;
}
obj->setReservedSlot(TAINT_SLOT, PrivateValue(nullptr));
obj->setReservedSlot(TAINT_SLOT, PrivateValue(new TaintFlow()));

if (buffer && buffer->isWasm()) {
obj->setTaint(
Expand Down Expand Up @@ -1859,6 +1859,7 @@ bool TypedArrayObject::copyWithin(JSContext* cx, unsigned argc, Value* vp) {
JS_SELF_HOSTED_FN("subarray", "TypedArraySubarray", 2, 0),
JS_FN("set", TypedArrayObject::set, 1, 0),
JS_FN("copyWithin", TypedArrayObject::copyWithin, 2, 0),
JS_FN("taintMe", js::Array_taintMe, 0,0),
JS_SELF_HOSTED_FN("every", "TypedArrayEvery", 1, 0),
JS_SELF_HOSTED_FN("fill", "TypedArrayFill", 3, 0),
JS_SELF_HOSTED_FN("filter", "TypedArrayFilter", 1, 0),
Expand Down
21 changes: 10 additions & 11 deletions js/src/wasm/WasmInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,16 @@ bool Instance::callImport(JSContext* cx, uint32_t funcImportIndex,
{
JS::AutoAssertNoGC nogc;
for (size_t i = 0; i < argc; i++) {

if (args[i].isNumber()) {
double d = args[i].toNumber();
JSObject* number = NumberObject::createTainted(
cx, d,
TaintFlow(
TaintOperation("WASM Import taint source", {taintarg(cx, d)})));
args[i].setObject(*number);
}

const void* rawArgLoc = &argv[i];
if (argTypes.isSyntheticStackResultPointerArg(i)) {
stackResultPointer = Some(*(char**)rawArgLoc);
Expand Down Expand Up @@ -294,17 +304,6 @@ bool Instance::callImport(JSContext* cx, uint32_t funcImportIndex,
RootedValue thisv(cx, UndefinedValue());
RootedValue rval(cx);

for (size_t i = 0; i < args.length(); i++) {
double d;
if (ToNumber(cx, args[i], &d)) {
JSObject* number = NumberObject::createTainted(
cx, d,
TaintFlow(
TaintOperation("WASM Import taint source", {taintarg(cx, d)})));
args[i].setObject(*number);
}
}

if (!Call(cx, fval, thisv, args, &rval)) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion taint/Taint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,7 @@ StringTaint ParseTaint(const std::string& str)

#if (DEBUG_E2E_TAINTING)
std::cout << "Done parsing taint. Result: " << std::endl;
PrintTaint(taint);
/*PrintTaint(taint);*/
#endif

return taint;
Expand Down

0 comments on commit 661ed0c

Please sign in to comment.