Skip to content

p11scope v0.1.0

Choose a tag to compare

@mingulov mingulov released this 30 Sep 04:18
· 275 commits to main since this release

p11scope v0.1.0

First public release, 2026-09-30.

p11scope observes the PKCS#11 calls made by Linux applications using eBPF
uprobes. It reports functions, callers, return values, counts and latency
without replacing the application's provider. Its privacy allowlist excludes
payloads, PINs and key material.

This first release provides doctor, inspect, profile, trace and run,
function-table discovery, multi-module capture, aggregate-only metrics and
versioned JSON reports. The optional p11scope-discover helper creates a
provider manifest for the documented attested semantic-capture workflow.

Download p11scope-0.1.0-x86_64-linux-musl.tar.gz and SHA256SUMS. The
observer is static and embeds its BPF programs; binary installation needs
neither Rust nor the BPF build toolchain. The optional discovery helper must
match the provider's libc: choose the glibc or musl archive. Both helpers
are dynamically linked. All three binary bundles include licenses,
third-party notices and RELEASE.json provenance.

Follow the installation instructions,
then run sudo p11scope doctor and sudo p11scope inspect --pid PID.
The operator guide
explains capture commands, privileges, mechanisms and evidence interpretation.
Linux x86-64 with BTF and the documented kernel/privilege requirements is
required; the supported kernel floor is 5.15.

The attached p11scope-0.1.0-source.tar.gz includes the committed source,
exact pinned Aya archives and patch recipe. Its remaining locked Cargo
dependencies require network access or populated caches, plus the pinned
Rust/BPF and host build tools. GitHub's automatic source archives do not
contain those embedded Aya inputs. Crates.io installation is deferred.

Known limitations:

  • --system is a preview with bounded discovery, shared attach capacity and
    explicit refusal/loss reporting. This release does not claim complete
    continuous inventory or coverage of every provider and caller on a host.
  • Terminal snapshots remain PARTIAL because final callback drainage is
    unproven. Read the reason and counters: withheld attribution, an unproven
    drain and actual observation loss have different meanings.
  • Manifest-free capture is count-only. Semantic interpretation requires the
    documented attestation; provider loading alone does not prove application
    calls or mechanism use.
  • Calls before attachment are not observed. Sandboxed providers may need an
    explicit matching manifest and accessible provider dependencies.
  • The published helper binaries are 64-bit; a 32-bit provider needs a matching
    separately built helper. The observer itself remains x86-64.

The changelog
describes the full command surface, limits and historical candidate results.
The evidence below applies specifically to this release.

Verification

  • Source commit: dcc1645a91ec6e0c1f66fbd3f014b6cece5e7845; tree:
    4040cd0229986206e7e4cd7bed0ac7dc374136af.
  • Hosted staging CI: run 36661058457
    passed normal checks, coverage, release-preview and log archival on this exact
    commit. Full-workspace/all-target line coverage was 85.01% against the unchanged
    83% floor. Main CI run 36663552492
    passed normal checks, coverage (84.99% lines) and archival on the same commit;
    its dispatch-only preview and self-hosted jobs were not selected.
  • Post-release CI: a tag rerun
    exposed a test-fixture cleanup race, and the next main run exposed an injected
    stand-in READY publication race. Both test-only corrections are on main at
    d97e2d2; its CI run
    passed checks/e2e, coverage (85.00% lines) and archival. The v0.1.0 tag and
    assets retain their original source and hashes.
  • Local checks: formatting, locked workspace/all-target check and Clippy passed.
    The full locked/offline workspace/all-target suite passed 2,341 top-level tests,
    zero failures and 51 ignored across 39 targets. Four new retained-FD identity
    regressions and 61 identity tests passed; the reviewed source repair also
    captured every expected call in two diagnostic runs each on 6.1 and 6.6.
    The official-package kernel checks below independently qualify the shipped bytes.
  • Official builder: exit, receipt status, terminal status and digest checker all
    passed with status 0. The binary ledger SHA-256 is
    116c9d60fb501bf83567c244858a2c5befc63f4bd2e87e8b062be1f5be077915.
    The full 12-lane live privacy matrix, attach and hostile-target smokes passed.
  • Official observer SHA-256:
    fa4e86937b006eea8f578294c12326f9105ccb47f13154f224281a9106775937.
    The safe-only static musl observer embeds its BPF object and contains no build-home
    path. GNU and musl helpers remain separately labeled and dynamically linked.
  • Toolchains: Rust 1.88.0 (6b00bc388, 2025-06-23); BPF Rust
    1.97.0-nightly (e50aa6fba, nightly-2026-05-20); bpf-linker 0.10.4;
    Ubuntu clang 18.1.8. Binary reproducibility across independent builds has
    not been established.
  • Final archive verification: all six assets passed checksum, exact inventory,
    archive-mode, license/notice, provenance and official-binary identity checks.
    Version/help passed for the extracted observer and GNU helper on the host and
    for the musl helper in a pinned Alpine container.
  • Source-recipient verification: all 669 regular exported files, modes, hashes
    and the complete inventory passed verification. Embedded Aya inputs reconstructed
    offline, and a recipient musl observer build reported p11scope 0.1.0. Remaining
    Cargo dependencies used populated caches; this is not an empty-cache or fully
    offline build claim.
  • Packaged observer host qualification: all 12 public-command cells passed
    on Linux 7.0.0-34-generic,
    including independent per-function counts, metrics, trace, multithreaded capture,
    system-preview scope, owned run, FIFO refusal and SIGINT publication.
  • Packaged observer kernel qualification: all 12 public-command cells passed
    independently on each of 5.15.0-187-generic, 6.1.188-0601188-generic,
    6.6.157-0606157-generic, 6.8.0-142-generic, 6.12.111-0612111-generic,
    and 7.2.6-070206-generic. Every owned-run cell captured exactly 12,008 calls
    across 14 named functions, with protected pause and zero checked observation
    faults. These are local owned VM tests; Linux 7.0 is separately covered by
    the host matrix above. A distinct pinned 7.0 VM lane is planned.
  • Packaged observer container qualification: Docker, shared-layer and fork-scope/
    privilege lanes passed using the exact observer and GNU helper from these
    bundles. Owned services and containers were retired; no newly created matrix
    resources remained. Expected partial coverage and refusals remain reported.
  • Overhead: the separately source-built observer at this same commit was
    benchmarked on Linux 7.0.0-34-generic, AMD Ryzen AI 9 HX PRO 370, in five
    interleaved rounds of 1,000,000 calls per condition (1,000-call warm-up for
    observed runs). All 15 observed samples were valid; none were excluded.
    Median additional time per call was 3.632 µs for metrics, 6.810 µs for profile
    and 5.066 µs for trace, against an unobserved median of 0.748 µs per call.
    These controlled microbenchmark results apply to source-built observer
    SHA-256 2e138aec3a4f200ac26258fdc310db7703fbbde0c83bd0c1973726dc687ae63d;
    they are not measurements of the packaged static observer or a universal
    application-overhead estimate.
  • Post-publication acquisition: all six published assets downloaded anonymously
    over HTTPS with HTTP 200, matched the retained official checksums and passed
    independent archive, mode, notice, provenance and binary-identity verification.
    A fresh private-prefix installation of those downloaded binaries reported
    0.1.0; version/help and privileged doctor passed on Linux 7.0.0-34-generic.
    The downloaded musl helper also passed version/help in the pinned Alpine
    container, which was removed after the check.
  • Local real-application capture: the exact downloaded observer and GNU helper
    traced an owned Firefox 156.0.1 session using libsoftokn3.so. Two HTTPS
    navigations completed inside the capture window. The trace contained 8,539
    named PKCS#11 events across 44 functions and five independently identified
    Firefox process generations, including signing, key generation and message
    encryption/decryption. Entry, return and rendered-event totals agreed; reported
    event/ring/output losses, unmatched returns, in-flight calls and truncation
    were zero. Owned browser processes and BPF links were retired.
    This demonstrates local installed functionality; the stricter whole-cgroup
    check failed because the report identified a skipped discovery subject,
    three vendor interfaces, interface-selection coverage gaps and four child
    ingress gaps. It remains PARTIAL, with withheld attribution, operation-state
    reconstruction limits and unproven final drainage. Complete browser/system
    coverage and the number of underlying application operations are not certified.
    This was a local test, separate from hosted CI.
Asset SHA-256
RELEASE.json d09db29666c819797ba6a5f5ce0f4099137c726848cea846488de9d44521b92b
SHA256SUMS 52f21c3963c1cfe24c3ed31d649b53d7c72ad7a0604473740c5b2d46e9ba086b
p11scope-0.1.0-source.tar.gz 4bf09c81c0d5f5dc44c54565c04504096ad4bb1a25bb64848eb0ae8b234e1aad
p11scope-0.1.0-x86_64-linux-musl.tar.gz 840c4ef88fce3245d971cbd0077db89e7852f129dc3a47449f4e274d4cbbe713
p11scope-discover-0.1.0-x86_64-linux-gnu.tar.gz 9caa3212f092efb5b987d000cead0cb34e5bd837661a84c1edf07dc7d11dd91f
p11scope-discover-0.1.0-x86_64-linux-musl.tar.gz 183c327b6afd2e19992b6516538e213c3e90a00ee52a01c5225594938ad66b8c