Handling callbacks
Finally, let's sandbox the call to the call_cb
function. To do this, we need
to modify the callback to have a signature that RLBox permits. Currently the
callback looks like this:
void hello_cb(const char* str)
{
release_assert(str != nullptr, "Expected value for string");
printf("hello_cb: %s\n", str);
}
To modify this to a signature RLBox will allow, we need to
- Set the first parameter to be a reference to the sandbox
- Make all parameters and returns a tainted value. (A
void
return does not need to be tainted)
With this change, the callback will now look like
void hello_cb(rlbox_sandbox_mylib& sandbox, tainted_mylib<const char*> str)
This callback is called with a tainted string. To actually use the tainted
string we need to verify it. To do this, we use the string verification function
copy_and_verify_string()
with a simple verifier:
str.copy_and_verify_string([](unique_ptr<char[]> val) {
release_assert(val != nullptr && strlen(val.get()) < 1024, "val is null or greater than 1024\n");
return move(val);
});
This verifier moves the string if it is not null and if its length is less than 1KB. In the callback we simply print this string.
Let's now continue back in main
. To call_cb
with the callback we first
need to register the callback - otherwise RLBox will disallow the
library-application call - and pass the callback to the call_cb
function:
// register callback
auto cb = sandbox.register_callback(hello_cb);
// Call the library function call_cb, passing in the callback hello_cb
sandbox.invoke_sandbox_function(call_cb, cb);
Note that cb
here is an RAII type. Meaning the callback is automatically
unregistered if cb
goes out of scope. If you want the callback to be
registered for longer, make sure to keep cb
alive.