nixos/systemd-boot-builder: rebuild secret-bearing initrds atomically each run
Appending to the existing file made it grow on every rebuild and a failed script could leave it half-written. Always rebuild from the pristine initrd into a temp file and rename into place.
This commit is contained in:
@@ -88,29 +88,26 @@ class InitrdWithSecretsWriter:
|
||||
initrd_secrets: Path
|
||||
|
||||
def write_boot_file(self, path: Path) -> None:
|
||||
if path.exists():
|
||||
# TODO: This is for matching old behavior. Previously, we
|
||||
# appended secrets to initrd every time no matter what, so
|
||||
# we must continue doing that. One potential alternative
|
||||
# would be running the secret script on an empty file and
|
||||
# using the hashed contents of that file as part of the
|
||||
# key that the path name is based on.
|
||||
run([self.initrd_secrets, path])
|
||||
else:
|
||||
with tempfile.NamedTemporaryFile(
|
||||
mode="wb",
|
||||
dir=path.parent,
|
||||
delete=False,
|
||||
prefix=path.name,
|
||||
suffix=".tmp",
|
||||
) as tmp:
|
||||
with open(self.source, mode="rb") as source_file:
|
||||
shutil.copyfileobj(source_file, tmp)
|
||||
tmp.flush()
|
||||
run([self.initrd_secrets, tmp.name])
|
||||
os.fsync(tmp.fileno())
|
||||
tmp.close()
|
||||
os.rename(tmp.name, path)
|
||||
# Secrets can change between rebuilds, so always rebuild from the
|
||||
# pristine initrd into a temp file and rename into place.
|
||||
tmp = tempfile.NamedTemporaryFile(
|
||||
mode="wb",
|
||||
dir=path.parent,
|
||||
delete=False,
|
||||
prefix=path.name,
|
||||
suffix=".tmp",
|
||||
)
|
||||
try:
|
||||
with open(self.source, mode="rb") as source_file:
|
||||
shutil.copyfileobj(source_file, tmp)
|
||||
tmp.close()
|
||||
run([self.initrd_secrets, tmp.name])
|
||||
with open(tmp.name, "rb") as f:
|
||||
os.fsync(f.fileno())
|
||||
except BaseException:
|
||||
os.unlink(tmp.name)
|
||||
raise
|
||||
os.rename(tmp.name, path)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
Reference in New Issue
Block a user