Security/Tainting IPC Data

From MozillaWiki
Jump to: navigation, search

Goals

The goal is to enable IPC methods to opt-in to being 'tainted', meaning their resulting Recv call will be provided Tainted<T> types instead of the original T types. The Tainted<> types will require explicit validation of the data before it can be used for comparisons or in arithmetic. They are intended to be passed down callstacks (still in Tainted<> form) to whatever location is appropriate to validate (or complete validation) of the data before finally unwrapping it into a T. We will iterate on the ergonomics of validation and unwrapping.

The purpose is to ensure that validation on data actually occurs and is not forgotten, to increase consideration of validation so it can be as strict as possible, and to make it clear from a code point of view where and what validation is performed on IPC parameters. The latter in particular will aid in code review, and can be used with static/dynamic analysis tools.

How it works

Tainting is automatically applied by annotating a method in the parent process with a "taint" keyword. Example:

    async VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
                        double aIntensity, double aDuration, uint32_t aPromiseID) tainted;

Note how the resulting Recv function that implements this IPDL function in the parent process will have a signature with Tainted types:

mozilla::ipc::IPCResult GamepadEventChannelParent::RecvVibrateHaptic(
    const Tainted<uint32_t>& aControllerIdx,
    const Tainted<uint32_t>& aHapticIndex, const Tainted<double>& aIntensity,
    const Tainted<double>& aDuration, const Tainted<uint32_t>& aPromiseID) {
  // TODO: Bug 680289, implement for standard gamepads

  if (SendReplyGamepadPromise(MOZ_VALIDATE_AND_GET(aPromiseID, isValidPromiseID(aPromiseID)))) {
    return IPC_OK();
  }

Removing Taint by Validation

While still experimental, we have envisioned a couple of macros that help unwrapping the tainted types.

MOZ_VALIDATE_AND_GET(aValue, condition, assertionText)

First and foremost, folks should use MOZ_VALIDATE_AND_GET(). As you can see in the code sample above, the macro unwraps a Taint<T> and returns a T. The second parameter of the macro should receive an boolean expression that ensures the value is within expected boundaries. The value will only be unwrapped when the condition is true. If it is not, we will raise a MOZ_RELEASE_ASSERT. The assertion text is optional. If an assertion is not desirable, see below.

MOZ_VALIDATE_OR(aValue, condition, defaultValue)

The MOZ_VALIDATE_OR behaves similar to the above, but returns a default value instead of raising an assert.

MOZ_NO_VALIDATE(aValue, "justification")

This is an escape hatch that allows unwrapping things from taint without any further checks. The justification string needs to be supplied to give an explanation.

Meta

  • Folks involved: Security Infrastructure Team under Chris Kerschbaumer (Tom Ritter, June Wilde, Frederik Braun)
  • Meta Bug