Skip to content

Commit e1bf318

Browse files
[no-relnote] Add e2e test for firmware path traversal
A container image could be crafted with a symbolic link in /lib/firmware/nvidia/ that points to a location outside of the container's root filesystem. When running such a container with the NVIDIA Container Toolkit, this could potentially lead to files being created on the host filesystem. This change adds an end-to-end test to ensure that the toolkit is not vulnerable to this kind of path traversal attack. Signed-off-by: Carlos Eduardo Arango Gutierrez <[email protected]>
1 parent d6326e7 commit e1bf318

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

tests/e2e/nvidia-container-toolkit_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package e2e
1818

1919
import (
2020
"context"
21+
"fmt"
2122
"path/filepath"
2223
"strings"
2324

@@ -297,4 +298,54 @@ var _ = Describe("docker", Ordered, ContinueOnFailure, func() {
297298
Expect(err).ToNot(HaveOccurred())
298299
})
299300
})
301+
302+
When("Running a container where the firmware folder resolves outside the container root", Ordered, func() {
303+
var outputDir string
304+
BeforeAll(func(ctx context.Context) {
305+
pwd, _, err := runner.Run("pwd")
306+
Expect(err).ToNot(HaveOccurred())
307+
outputDir = filepath.Join(strings.TrimSpace(pwd), "test-output")
308+
309+
_, _, err = runner.Run(fmt.Sprintf("mkdir -p %s", outputDir))
310+
Expect(err).ToNot(HaveOccurred())
311+
312+
_, _, err = runner.Run("docker pull ubuntu")
313+
Expect(err).ToNot(HaveOccurred())
314+
315+
dockerBuildCmd := fmt.Sprintf(`docker build -t firmware-test --build-arg RM_VERSION="$(basename $(ls -d /lib/firmware/nvidia/*.*))" --build-arg CURRENT_DIR=%q - <<EOF`, outputDir)
316+
dockerBuildDockerfile := `
317+
FROM ubuntu
318+
RUN mkdir -p /lib/firmware/nvidia/
319+
ARG RM_VERSION
320+
ARG CURRENT_DIR
321+
RUN ln -s /../../../../../../../../\$CURRENT_DIR /lib/firmware/nvidia/\$RM_VERSION
322+
EOF`
323+
_, _, err = runner.Run(dockerBuildCmd + dockerBuildDockerfile)
324+
Expect(err).ToNot(HaveOccurred())
325+
})
326+
327+
AfterAll(func(ctx context.Context) {
328+
if outputDir != "" {
329+
runner.Run(fmt.Sprintf("rm -rf %s", outputDir))
330+
}
331+
})
332+
333+
It("should not fail when using CDI", func(ctx context.Context) {
334+
output, _, err := runner.Run("docker run --rm --runtime=nvidia --gpus=all firmware-test")
335+
Expect(err).ToNot(HaveOccurred())
336+
Expect(output).To(BeEmpty())
337+
338+
output, _, _ = runner.Run(fmt.Sprintf("ls -A %s", outputDir))
339+
Expect(output).To(BeEmpty())
340+
})
341+
342+
It("should fail when using the nvidia-container-runtime-hook", Label("legacy"), func(ctx context.Context) {
343+
_, stderr, err := runner.Run("docker run --rm --runtime=runc --gpus=all firmware-test")
344+
Expect(err).To(HaveOccurred())
345+
Expect(stderr).To(ContainSubstring("nvidia-container-cli.real: mount error: path error:"))
346+
347+
output, _, _ := runner.Run(fmt.Sprintf("ls -A %s", outputDir))
348+
Expect(output).To(BeEmpty())
349+
})
350+
})
300351
})

tests/e2e/runner.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ func (r remoteRunner) Run(script string) (string, string, error) {
124124
// Run the script
125125
err = session.Run(script)
126126
if err != nil {
127-
return "", "", fmt.Errorf("script execution failed: %v\nSTDOUT: %s\nSTDERR: %s", err, stdout.String(), stderr.String())
127+
return "", stderr.String(), fmt.Errorf("script execution failed: %v\nSTDOUT: %s\nSTDERR: %s", err, stdout.String(), stderr.String())
128128
}
129129

130130
// Return stdout as string if no errors

0 commit comments

Comments
 (0)