Skip to content

[R7-3] Architectural recommendation: privsep worker pattern — defer adoption (cost/benefit) #412

@mcdope

Description

@mcdope

Cluster

C6 — Hardening & Privilege Separation (de Raadt-led): evaluate whether the current architecture warrants a privsep worker pattern.

Recommendation

Do not adopt the privsep worker pattern at this time. Reassess if the threat surface materially expands.

Cost / benefit analysis

What the pattern would buy

A worker forking from pusb_sm_authenticate, dropping privileges to a synthetic uid before parsing XML and before opening attacker-supplied USB filesystem contents, would isolate the following code paths from the host PAM process's root context:

  • libxml2 XML parsing and XPath evaluation (conf.c, xpath.c).
  • USB-side pad I/O and fsync on attacker-controlled FAT/exFAT volumes (pad.c).
  • getrandom(2) + write-and-rename atomic update (pad.c).

A compromise of any of those subsystems would terminate the worker without lasting effect on the host PAM process.

What the pattern would cost

  • Fork-from-PAM-hook is fragile: glib/UDisks2 client state (udisks_client_new_sync) is initialized in the parent; forking after it is a documented anti-pattern (pthread_atfork warning in glib docs).
  • Re-architecting device.c / volume.c to talk to UDisks2 in the parent while delegating pad I/O to a worker requires either a second IPC channel or marshalling mount points across the boundary.
  • The current binary footprint (~4,200 LOC) does not justify the operational complexity of a worker; the audit floor for medium-or-higher vulns surfaced from the named subsystems over six prior rounds is small.
  • Debug cycles increase substantially — strace -f becomes the only useful introspection tool.

Adoption blockers identified in current code

Should the pattern become warranted later, the following blockers would need to be addressed:

  1. pusb_log_init writes to thread-local globals (src/log.c:26-28); a worker would need its own init call.
  2. udisks_client_new_sync in device.c:123 initializes long-lived glib state; this initialization must remain on one side of the boundary, not straddle a fork.
  3. The PAM stack assumes synchronous return from pam_sm_authenticate; the worker boundary must be fully drained before the hook returns.

Conclusion

The libxml2 + UDisks2 + OTP surface, audited across rounds 1-6, has produced findings that are mostly addressable in-place. A worker model would not have prevented the published findings to date. Recommend leaving the architecture as-is and revisiting if either:

  • A future round surfaces a libxml2 / glib / UDisks2 vulnerability whose only mitigation is privsep, or
  • The codebase grows significantly (e.g., adds support for non-PAM auth flows).

This issue does not receive a CVSS score — it is an architectural opinion, not a vulnerability report.

Metadata

Metadata

Assignees

No one assigned

    Labels

    RFCRequest for commentsenhancementNew feature or requesthelp wantedExtra attention is needed

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions