5.3 Reading and writing a file's security descriptor

A file's SD can be accessed by path or by fd. In both cases secinfo is a mask of KACS_SECINFO_* bits selecting which components (owner, group, DACL, SACL, …) the operation touches — you read or write just the parts you name and leave the rest alone.

The rights required scale with the components you touch (see Managing file security):

Component (KACS_SECINFO_*)Reading needsWriting needs
OWNER / GROUPREAD_CONTROLWRITE_OWNER (plus owner-SID validation)
DACLREAD_CONTROLWRITE_DAC
SACLACCESS_SYSTEM_SECURITYACCESS_SYSTEM_SECURITY
LABELREAD_CONTROLWRITE_OWNER (the label cannot rise above the caller's integrity without SeRelabelPrivilege)

ACCESS_SYSTEM_SECURITY is itself gated by SeSecurityPrivilege; READ_CONTROL and WRITE_DAC are implicitly granted to the owner. SACL and LABEL cannot be combined in one call (EINVAL). The check is all-or-nothing: if any requested component fails its check, the whole call fails.

5.3.0.1 By path #

ssize_t peios_file_get_sd(int dirfd, const char *path, uint32_t secinfo,
                          void *buf, size_t cap, uint32_t at_flags);
int     peios_file_set_sd(int dirfd, const char *path, uint32_t secinfo,
                          const void *sd, size_t len, uint32_t at_flags);
  • peios_file_get_sd reads the secinfo-selected components of path's SD into buf, getxattr-style (two-call protocol — probe with cap == 0, and a too-small non-zero buffer fails ERANGE without truncating). at_flags accepts AT_SYMLINK_NOFOLLOW. Errors: EACCES (component right missing), EINVAL (SACL + LABEL together; NULL path, or NULL buffer with non-zero cap), ERANGE (non-probe buffer too small), ENOENT (path doesn't exist), ELOOP (no-follow and symlink).
  • peios_file_set_sd writes the secinfo components of sd onto path, preserving the components you did not select. So to change only the DACL, build an SD with a DACL, pass secinfo = KACS_SECINFO_DACL, and the owner/group/SACL are untouched. Errors: EACCES (component right missing), EPERM (owner-SID validation failed without SeRestorePrivilege; label raised without SeRelabelPrivilege; MANDATORY attribute removed without SeTcbPrivilege), EINVAL (malformed SD, SACL + LABEL together, NULL or zero-length sd), ENOENT, ELOOP.

5.3.0.2 By fd #

ssize_t peios_fd_get_sd(int fd, uint32_t secinfo, void *buf, size_t cap);
int     peios_fd_set_sd(int fd, uint32_t secinfo, const void *sd, size_t len);

The same operations against the object fd already refers to. The access check they perform depends on the fd type: a normal file fd is checked against its cached granted mask (the one baked in at open), while an O_PATH, pidfd, or token fd triggers a live check. That distinction — cached for the fixed-grant file fd, live for the others — is documented in the Peios Kernel TRM §3.9, FACS; the practical upshot is that a file fd already opened with the right access can get/set its SD without a second path resolution.

The required rights and errors match the by-path calls, minus the path-resolution failures (ENOENT/ELOOP), plus EBADF (bad fd).

Edit this page