Skip to content

[IR] Add !sensitive metadata for sensitive stack objects - #3

Draft
claude[bot] wants to merge 1 commit into
zeroize-intrinsicfrom
sensitivity-metadata
Draft

[IR] Add !sensitive metadata for sensitive stack objects#3
claude[bot] wants to merge 1 commit into
zeroize-intrinsicfrom
sensitivity-metadata

Conversation

@claude

@claude claude Bot commented Aug 11, 2026

Copy link
Copy Markdown

Requested by Francesco Bertolaccini · Slack thread

Register a fixed metadata kind, MD_sensitive with ID 56, marking an alloca
whose contents should not be left readable in the stack frame once the function
is done with them. The metadata is only used as a flag: its presence on the
alloca is the entire signal and the node must be empty, with the contents of
the node reserved for future use.

%round_keys = alloca [176 x i8], align 16, !sensitive !0

!0 = !{}

The marked objects are what the "sensitive" mode of the "zeroize-stack"
attribute clears, so the LangRef entry is written around the direction of the
fallback between the two, and the attribute entry now cross-references it
instead of referring to "sensitivity metadata" without naming it. The metadata
buys precision and is not itself part of the guarantee, which LangRef spells out
as rules a transform has to respect: dropping the metadata is always permitted,
and where the marked set has stopped describing the frame — a marked object
split, merged, replaced or promoted without the metadata following — the
response is to clear more, at the limit every stack slot the function used, never
to clear less. Attaching it to an object that was not marked before is likewise
permitted and can only widen what is cleared. Absence of the metadata is not a
statement that an object is insensitive, so a transform may not shrink the set
of objects a function clears on the strength of what is or is not marked.

What makes losing the metadata safe is the floor the mode already has: it clears
every frame object whose contents cannot be traced back to a source-level object
— spill slots, the callee-save area, alignment padding — whether or not anything
is marked. Those are exactly the places a copy of marked data can land with
nothing recording where it came from.

Parsing, printing and bitcode serialization of metadata attachments are generic,
so nothing in the parser or the bitcode reader and writer needed changing;
registering the kind is what gives consumers a fixed ID to look the attachment up
by. llvm/test/Assembler/sensitive-metadata.ll covers the textual and bitcode
round-trips, alongside the comparable per-kind assembler tests
associated-metadata.ll and noalias-addrspace-md.ll.

No pass or backend reads the metadata yet, and nothing here changes the
behaviour of any existing pass. Which transforms should be taught to carry the
metadata across the objects they create is scoped separately as
trailofbits/vspells-ct-internal-notes#13; LangRef says that propagation is a
question of precision rather than of correctness, which is what makes it safe to
defer.

The spellings !sensitive and "zeroize-stack" are recommendations still
awaiting sign-off on trailofbits/vspells-ct-internal-notes#64, not ratified
names.

Third change in the wave-1 stack, on top of zeroize-intrinsic. Implements
trailofbits/vspells-ct-internal-notes#12.

AI tool use

This pull request contains AI-generated content. It was prepared with the assistance of Claude Code; the contributor has reviewed the generated code and text, is the author of the contribution, and is accountable for it, per the LLVM AI Tool Use Policy.


Generated by Claude Code

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@claude
claude Bot force-pushed the zeroize-intrinsic branch from 68b8fec to 0bd0b1b Compare August 11, 2026 16:33
@claude
claude Bot force-pushed the sensitivity-metadata branch from a19500d to ce6cbab Compare August 11, 2026 16:33
@claude claude Bot changed the title Add !sensitive metadata for stack objects holding sensitive data [IR] Add !sensitive metadata for sensitive stack objects Aug 11, 2026
kumarak added a commit that referenced this pull request Aug 11, 2026
Emit the two IR function attributes a protected function needs:
"zero-call-used-regs"="all" for register clearing and the new
"zeroize-stack"="used" for stack clearing. The register attribute is the
existing one, reused unchanged. Pinning it to "all" rather than one of the
"used" modes is deliberate: the used-register computation ignores implicit
operands and so misses registers defined only implicitly, which is
acceptable for a hardening option and not for an obligation over machine
state.

The lowering runs after the zero_call_used_regs block so that it wins over
both the command-line mode and an explicit zero_call_used_regs on the same
function. The attribute's guarantee is a minimum that other policy may
widen but not narrow.

Unlike zero_call_used_regs, the requests are not stamped onto call sites.
They describe the callee's own frame and its exits, and putting them on a
call instruction would suggest the call site clears something.

An explicitly annotated main keeps both requests. The existing exemption
that strips the command-line default from main is narrowed rather than
removed, so an un-annotated main is unaffected.

ClangIR emits the same requests, which needs a zeroize_stack field on
LLVM::LLVMFuncOp and the underscore-to-dash conversion in the MLIR
translator. -fzero-call-used-regs behaviour is unchanged throughout, which
the existing zero-call-used-regs tests pin.

Part of #1. Closes #3.
Register a fixed metadata kind marking an alloca whose contents should
not be left readable in the stack frame once the function is done with
them. The metadata is only used as a flag: its presence on the alloca is
the entire signal and the node must be empty, with the contents of the
node reserved for future use.

The marked objects are what the "sensitive" mode of the "zeroize-stack"
attribute clears, so the LangRef entry is written around the direction
of the fallback between the two. The metadata buys precision and is not
itself part of the guarantee. Dropping it is always permitted, and where
the marked set has stopped describing the frame the response is to clear
more, at the limit every stack slot the function used, never to clear
less. Absence of the metadata on an object is not a statement that the
object is insensitive, and a transform may not shrink the set of objects
a function clears on the strength of what is or is not marked. What
makes losing the metadata safe is that the mode's floor already covers
every frame object with no source-level provenance, such as spill slots,
the callee-save area and alignment padding, whether or not anything is
marked.

Parsing, printing and bitcode serialization of metadata attachments are
generic, so the round-trip test needs no new parser code; registering
the kind gives consumers a fixed ID to look the attachment up by. No
pass or backend reads the metadata yet, and which transforms should
carry it across the objects they create is left to a later change.

The name is a recommendation still awaiting sign-off on
trailofbits/vspells-ct-internal-notes#64.
@claude
claude Bot force-pushed the zeroize-intrinsic branch from 0bd0b1b to f01c5be Compare August 11, 2026 19:57
@claude
claude Bot force-pushed the sensitivity-metadata branch from ce6cbab to 6099f1a Compare August 11, 2026 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants