On this page
- Forward-compatibility model
- kacs_access_check_args
- kacs_open_how
- kacs_mount_policy_args
- kacs_query_args
- kacs_adjust_privs_args
- kacs_priv_entry
- kacs_adjust_groups_args
- kacs_group_entry
- kacs_adjust_default_args
- kacs_duplicate_args
- kacs_restrict_args
- kacs_link_tokens_args
- kacs_get_linked_token_args
- kacs_node_result
- kacs_object_type_entry
- Forward-compat detail
Structs and forward-compat
The KACS syscalls and ioctls pass parameter structs across the kernel boundary. Each struct has a fixed layout — field offsets, sizes, types. Some are size-versioned: the struct carries a size field at offset 0, and the kernel reads only up to whatever size the caller declares. This page catalogues the structs and the size-versioning rules.
For wire-format payloads (token wire format, session wire format, SD self-relative layout, conditional ACE bytecode, CAAP wire format), see Wire formats reference. The structs here are syscall parameter records; the wire formats there are payloads pointed to by struct fields.
All numeric fields are little-endian on x86_64.
Forward-compatibility model
Several structs are versioned by size at the wire level. The pattern:
- The first field of the struct is the size (in bytes) the caller is using.
- The kernel reads
min(declared_size, kernel_known_size)bytes. - Fields beyond the kernel's known size must be zero (otherwise
-EINVAL). - New struct versions append fields at the end. Older callers don't write the new fields; their
sizedeclares the smaller layout; the kernel uses defaults for the unknown fields.
This pattern lets userspace built for an older kernel work against a newer one (new fields default), and lets userspace built for a newer kernel fail gracefully on an older one (it would set fields beyond the old kernel's known size, which the old kernel doesn't accept unless they're zero).
Three structs use this pattern in v0.20:
| Struct | Field controlling version | Minimum size (v1) |
|---|---|---|
kacs_access_check_args |
size at offset 0 |
40 bytes (KACS_ACCESS_CHECK_ARGS_V1_SIZE) |
kacs_open_how |
howsize parameter (separate from struct) |
16 bytes (through flags field) |
kacs_mount_policy_args |
argsize parameter |
16 bytes |
The other structs documented here are fixed-size in v0.20. Future versions may convert them to the size-versioned pattern if extension is needed.
kacs_access_check_args
Used by kacs_access_check and kacs_access_check_list.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | size |
Size of this struct as known to the caller. |
| 4 | 4 | token_fd |
The calling token. |
| 8 | 8 | sd_ptr |
Userspace pointer to the SD blob. |
| 16 | 4 | sd_len |
Length of the SD blob. |
| 20 | 4 | desired_access |
Requested access mask. |
| 24 | 4 | generic_read |
GenericMapping: READ → object-specific bits. |
| 28 | 4 | generic_write |
GenericMapping: WRITE → object-specific bits. |
| 32 | 4 | generic_execute |
GenericMapping: EXECUTE → object-specific bits. |
| 36 | 4 | generic_all |
GenericMapping: ALL → object-specific bits. |
| 40 | 8 | self_sid_ptr |
Pointer to self_sid (for PRINCIPAL_SELF ACE resolution); may be NULL. |
| 48 | 4 | self_sid_len |
Length of self_sid in bytes; 0 if NULL. |
| 52 | 4 | privilege_intent |
Flags: BACKUP_INTENT (0x01), RESTORE_INTENT (0x02). |
| 56 | 8 | object_tree_ptr |
For kacs_access_check_list: pointer to flat array of kacs_object_type_entry. NULL for simple check. |
| 64 | 4 | object_tree_count |
Number of entries in object_tree. |
| 68 | 4 | pip_type |
The calling process's PSB pip_type (caller supplies; kernel doesn't read it itself). |
| 72 | 4 | pip_trust |
Calling process's pip_trust. |
| 76 | 4 | _pad | Reserved; must be zero. |
| 80 | 8 | local_claims_ptr |
Pointer to local-claims buffer (multi-entry KACS claim format). NULL if no @Local claims. |
| 88 | 4 | local_claims_len |
Length. |
| 92 | 4 | granted_out |
Output: the granted access mask. |
| 96 | 8 | granted_out_ptr |
(For per-node variant) Reserved; pass NULL for single-result calls. |
| 104 | 8 | audit_context_ptr |
Pointer to caller-supplied opaque object identifier for audit events. May be NULL. |
| 112 | 4 | audit_context_len |
Length. |
| 116 | 4 | continuous_audit_out |
Output: the continuous-audit mask to cache on the handle. |
| 120 | 8 | continuous_audit_out_ptr |
(Reserved) |
| 128 | 4 | staging_mismatch_out |
Output: 1 if any CAAP staging mismatch occurred, 0 otherwise. |
| 132 | 4 | _pad | Reserved. |
Total v1 size: 136 bytes. Minimum size the kernel accepts: 40 bytes (KACS_ACCESS_CHECK_ARGS_V1_SIZE). Callers using the minimum size pass NULL for the optional pointer fields and zero for the output fields.
kacs_open_how
Used by kacs_open. The howsize parameter to the syscall controls how much of this struct the kernel reads.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | desired_access |
Requested access mask. |
| 4 | 4 | create_disposition |
KACS_FILE_* constant (0–5). |
| 8 | 4 | create_options |
Flags: KACS_CREATE_OPT_DIRECTORY (0x01), KACS_CREATE_OPT_DELETE_ON_CLOSE (0x02). |
| 12 | 4 | flags |
Path flags: AT_EMPTY_PATH (0x1000), AT_SYMLINK_NOFOLLOW (0x100). |
| 16 | 8 | sd_ptr |
Creator-supplied SD for new files. NULL to inherit from parent. |
| 24 | 4 | sd_len |
Length of SD blob. |
| 28 | 4 | _pad | Reserved; must be zero. |
Total v1 size: 32 bytes. Minimum howsize the kernel accepts: 16 bytes (through the flags field). Callers using the minimum cannot supply a creator SD.
kacs_mount_policy_args
Used by kacs_get_mount_policy and kacs_set_mount_policy. The argsize parameter controls how much is read.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | policy |
The policy class constant (KACS_MOUNT_POLICY_*). |
| 4 | 4 | flags |
Reserved; must be zero. |
| 8 | 8 | generation |
Output: current generation counter. |
| 16 | 8 | template_sd_ptr |
Pointer to mount template SD. NULL for none. |
| 24 | 4 | template_sd_len |
Length of template. 0 with NULL means no template. |
| 28 | 4 | _pad | Reserved. |
Total v1 size: 32 bytes. Minimum argsize: 16 bytes. Callers using the minimum cannot read or set the template.
kacs_query_args
Used by KACS_IOC_QUERY.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | token_class |
Numeric query class (1–24). |
| 4 | 4 | buf_len |
Input: buffer size. Output: required size. |
| 8 | 8 | buf_ptr |
Userspace pointer to output buffer. May be 0 for probe. |
Total: 16 bytes. Fixed-size.
kacs_adjust_privs_args
Used by KACS_IOC_ADJUST_PRIVS.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | count |
Number of kacs_priv_entry records. |
| 4 | 4 | _pad | Reserved. |
| 8 | 8 | data_ptr |
Pointer to array of kacs_priv_entry. |
| 16 | 8 | previous_enabled |
Output: previous enabled bitmask. |
Total: 24 bytes.
kacs_priv_entry
Array element (each entry is 8 bytes):
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | luid |
Privilege LUID (bit position 0–63). 0 with KACS_PRIV_RESET_ALL_DEFAULTS attributes is the reset sentinel. |
| 4 | 4 | attributes |
0 (disable), SE_PRIVILEGE_ENABLED (0x02 = enable), SE_PRIVILEGE_REMOVED (0x04 = remove), KACS_PRIV_RESET_ALL_DEFAULTS (0x80000000 = reset). |
kacs_adjust_groups_args
Used by KACS_IOC_ADJUST_GROUPS.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | count |
Number of kacs_group_entry records. |
| 4 | 4 | _pad | Reserved. |
| 8 | 8 | data_ptr |
Pointer to array. |
| 16 | 8 | previous_state |
Output: previous enabled state bitmask. |
Total: 24 bytes.
kacs_group_entry
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | index |
0-based index into the token's groups array. 0xFFFFFFFF is the reset-all sentinel. |
| 4 | 4 | enable |
1 to enable, 0 to disable. |
8 bytes per entry.
kacs_adjust_default_args
Used by KACS_IOC_ADJUST_DEFAULT.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 8 | dacl_ptr |
Three-way: 0 = no change; nonzero with len>0 = replace; nonzero with len=0 = clear. |
| 8 | 4 | dacl_len |
DACL length. |
| 12 | 2 | owner_index |
0xFFFF = no change; otherwise the new owner-SID index. |
| 14 | 2 | group_index |
Same for primary group. |
Total: 16 bytes.
kacs_duplicate_args
Used by KACS_IOC_DUPLICATE.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | access_mask |
Desired access mask for the new fd. |
| 4 | 4 | token_type |
1 = Primary, 2 = Impersonation. |
| 8 | 4 | impersonation_level |
0–3. |
| 12 | 4 | result_fd |
Output: the new fd. |
Total: 16 bytes.
kacs_restrict_args
Used by KACS_IOC_RESTRICT.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 8 | privs_to_delete |
Bitmask of privileges to remove. |
| 8 | 4 | num_deny_indices |
Count of group indices to mark deny-only. |
| 12 | 4 | num_restrict_sids |
Count of restricting SIDs to add. |
| 16 | 4 | data_len |
Total length of the data payload. |
| 20 | 4 | flags |
KACS_RESTRICT_WRITE_RESTRICTED (0x01). |
| 24 | 8 | data_ptr |
Pointer to payload: u32[] deny indices followed by packed binary SIDs. |
| 32 | 4 | result_fd |
Output: the new fd. |
| 36 | 4 | _pad | Reserved. |
Total: 40 bytes.
kacs_link_tokens_args
Used by KACS_IOC_LINK_TOKENS.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | elevated_fd |
Fd of the Full token. |
| 4 | 4 | filtered_fd |
Fd of the Limited token. |
| 8 | 8 | session_id |
Session LUID both tokens reference. |
Total: 16 bytes.
kacs_get_linked_token_args
Used by KACS_IOC_GET_LINKED_TOKEN.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | result_fd |
Output: partner's fd. |
Total: 4 bytes.
kacs_node_result
Output array element for kacs_access_check_list.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | granted |
The granted mask for this node. |
| 4 | 4 | status |
0 = granted, -EACCES = denied. |
8 bytes per entry. Caller passes an array of these to receive per-node results.
kacs_object_type_entry
Input array element for object type lists.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 2 | level |
Tree depth (0 = root). |
| 2 | 2 | _reserved | Must be zero. |
| 4 | 16 | guid |
Property GUID. |
20 bytes per entry. The array is a preorder flattening of the tree.
Validation: first entry's level must be 0; exactly one level-0 entry; no level gaps; no duplicate GUIDs; all _reserved zero.
Forward-compat detail
For the three size-versioned structs (kacs_access_check_args, kacs_open_how, kacs_mount_policy_args), the rules in detail:
When the caller declares a smaller size than the kernel knows, the kernel reads up to the declared size. Fields the kernel "knows about" beyond the declared size get default values (zero, NULL, or a struct-specific default depending on the field).
When the caller declares a larger size than the kernel knows, the kernel:
- Reads up to its own known size.
- Reads (but does not interpret) the trailing bytes up to the declared size.
- Checks that all trailing bytes are zero. If any non-zero byte is found beyond the kernel's known size, returns
-EINVAL.
This is the "caller using new fields the kernel doesn't know" case. If the caller sets a new field (which would be zero on an older kernel), the older kernel sees non-zero trailing bytes and rejects the call. The userspace program can then notice the rejection and fall back to a compatible code path.
When the caller declares a size smaller than the minimum (e.g., less than 40 for kacs_access_check_args), the call is rejected with -EINVAL. The minimum is what the kernel needs to know to perform the operation at all.
The minimum sizes (KACS_ACCESS_CHECK_ARGS_V1_SIZE = 40; kacs_open_how minimum = 16; kacs_mount_policy_args minimum = 16) are stable; they will not change in future versions. Fields added after the v1 minimum are appended; the offsets of existing fields are stable.