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.