RC RANDOM CHAOS

LUKS suspend leaves your encryption key in memory

On Linux 6.9, LUKS suspend returns success but does not wipe disk encryption keys from memory. The success report no longer proves the state it claims.

· 7 min read
LUKS suspend leaves your encryption key in memory

Linux 6.9 ships a LUKS suspend operation that does not remove disk encryption keys from memory. The single function that operation is named for, the wipe, does not run. When LUKS suspend is invoked against an encrypted volume, the volume is presented as suspended, and the key that decrypts it is not cleared from memory. The control that this operation exists to enforce does not enforce.

State the position without softening. A control that does not perform its enforcing action is not a control. It is a label. The suspend operation carries the reputation of removing the key while producing none of the effect. Every system that called this operation and treated the result as protective was operating on a guarantee that was not delivered.

Two things are confirmed and no more. Since Linux 6.9, disk encryption keys are not wiped from memory on LUKS suspend. That is the fact. Everything past that boundary is not confirmed. The cause of the change is not confirmed. Whether the condition has been exploited is not confirmed. The number of affected systems is not confirmed. How long a key remains resident after the operation returns is not confirmed. Accuracy governs here over completeness. The failure is defined by what is stated, not by what is plausible.

The LUKS suspend operation exists to do one specific thing. It freezes access to an encrypted volume and removes the encryption key from memory while the volume stays mounted. That second action is the reason the operation has value. Suspending a volume without clearing the key would be a state change with no security effect. The wipe is the point.

Operators built protection models on that behavior. Disk encryption defends data at rest. A running system with the key held in memory is not at rest, because the material that converts ciphertext to plaintext is present and reachable. The suspend operation was the mechanism that moved a live system back toward the at-rest condition without a full shutdown. The assumption embedded in every use of it was direct. After suspend, the key is gone from memory, and a capture of memory yields nothing that unlocks the volume.

That assumption is a boundary statement. The key is the boundary between encrypted storage and readable data. Whoever holds the key holds the data, independent of every other access control on the system. The memory wipe was the enforcement point for that boundary during suspend. The design placed trust in that single action. The value of the operation was never the freeze. It was the removal of the key from the one location an attacker with memory access could read.

Since Linux 6.9, the observable behavior of the operation changed in one respect. Invoking LUKS suspend no longer results in the key being wiped from memory. The action that defined the operation stopped occurring. That is the state transition, and it is the only transition supported by the facts. The prior behavior included the wipe. The current behavior does not.

The operation still returns. It still reports the volume as suspended. That is the failure condition, not a mitigation of it. The success signal of the operation no longer corresponds to the state it claims. An operator who runs LUKS suspend and receives a successful result now holds a false belief about the contents of memory. The reported state and the actual state have separated. The system says the volume is suspended and protected. The key says otherwise, because the key is still there. A control that reports success while failing to act is worse than an absent control, because it suppresses the response that its own failure should trigger.

What produced the change is not confirmed, and it is not to be assumed. How the regression entered 6.9 is not confirmed. Whether a corrected version exists is not confirmed. Whether the condition extends beyond LUKS suspend into other encryption workflows is not confirmed. Whether the key persists in memory for seconds or indefinitely after the operation is not confirmed. These gaps are not to be filled with behavior borrowed from similar incidents. The condition is defined by one confirmed fact. In Linux 6.9, LUKS suspend does not wipe disk encryption keys from memory. Everything an operator does next has to start from that statement and nothing added to it.

The failure is visible in the gap between two outputs of the same operation. LUKS suspend returns. It reports the volume as suspended. The wipe does not run. These are not three views of one event. They are the confirmed behavior of the operation on Linux 6.9, and they do not agree. The return value reports an action that did not occur.

A key held in memory is readable by anything with access to that memory. That is the property disk encryption removes at rest, and it is the property the wipe existed to restore during suspend. On 6.9 the wipe does not run, so the property is not restored. The volume is reported as suspended while the material that decrypts it stays in the one location a memory capture reads. Capture the memory, read the key, decrypt the volume. The success report does nothing to interrupt that sequence, because the report and the wipe are now separate. One occurs. The other does not.

Nothing beyond that is confirmed. Whether the key sits in memory for seconds or remains until power loss is not confirmed. Whether an attacker has read it is not confirmed. Whether the same gap exists in encryption workflows other than LUKS suspend is not confirmed. The mechanism is defined only by what is observable. The operation returns success, and the key is still there. Every unknown past that point stays unknown, and none of them are required to describe the failure. The success signal no longer proves the state it reports. That is the mechanism, complete.

The mechanism generalizes to a single condition. A control’s success report and the control’s enforcing action are separate things. When they are coupled, the report is evidence of the action. When they are not, the report is evidence of nothing but its own execution. On 6.9, LUKS suspend reports success and does not wipe. The report survived the removal of the action it was supposed to certify. Any control built this way can enter the same state.

The exposure is not the missing wipe by itself. It is that the missing wipe produces no signal. The operation does not fail loudly. It does not return an error. It returns the same success it returned when the wipe still ran. Every system that reads that return value and marks the volume protected inherits the false state and passes it forward. A control that fails silently while reporting success removes the one condition that would trigger a response. The absence of the wipe and the presence of a success report are the same event here, and that is what makes it worse than no control at all.

The same shape appears in any operation whose result is trusted by its return rather than confirmed by its effect. If the enforcing action can be removed while the success report remains, the report is a label, not proof. This is the Phase 1 condition stated as a class. The wipe is the action. The suspend return is the label. On 6.9 they came apart, and only the label was left. Wherever a control is accepted on its word instead of its result, the same separation is possible, and the same silent gap follows.

Define what must now be true. On Linux 6.9, a LUKS volume that has been through the suspend operation must be treated as a volume with its key in memory. The suspend return does not change that. Any protection model that counted the key as gone after suspend on 6.9 was counting on an action that does not run, and that model is void until the effect is confirmed by something other than the operation’s own report.

The key is the boundary. Whoever reads it holds the data, independent of every other control on the system. The wipe was the enforcement of that boundary during suspend, and on 6.9 the enforcement is not present. A boundary with no enforcement is not a boundary. It is a line on a diagram. Treat the encrypted volume on a running 6.9 system as decryptable by anyone who reaches its memory, because that is what the confirmed facts describe and nothing in the operation contradicts it.

A control is not what it is named. It is what it does. LUKS suspend is named for a wipe it does not perform on 6.9, and the name is now the only part of the wipe that remains. Verify controls by their effect, never by their success report, because on 6.9 the two are proven to be different. The wipe either cleared the key or it did not. On this version, it did not. Everything an operator trusted to that operation has to be re-established on evidence of the effect, not the return. If a control cannot be confirmed by its result, it is not confirmed at all.

Share

Keep Reading

Stay in the loop

New writing delivered when it's ready. No schedule, no spam.