Files
Shayon Mukherjee 2f33a0198c sandboxsetup: export gofer mount setup functions for reuse
Building a custom gVisor gofer that serves LisaFS-backed volumes requires
duplicating unexported mount setup code from runsc/cmd/gofer.go.
These are Gofer struct methods (setupRootFS, setupMounts, setupDev,
resolveMounts, writeMounts) that must be manually re-synced on every gVisor
version bump.

This is a continuation of the work in #12902 which exported standalone utility
functions. The remaining methods only access struct fields for mount
configurations, device FDs, and mount FDs that can be passed as explicit
parameters.

To avoid importing the heavy runsc/boot package from sandboxsetup, this change
moves GoferMountConf and related types from runsc/boot to runsc/specutils
(replacing the erofs.Name import with a hardcoded "erofs" string, consistent
with specutils.IsErofsMount). All callers now use specutils.GoferMountConf
directly with no type aliases in boot.

Also introduces a MountOpener callback to avoid importing runsc/container.

Also deletes the now-unused vfio.VFIOPath constant (sandboxsetup was its only
consumer and uses a local constant instead).

Also fixes a nil pointer dereference in setupMounts where srcFile.Close()
was called unconditionally, but srcFile is nil when unix.Access succeeds.
2026-04-15 14:38:49 -04:00

91 lines
2.8 KiB
Go

// Copyright 2024 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sandboxsetup
import (
"testing"
)
func TestShouldExposeNvidiaDevice(t *testing.T) {
tests := []struct {
name string
path string
want bool
}{
{name: "nvidiactl", path: "/dev/nvidiactl", want: true},
{name: "nvidia-uvm", path: "/dev/nvidia-uvm", want: true},
{name: "nvidia0", path: "/dev/nvidia0", want: true},
{name: "nvidia1", path: "/dev/nvidia1", want: true},
{name: "nvidia42", path: "/dev/nvidia42", want: true},
{name: "nvidia-uvm-tools", path: "/dev/nvidia-uvm-tools", want: false},
{name: "nvidia-modeset", path: "/dev/nvidia-modeset", want: false},
{name: "not nvidia", path: "/dev/sda", want: false},
{name: "nvidia prefix but not device", path: "/dev/nvidia-cap1", want: false},
{name: "empty", path: "", want: false},
}
for _, tst := range tests {
t.Run(tst.name, func(t *testing.T) {
got := ShouldExposeNvidiaDevice(tst.path)
if got != tst.want {
t.Errorf("ShouldExposeNvidiaDevice(%q) = %v, want %v", tst.path, got, tst.want)
}
})
}
}
func TestShouldExposeVFIODevice(t *testing.T) {
tests := []struct {
name string
path string
want bool
}{
{name: "vfio dir", path: "/dev/vfio/vfio", want: true},
{name: "vfio group", path: "/dev/vfio/0", want: true},
{name: "vfio dir itself", path: "/dev/vfio", want: true},
{name: "not vfio", path: "/dev/sda", want: false},
{name: "empty", path: "", want: false},
}
for _, tst := range tests {
t.Run(tst.name, func(t *testing.T) {
got := ShouldExposeVFIODevice(tst.path)
if got != tst.want {
t.Errorf("ShouldExposeVFIODevice(%q) = %v, want %v", tst.path, got, tst.want)
}
})
}
}
func TestShouldExposeTpuDevice(t *testing.T) {
tests := []struct {
name string
path string
want bool
}{
// VFIO devices are always detected as TPU devices regardless of sysfs.
{name: "vfio device", path: "/dev/vfio/0", want: true},
{name: "vfio vfio", path: "/dev/vfio/vfio", want: true},
{name: "not tpu", path: "/dev/sda", want: false},
{name: "empty", path: "", want: false},
}
for _, tst := range tests {
t.Run(tst.name, func(t *testing.T) {
got := ShouldExposeTpuDevice(tst.path)
if got != tst.want {
t.Errorf("ShouldExposeTpuDevice(%q) = %v, want %v", tst.path, got, tst.want)
}
})
}
}