Skip to content

Replace NativeBufferFactory with a more secure implementation #3062

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
kewde opened this issue Mar 26, 2025 · 2 comments
Open

Replace NativeBufferFactory with a more secure implementation #3062

kewde opened this issue Mar 26, 2025 · 2 comments
Labels
enhancement New feature or request

Comments

@kewde
Copy link
Contributor

kewde commented Mar 26, 2025

Description

Skia.NativeBuffer is badly designed.

The MakeFromImage function sadly returns pointers as BigInts.

JSI_HOST_FUNCTION(MakeFromImage) {
auto image = JsiSkImage::fromValue(runtime, arguments[0]);
image->makeNonTextureImage();
uint64_t pointer = getContext()->makeNativeBuffer(image);
return jsi::BigInt::fromUint64(runtime, pointer);
}

The Release function accepts a BigInt argument, which is expected to be the pointer for which the memory should be freed. It should've encapsulated the pointers and restricted this with a check to ensure the value can't be tampered with from JavaScript side.

JSI_HOST_FUNCTION(Release) {
jsi::BigInt pointer = arguments[0].asBigInt(runtime);
const uintptr_t nativeBufferPointer = pointer.asUint64(runtime);
getContext()->releaseNativeBuffer(nativeBufferPointer);
return jsi::Value::undefined();
}

Ideally, the JavaScript side does not get an arbitrary way to free any hardware pointers beyond the ones it's explicitly been granted.

@kewde kewde added the enhancement New feature or request label Mar 26, 2025
@kewde
Copy link
Contributor Author

kewde commented Apr 7, 2025

The recent blogpost by Google Project Zero [1] is a good example of how a simple CFRelease can be useful exploit primitive.

The gist of the attack is to rely on destructors of other Core Foundation classes to gain code execution, in the blogpost above the describe a way to create a fake malicious CFReadStream, if CFRelease is called onto these fake objects, their destructors get called and suddenly the attacker owns the control flow of the application.

In essence, this API can be abused to allocate a native buffer and we get its pointer to this memory. We fill that memory with our own fake CFReadStream, then call to release it and from there on out we control what gets executed. The memory we allocate likely isn't executable so, and there are a lot of hoops to jump through but I have a hunch that it is a viable exploitation path.

[1] https://googleprojectzero.blogspot.com/2025/03/blasting-past-webp.html

@wcandillon
Copy link
Contributor

wcandillon commented Apr 7, 2025 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants