Skip to content

Displaying Capabilities

Robert Norton edited this page Sep 16, 2021 · 9 revisions

When CHERI capabilities are used in pointers in C, it is helpful for developers to provide a human-friendly format for properties of pointers beyond the address such as bounds and permissions. This document defines a few different formats for displaying capabilities as well as contexts for displaying them.

Capability Display Formats

Different contexts may use different formats.

Raw Format

The simplest format for displaying a capability is to display the raw contents of the capability as a hexadecimal value. This may or may not include the tag (TBD?).

An example use of this format is p/x of a capability in CHERI GDB.

Format:

<capability>

Fields:

  • capability: Hex value of capability bytes.

Basic Format

Another simple format for displaying a capability is to display the address of a capability as a hexadecimal value. This should generally match the existing format used with integer pointers.

An example use of this format is the printf(3) %p format when used in pure-capability CHERI C.

Format:

<address>

Fields:

  • address: Virtual address of capability.

Simplified Format

Initially, CHERI projects used a verbose format which displayed all possible fields of capabilities as separate hex values. However, this format had a couple of disadvantages. First, it was quite broad (over 80 characters for a single pointer). Secondly, it still required manual decoding of fields such as permission bits and object types. The simplified format aims to provide a more concise format which provides details that are generally applicable to most developers using CHERI C such as basic permissions. It does omit some details such as more obscure permissions and most object types. In addition, for null-derived capabilities (capabilities where the tag and upper attribute word are all zero), only the address is displayed (the Basic Format).

An example use of this format is the printf(3) %#p format when used in pure-capability CHERI C.

Format:

<address> [<permissions>,<base>-<top>] (<attr>)
  • address: Virtual address of capability displayed as a hexadecimal value with a 0x prefix.
  • permissions: Zero or more of the following characters:
    • r: LOAD permission
    • w: STORE permission
    • x: EXECUTE permission
    • R: LOAD_CAP permission
    • W: STORE_CAP permission
    • E: EXECUTIVE permission (Morello only)
      • Could be X instead so we have rwxRWX, though we may want X for ASR instead
  • base: Lower bound of capability displayed as a hexadecimal value with a 0x prefix.
  • top: Upper bound of capability plus 1 displayed as a hexadecimal value with a 0x prefix.
  • attr: Zero or more of the following comma-separated attributes. If none of the attributes are present, this field is omitted (along with the enclosing parentheses/brackets).
    • invalid: Capability's tag is clear.
    • sentry: Capability is a sealed entry.
    • sealed: Capability is sealed with a type other than the sealed entry object type.

Verbose Format

In some cases, all of the details of a capability may be desired (for example, when working with code that uses sealed capabilities). For these cases, a verbose (but readable) format should be defined. Ideally such a format would retain human-friendly display of fields such as permissions when possible while providing details of all of the fields of a capability.

Ideally, displaying capabilities in this format would be provided in debuggers.

Format:

TBD

printf(3) formats

Both pure-capability and hybrid CHERI C implementations should permit the display of capabilities via printf(3) via the p format specifier.

By default, the p specifier should print the address of the capability (the Basic Format) matching the format used for integer pointers in plain C for the given platform. Different environments display pointers differently (for example BSD kernels and C libraries display integer pointers as hexadecimal values with a 0x prefix, whereas the Linux kernel displays integer pointers as hexadecimal without a 0x prefix), and p should match a platform's existing format.

In addition, the following additional format specifiers are defined in CHERI C:

  • The l modifier can be used with the p specifier to indicate that the argument is a void * __capability rather than a void *.

    For hybrid CHERI C, p accepts integer pointer arguments by default (void *). This modifier allows a capability to be passed instead. To ease portability between hybrid and pure-capability CHERI C, pure-capability CHERI C also accepts (but ignores) this modifier. In pure-capability CHERI C, void * is already a capability.

  • The # modifier can be used with the p specifier to request that a capability be displayed using the Simplified Format.

    To ease portability, this modifier is ignored if it is used with an integer pointer in hybrid CHERI C.

  • An optional precision can be used with the p specifier.

    If given, the precision is used to determine the width of addresses (address, base, and top) displayed in the Simplified Format. Each address should be zero-padded if necessary to meet the desired precision. Note that the precision applies to the hexadecimal digits displayed for each address and does not include the 0x prefix.

If a field width is provided for the p specifier, that field width should be applied to the result of the entire output string generated by the Simplified Format when used with the # modifier.

Samples

Open Questions

  1. E vs X permission (see above)
  2. Should absent permissions be denoted by a - similar to ls -l output? When used with precision, this would provide a fixed-width format which is nice for dumping tables of registers.
  3. Other permissions? ASR could be useful and is likely to stick around. S and U are useful but in an otype-less world with just sentries those would no longer be needed.
  • ASR may make sense as X: just as LOAD_CAP gates access to specific types of loads, ASR gates access to specific types of instructions.
  • We may also want to show flags (e.g. cap mode for risc-v)