mirror of
https://github.com/hanzoai/visor.git
synced 2026-09-24 17:04:14 +00:00
Directfs accesses host filesystem directly, without going through the gofer server. This change basically adds runsc fsgofer functionality into the gofer client. We use the gofer dentry impl abstraction to make direct host syscalls instead of making LISAFS RPCs. It works on a donated FD to the root of the mount. All other relevant mount options supported in gofer client are also supported here. Directfs is also a lisafs user. Directfs client makes a Mount RPC. The server is expected to donate a host FD to the mount point that the client can use to perform all necessary filesystem operations. Directfs client does not set up any flipcall channels, because it (mostly) doesn't make any RPCs. Note however that we can not avoid LISAFS RPCs in certain cases. Certain operations like bind(2) and connect(2) require host paths. But the container filesystem is not mounted inside the sandbox's mount namespace. The sandbox just has an FD to the filesystem root. Furthermore, procfs is also not mounted in the sandbox process for security reasons. Otherwise we could have used host paths like `/proc/self/fd/<sockFD>`. The only viable option is to use fchdir(2) to change working directory to the socket's parent directory and use a relative host path from there. But in certain situations, we don't even have access to a socket's parent directory (in case of a socket mount point). The parent lives in a different gofer mount in the sentry. There is no clean way of fetching that. In these extreme corner cases, directfs falls back to using LISAFS RPCs. These corner cases are: - chmod(2) on mount point socket. - utimensat(2) on mount point symlink. - connect(2) on mount point socket. PiperOrigin-RevId: 510465837
51 lines
1.3 KiB
Go
51 lines
1.3 KiB
Go
// Copyright 2019 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.
|
|
|
|
//go:build amd64
|
|
// +build amd64
|
|
|
|
package fsutil
|
|
|
|
import (
|
|
"unsafe"
|
|
|
|
"golang.org/x/sys/unix"
|
|
"gvisor.dev/gvisor/pkg/syserr"
|
|
)
|
|
|
|
// StatAt is a convenience wrapper around newfstatat(2).
|
|
func StatAt(dirFd int, name string) (unix.Stat_t, error) {
|
|
nameBytes, err := unix.BytePtrFromString(name)
|
|
if err != nil {
|
|
return unix.Stat_t{}, err
|
|
}
|
|
namePtr := unsafe.Pointer(nameBytes)
|
|
|
|
var stat unix.Stat_t
|
|
statPtr := unsafe.Pointer(&stat)
|
|
|
|
if _, _, errno := unix.Syscall6(
|
|
unix.SYS_NEWFSTATAT,
|
|
uintptr(dirFd),
|
|
uintptr(namePtr),
|
|
uintptr(statPtr),
|
|
unix.AT_SYMLINK_NOFOLLOW,
|
|
0,
|
|
0); errno != 0 {
|
|
|
|
return unix.Stat_t{}, syserr.FromHost(errno).ToError()
|
|
}
|
|
return stat, nil
|
|
}
|