| # IOBuffer | |
| ## Name | |
| IOBuffer - Shared memory endpoint with asymmetric access control and disciplines | |
| ## Synopsis | |
| An `IOBuffer` (IOB) is a peered Zircon kernel object designed for | |
| high-throughput, low-latency communication and shared memory transports between | |
| processes. It combines peered session management with multi-region | |
| encapsulation, asymmetric access control, and kernel-mediated access | |
| disciplines. | |
| ## Description | |
| An `IOBuffer` always operates as a pair of endpoints (Endpoint 0 and Endpoint | |
| 1). It allows two processes to communicate by sharing multiple independent | |
| memory regions (up to a maximum of 64, defined by `ZX_IOB_MAX_REGIONS`), each | |
| configured with specific access permissions and behavior. | |
| ### Peered lifetime and signaling | |
| Like Channels and Sockets, `IOBuffer` endpoints are peered. | |
| - The endpoints control the lifetime of the backing memory regions. | |
| - **Reference Tracking**: Active virtual memory mappings created from an | |
| endpoint count as references alongside open handles to that endpoint. | |
| - **Peer Closure**: When all references (both open handles and active virtual | |
| memory mappings) to one endpoint close, the system asserts the | |
| `ZX_IOB_PEER_CLOSED` signal on the opposing endpoint. | |
| ### Regions: Private vs. shared | |
| An `IOBuffer` can encapsulate multiple memory regions: | |
| - **Private Regions (`ZX_IOB_REGION_TYPE_PRIVATE`)**: Backed by a private | |
| `VmObject` uniquely owned by the `IOBuffer` pair. Used for isolated, | |
| point-to-point communication. | |
| - **Shared Regions (`ZX_IOB_REGION_TYPE_SHARED`)** *(Experimental)*: Points to a | |
| standalone `shared_region` object. Multiple independent `IOBuffer` pairs can | |
| reference the same shared region, enabling many-to-one patterns (for example, | |
| multiple client log writers sending data to a single reader). | |
| ### Asymmetric access control | |
| You can configure each region with different permissions for Endpoint 0 and | |
| Endpoint 1. Permissions include: | |
| - **Direct Mapping**: Allows the process to map the region into its virtual | |
| address space (VMAR) for direct read/write access. | |
| - `ZX_IOB_ACCESS_EP0_CAN_MAP_READ` / `_WRITE` | |
| - `ZX_IOB_ACCESS_EP1_CAN_MAP_READ` / `_WRITE` | |
| - **Kernel-Mediated Access**: Restricts direct mapping, requiring all access to | |
| go through kernel system calls (such as `zx_iob_writev`). This protects | |
| against Time-of-Check to Time-of-Use (TOCTOU) attacks. | |
| - `ZX_IOB_ACCESS_EP0_CAN_MEDIATED_READ` / `_WRITE` | |
| - `ZX_IOB_ACCESS_EP1_CAN_MEDIATED_READ` / `_WRITE` | |
| #### Effective rights and handle interaction | |
| When validating a memory operation, the kernel intersects the region's access | |
| permissions (logical AND) with the endpoint handle rights. Region-level | |
| permissions cannot override handle-level permissions. | |
| - **Map Operation**: The effective read/write rights are `uRn & hRn` and `uWn & | |
| hWn` respectively, where `u` represents mapping permission and `h` represents | |
| handle rights. | |
| - **Mediated Operation**: The effective read/write rights are `kRn & hRn` and | |
| `kWn & hWn` respectively, where `k` represents mediated permission and `h` | |
| represents handle rights. | |
| #### Mediated directionality vs. absolute permissions | |
| Unlike direct mappings, kernel-mediated access operates in a logical/directional | |
| sense rather than absolute hardware permissions. For example, a logical mediated | |
| read operation (such as retrieving data from a ring buffer) may require the | |
| kernel to write to bookkeeping structures in that same region under the hood. | |
| The kernel permits such internal bookkeeping writes for read-only mediated | |
| endpoints, because the kernel acts as the trusted mediator enforcing the logic. | |
| ### Memory access disciplines | |
| Disciplines define the structured memory layout and behavior for | |
| kernel-mediated operations within a region: | |
| - **None (`ZX_IOB_DISCIPLINE_TYPE_NONE`)**: Free-form raw byte buffer. No | |
| kernel-mediated operations. | |
| - **ID Allocator (`ZX_IOB_DISCIPLINE_TYPE_ID_ALLOCATOR`)** *(Experimental)*: A | |
| thread-safe structure mapping sized data blobs to sequentially allocated | |
| numeric IDs. Useful for string interning in tracing. | |
| - **Mediated Write Ring Buffer | |
| (`ZX_IOB_DISCIPLINE_TYPE_MEDIATED_WRITE_RING_BUFFER`)** *(Experimental)*: A | |
| circular ring buffer designed for concurrent, kernel-mediated writes by | |
| multiple clients and a single userspace reader (for example, high-efficiency | |
| system logging). | |
| ### Mapping via VMAR | |
| The system maps IOBuffer regions into a VMAR via `zx_vmar_map_iob`. Only the | |
| following VMAR options are supported: | |
| - `ZX_VM_SPECIFIC` | |
| - `ZX_VM_SPECIFIC_OVERWRITE` | |
| - `ZX_VM_OFFSET_IS_UPPER_LIMIT` | |
| - `ZX_VM_PERM_READ` | |
| - `ZX_VM_PERM_WRITE` | |
| - `ZX_VM_MAP_RANGE` | |
| Any other VMAR options return `ZX_ERR_INVALID_ARGS`. | |
| ### Querying object properties and regions | |
| IOBuffers support standard property queries via `zx_object_get_info`. | |
| #### `ZX_INFO_IOB` | |
| Returns information about the overall `IOBuffer` instance using `zx_iob_info_t`: | |
| - ``options``: The options used at creation. | |
| - ``region_count``: The number of memory regions encapsulated. | |
| #### `ZX_INFO_IOB_REGIONS` | |
| Returns information about each region as an array of `zx_iob_region_info_t`. | |
| - **Access Bit Swapping**: When returned, the kernel swaps the access modifier | |
| bits so that Endpoint 0 access bits reflect the rights of the endpoint handle | |
| executing the query, and Endpoint 1 access bits reflect the peer's rights. | |
| This allows endpoint-agnostic libraries to validate permissions dynamically. | |
| #### `ZX_INFO_PROCESS_VMOS` | |
| The kernel reports the memory objects backing private IOB regions under this | |
| topic like standard VMOs. By default, backing VMOs share the name of the parent | |
| `IOBuffer`. | |
| ## Rights | |
| An `IOBuffer` handle has the following rights by default: | |
| - `ZX_RIGHT_TRANSFER` | |
| - `ZX_RIGHT_DUPLICATE` | |
| - `ZX_RIGHT_WAIT` | |
| - `ZX_RIGHT_INSPECT` | |
| - `ZX_RIGHT_READ` | |
| - `ZX_RIGHT_WRITE` | |
| - `ZX_RIGHT_MAP` | |
| - `ZX_RIGHT_SIGNAL` | |
| - `ZX_RIGHT_SIGNAL_PEER` | |
| - `ZX_RIGHT_GET_PROPERTY` | |
| - `ZX_RIGHT_SET_PROPERTY` | |
| ## Properties | |
| IOBuffers support the following properties: | |
| - `ZX_PROP_NAME`: Used for diagnostics and attributing memory. | |
| ## Signals | |
| The system can set the following signals for an `IOBuffer` endpoint: | |
| - **ZX_IOB_PEER_CLOSED**: The peer endpoint closed (including all handles and | |
| active mappings). | |
| - **ZX_IOB_SHARED_REGION_UPDATED** *(Experimental)*: Raised when a shared region | |
| has been updated by a mediated write. | |
| ## Syscalls | |
| - [`zx_iob_create()`] - create a new peered IOBuffer pair | |
| - [`zx_iob_create_shared_region()`] *(Experimental)* - create a standalone | |
| shared region | |
| - [`zx_iob_writev()`] - perform a kernel-mediated write to a region | |
| - [`zx_iob_allocate_id()`] *(Experimental)* - allocate an ID in an ID Allocator | |
| region | |
| - [`zx_vmar_map_iob()`] - map an IOBuffer region into a VMAR | |
| [`zx_iob_create()`]: /reference/syscalls/iob_create.md | |
| [`zx_iob_create_shared_region()`]: /reference/syscalls/iob_create_shared_region.md | |
| [`zx_iob_writev()`]: /reference/syscalls/iob_writev.md | |
| [`zx_iob_allocate_id()`]: /reference/syscalls/iob_allocate_id.md | |
| [`zx_vmar_map_iob()`]: /reference/syscalls/vmar_map_iob.md |