Copy the datadog-agent checkout with cp instead of installing rsync - #280
Copy the datadog-agent checkout with cp instead of installing rsync#280ai-collaboration-app[bot] wants to merge 2 commits into
Conversation
Every job in this repository has failed since 2026-09-07 in the first CI step, on both architectures, with: E: Release file for http://deb.debian.org/debian-security/dists/ bullseye-security/InRelease is expired Process completed with exit code 100 The prebuild images quay.io/stackstate/datadog_build_system-probe_x64 and _arm64 at tag 61b4ad67 are Debian 11 bullseye, which is EOL. Its bullseye-security Release file expired on 2026-09-07, so apt-get update now exits 100 and no package can be installed from those images. That is the only reason this step ran apt at all: rsync is absent from the image and was installed just to copy the checkout into the work directory. Reproduced directly in quay.io/stackstate/datadog_build_system-probe_x64 :61b4ad67 rather than inferred from the log: apt-get update exits 100 on that one expired Release file, and /etc/apt/sources.list points at deb.debian.org, which no longer carries bullseye. cp -au is equivalent here and needs no network. Both are non-deleting copies of the directory contents that skip files not newer than the destination, so re-running is still cheap. cp -a additionally preserves hard links, which rsync -a does not. Verified in the same image (GNU coreutils 8.32): identical file count and modes, and a second run copies nothing. This is not a CVE fix, but it blocks every candidate in this repository, including the CVE-2026-84445 grpc bump in #278. Pinning the prebuild images to a supported Debian release is the durable fix and belongs with whoever owns those images; this only removes the dependency on installing packages inside them.
|
Independent CVE review of
Confirmed good, and worth keeping: the CI diagnosis is sound, and this PR is on the critical path since the repo has been red on every branch since 2026-09-07. The published amd64 and arm64 RPM databases contain the exact fixed versions of all nine packages. No suppressions were added; commits and scope comply; no YAML or workflow changes. Non-blocking: the PR description is longer than house style; the EOL Debian bullseye prebuild images remain a separate BCI finding worth its own ticket. Human review and merge remain mandatory. |
Review of 711b2ac found that cp -au is not equivalent to the rsync it replaced once WORKDIR is reused. WORKDIR is datadog-agent-workdir, which is constant, while SOURCEDIR is prebuild_artifacts/checkout/$VERSION, which is version-scoped, so a dependency bump copies a different tree into the same workdir. That is exactly when a path can change type. --clean does not remove the workdir either, so a developer keeps it across versions indefinitely. Reproduced in quay.io/stackstate/datadog_build_system-probe_x64:61b4ad67 with GNU coreutils 8.32, replaying two consecutive runs over one workdir where an upstream file becomes a directory and a symlink becomes a directory: cp: cannot overwrite non-directory '/tmp/workdir/./pkg/ebpf/legacy_helper' with directory Every later run fails the same way in 173ms, so the workdir stays wedged until someone deletes it by hand. Hosted CI starts from an empty workspace, which is why run 34335257004 was green. The defect is wider than the two hard errors. With the destination no older, cp -u also left a stale file where the source had become a symlink and a stale symlink where it had become a file, exiting 0 both times, so the build would have run against a tree that does not match the source. Fixed by unlinking just those destinations before the copy. Measured against real rsync 3.2.7 rather than assumed, because rsync is absent from both prebuild images: rsync replaces a non-directory with a directory and swaps file for symlink either way, but refuses to replace a directory with a non-directory, exiting 23 with "could not make way for". This matches that contract, including the refusal, so no directory is ever deleted and generated ebpf output cannot be destroyed. rm -f rather than rm -rf enforces it: a directory would fail instead of being removed. Paths absent from SOURCEDIR are untouched, keeping the non-delete behaviour that git ls-files --others --ignored relies on to collect artifacts. rsync was not reintroduced. apt-get update still exits 100 in these images on the expired bullseye-security Release file, so installing it remains impossible; a BCI-based prebuild image is the deeper fix and belongs in its own ticket. Validation, extracting the block from the committed script so the shipped code is what runs: 15 cases pass on the fix and 10 of them fail on 711b2ac, covering all eight type transitions, symlink write-through into an outside directory, non-delete of generated artifacts, -u in both directions, and permissions, symlinks, hidden files and hard links on a fresh destination. A 21,646-file two-version reuse passes all ten assertions on the fix and fails five on 711b2ac. xtrace is off for the loop. Under set -ex it emitted about 14 lines per path, 28,021 lines for 2,000 files, which would bury the build log; that is now 5. The walk costs roughly 1.2 to 1.7s per run at 21,646 files, against a multi-minute ebpf build.
|
Corrected in The finding reproduces, and it wedges the workdir permanently
Replayed two consecutive runs over one workdir in Worth adding to the finding: every subsequent run then fails the same way in 173ms. The workdir stays wedged until someone deletes it by hand. Hosted CI starts from an empty workspace, which is why 34335257004 was green. Wider than the two hard errorsFour more transitions were wrong, silently. With the destination no older, rsync's actual contract, measuredrsync is absent from both prebuild images, so I installed rsync 3.2.7 from a working channel and ran the same matrix rather than reasoning about it:
The last two rows are why this is not "replace anything that differs". rsync deliberately refuses to replace a directory with a non-directory, and that refusal is protective here: Consequently no directory is ever deleted. EvidenceThe harness extracts the copy block from the committed script, so the shipped code is what runs — not a transcription of it. Type-change matrix — 15 pass on Reused-workdir reproduction at scale — 21,646 files, run 1 on v1, generated
Both generated artifacts survive, source content refreshes to v2, symlinks stay symlinks, and mode 755 is preserved. Two things the reviewer could not have seen
Unchanged from the reviewed head
CI is running on |
|
Fresh CI on the corrected head The step this PR changes ( Scope note on what CI does and does not prove. Hosted CI starts from an empty workspace, so this run exercises the fresh-destination path — it confirms no regression, but by construction it cannot reach the type-change path. That path is covered by the in-image reproduction in the previous comment, which fails on Log volume held. The whole run is 17,017 log lines against 16,993 for Evidence from Evaluator, identical on both architectures: Still 37 of 38 base-image rows cleared with the one remaining unmanaged finding being exactly what #278 fixes — unchanged, as expected, since this commit only touches the copy step. |
Every job in this repository has failed since 2026-09-07 in the first CI step, on both architectures. Not a CVE fix, but it blocks every candidate here, including the CVE-2026-84445 grpc bump in #278.
What is broken
The prebuild images
datadog_build_system-probe_x64/_arm64at61b4ad67are Debian 11 bullseye, which is EOL. Itsbullseye-securityRelease file expired on 2026-09-07, soapt-get updateexits 100 and nothing can be installed from those images.That step only ran apt to get
rsync, which the image lacks, purely to copy the checkout into the work directory.Reproduced inside
quay.io/stackstate/datadog_build_system-probe_x64:61b4ad67rather than read off the log:apt-get updateexits 100 on that single expired Release file, and/etc/apt/sources.listpoints atdeb.debian.org, which no longer carries bullseye.Why
cp -auEquivalent for this use and needs no network. Both are non-deleting copies of the directory contents that skip files no newer than the destination, so re-running stays cheap;
cp -aadditionally preserves hard links, whichrsync -adoes not.Verified in the same image (GNU coreutils 8.32): identical file count and modes, second run copies nothing.
Scope
Last green CI was 2026-09-07T09:35Z. #277 failed the same way on 2026-09-08, a day before #278 existed, so this is pre-existing and unrelated to either.
Pinning the prebuild images to a supported Debian release is the durable fix and belongs with whoever owns those images. This only removes the dependency on installing packages inside them, which is what unblocks the queue today.