mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Enable stat syscall support on arm64.
x86 and arm64 use a different stat struct in Linux kernel, so the stat() syscall implementation has to handle the file stat data separately. Signed-off-by: Haibo Xu <haibo.xu@arm.com> Change-Id: If3986e915a667362257a54e7fbbcc1fe18951015 COPYBARA_INTEGRATE_REVIEW=https://github.com/google/gvisor/pull/1493 from xiaobo55x:stat f15a216d9297eb9a96d2c483d396a9919145d7fa PiperOrigin-RevId: 290274287
This commit is contained in:
@@ -42,6 +42,8 @@ go_library(
|
||||
"sys_socket.go",
|
||||
"sys_splice.go",
|
||||
"sys_stat.go",
|
||||
"sys_stat_amd64.go",
|
||||
"sys_stat_arm64.go",
|
||||
"sys_sync.go",
|
||||
"sys_sysinfo.go",
|
||||
"sys_syslog.go",
|
||||
|
||||
@@ -61,6 +61,7 @@ var ARM64 = &kernel.SyscallTable{
|
||||
22: syscalls.Supported("epoll_pwait", EpollPwait),
|
||||
23: syscalls.Supported("dup", Dup),
|
||||
24: syscalls.Supported("dup3", Dup3),
|
||||
25: syscalls.PartiallySupported("fcntl", Fcntl, "Not all options are supported.", nil),
|
||||
26: syscalls.Supported("inotify_init1", InotifyInit1),
|
||||
27: syscalls.PartiallySupported("inotify_add_watch", InotifyAddWatch, "inotify events are only available inside the sandbox.", nil),
|
||||
28: syscalls.PartiallySupported("inotify_rm_watch", InotifyRmWatch, "inotify events are only available inside the sandbox.", nil),
|
||||
@@ -78,7 +79,9 @@ var ARM64 = &kernel.SyscallTable{
|
||||
40: syscalls.PartiallySupported("mount", Mount, "Not all options or file systems are supported.", nil),
|
||||
41: syscalls.Error("pivot_root", syserror.EPERM, "", nil),
|
||||
42: syscalls.Error("nfsservctl", syserror.ENOSYS, "Removed after Linux 3.1.", nil),
|
||||
43: syscalls.PartiallySupported("statfs", Statfs, "Depends on the backing file system implementation.", nil),
|
||||
44: syscalls.PartiallySupported("fstatfs", Fstatfs, "Depends on the backing file system implementation.", nil),
|
||||
45: syscalls.Supported("truncate", Truncate),
|
||||
46: syscalls.Supported("ftruncate", Ftruncate),
|
||||
47: syscalls.PartiallySupported("fallocate", Fallocate, "Not all options are supported.", nil),
|
||||
48: syscalls.Supported("faccessat", Faccessat),
|
||||
@@ -112,6 +115,7 @@ var ARM64 = &kernel.SyscallTable{
|
||||
76: syscalls.PartiallySupported("splice", Splice, "Stub implementation.", []string{"gvisor.dev/issue/138"}), // TODO(b/29354098)
|
||||
77: syscalls.Supported("tee", Tee),
|
||||
78: syscalls.Supported("readlinkat", Readlinkat),
|
||||
79: syscalls.Supported("fstatat", Fstatat),
|
||||
80: syscalls.Supported("fstat", Fstat),
|
||||
81: syscalls.PartiallySupported("sync", Sync, "Full data flush is not guaranteed at this time.", nil),
|
||||
82: syscalls.PartiallySupported("fsync", Fsync, "Full data flush is not guaranteed at this time.", nil),
|
||||
@@ -254,6 +258,8 @@ var ARM64 = &kernel.SyscallTable{
|
||||
219: syscalls.Error("keyctl", syserror.EACCES, "Not available to user.", nil),
|
||||
220: syscalls.PartiallySupported("clone", Clone, "Mount namespace (CLONE_NEWNS) not supported. Options CLONE_PARENT, CLONE_SYSVSEM not supported.", nil),
|
||||
221: syscalls.Supported("execve", Execve),
|
||||
222: syscalls.PartiallySupported("mmap", Mmap, "Generally supported with exceptions. Options MAP_FIXED_NOREPLACE, MAP_SHARED_VALIDATE, MAP_SYNC MAP_GROWSDOWN, MAP_HUGETLB are not supported.", nil),
|
||||
223: syscalls.PartiallySupported("fadvise64", Fadvise64, "Not all options are supported.", nil),
|
||||
224: syscalls.CapError("swapon", linux.CAP_SYS_ADMIN, "", nil),
|
||||
225: syscalls.CapError("swapoff", linux.CAP_SYS_ADMIN, "", nil),
|
||||
226: syscalls.Supported("mprotect", Mprotect),
|
||||
@@ -299,6 +305,8 @@ var ARM64 = &kernel.SyscallTable{
|
||||
282: syscalls.ErrorWithEvent("userfaultfd", syserror.ENOSYS, "", []string{"gvisor.dev/issue/266"}), // TODO(b/118906345)
|
||||
283: syscalls.ErrorWithEvent("membarrier", syserror.ENOSYS, "", []string{"gvisor.dev/issue/267"}), // TODO(gvisor.dev/issue/267)
|
||||
284: syscalls.PartiallySupported("mlock2", Mlock2, "Stub implementation. The sandbox lacks appropriate permissions.", nil),
|
||||
|
||||
// Syscalls after 284 are "backports" from versions of Linux after 4.4.
|
||||
285: syscalls.ErrorWithEvent("copy_file_range", syserror.ENOSYS, "", nil),
|
||||
286: syscalls.Supported("preadv2", Preadv2),
|
||||
287: syscalls.PartiallySupported("pwritev2", Pwritev2, "Flag RWF_HIPRI is not supported.", nil),
|
||||
|
||||
@@ -16,7 +16,6 @@ package linux
|
||||
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/binary"
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel"
|
||||
@@ -125,56 +124,6 @@ func fstat(t *kernel.Task, f *fs.File, statAddr usermem.Addr) error {
|
||||
return copyOutStat(t, statAddr, f.Dirent.Inode.StableAttr, uattr)
|
||||
}
|
||||
|
||||
// copyOutStat copies the attributes (sattr, uattr) to the struct stat at
|
||||
// address dst in t's address space. It encodes the stat struct to bytes
|
||||
// manually, as stat() is a very common syscall for many applications, and
|
||||
// t.CopyObjectOut has noticeable performance impact due to its many slice
|
||||
// allocations and use of reflection.
|
||||
func copyOutStat(t *kernel.Task, dst usermem.Addr, sattr fs.StableAttr, uattr fs.UnstableAttr) error {
|
||||
b := t.CopyScratchBuffer(int(linux.SizeOfStat))[:0]
|
||||
|
||||
// Dev (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(sattr.DeviceID))
|
||||
// Ino (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(sattr.InodeID))
|
||||
// Nlink (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uattr.Links)
|
||||
// Mode (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, sattr.Type.LinuxType()|uint32(uattr.Perms.LinuxMode()))
|
||||
// UID (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, uint32(uattr.Owner.UID.In(t.UserNamespace()).OrOverflow()))
|
||||
// GID (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, uint32(uattr.Owner.GID.In(t.UserNamespace()).OrOverflow()))
|
||||
// Padding (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, 0)
|
||||
// Rdev (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(linux.MakeDeviceID(sattr.DeviceFileMajor, sattr.DeviceFileMinor)))
|
||||
// Size (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(uattr.Size))
|
||||
// Blksize (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(sattr.BlockSize))
|
||||
// Blocks (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(uattr.Usage/512))
|
||||
|
||||
// ATime
|
||||
atime := uattr.AccessTime.Timespec()
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(atime.Sec))
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(atime.Nsec))
|
||||
|
||||
// MTime
|
||||
mtime := uattr.ModificationTime.Timespec()
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(mtime.Sec))
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(mtime.Nsec))
|
||||
|
||||
// CTime
|
||||
ctime := uattr.StatusChangeTime.Timespec()
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(ctime.Sec))
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(ctime.Nsec))
|
||||
|
||||
_, err := t.CopyOutBytes(dst, b)
|
||||
return err
|
||||
}
|
||||
|
||||
// Statx implements linux syscall statx(2).
|
||||
func Statx(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
|
||||
fd := args[0].Int()
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
//+build amd64
|
||||
|
||||
package linux
|
||||
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/binary"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel"
|
||||
"gvisor.dev/gvisor/pkg/sentry/usermem"
|
||||
)
|
||||
|
||||
// copyOutStat copies the attributes (sattr, uattr) to the struct stat at
|
||||
// address dst in t's address space. It encodes the stat struct to bytes
|
||||
// manually, as stat() is a very common syscall for many applications, and
|
||||
// t.CopyObjectOut has noticeable performance impact due to its many slice
|
||||
// allocations and use of reflection.
|
||||
func copyOutStat(t *kernel.Task, dst usermem.Addr, sattr fs.StableAttr, uattr fs.UnstableAttr) error {
|
||||
b := t.CopyScratchBuffer(int(linux.SizeOfStat))[:0]
|
||||
|
||||
// Dev (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(sattr.DeviceID))
|
||||
// Ino (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(sattr.InodeID))
|
||||
// Nlink (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uattr.Links)
|
||||
// Mode (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, sattr.Type.LinuxType()|uint32(uattr.Perms.LinuxMode()))
|
||||
// UID (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, uint32(uattr.Owner.UID.In(t.UserNamespace()).OrOverflow()))
|
||||
// GID (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, uint32(uattr.Owner.GID.In(t.UserNamespace()).OrOverflow()))
|
||||
// Padding (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, 0)
|
||||
// Rdev (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(linux.MakeDeviceID(sattr.DeviceFileMajor, sattr.DeviceFileMinor)))
|
||||
// Size (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(uattr.Size))
|
||||
// Blksize (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(sattr.BlockSize))
|
||||
// Blocks (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(uattr.Usage/512))
|
||||
|
||||
// ATime
|
||||
atime := uattr.AccessTime.Timespec()
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(atime.Sec))
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(atime.Nsec))
|
||||
|
||||
// MTime
|
||||
mtime := uattr.ModificationTime.Timespec()
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(mtime.Sec))
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(mtime.Nsec))
|
||||
|
||||
// CTime
|
||||
ctime := uattr.StatusChangeTime.Timespec()
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(ctime.Sec))
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(ctime.Nsec))
|
||||
|
||||
_, err := t.CopyOutBytes(dst, b)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
//+build arm64
|
||||
|
||||
package linux
|
||||
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/binary"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel"
|
||||
"gvisor.dev/gvisor/pkg/sentry/usermem"
|
||||
)
|
||||
|
||||
// copyOutStat copies the attributes (sattr, uattr) to the struct stat at
|
||||
// address dst in t's address space. It encodes the stat struct to bytes
|
||||
// manually, as stat() is a very common syscall for many applications, and
|
||||
// t.CopyObjectOut has noticeable performance impact due to its many slice
|
||||
// allocations and use of reflection.
|
||||
func copyOutStat(t *kernel.Task, dst usermem.Addr, sattr fs.StableAttr, uattr fs.UnstableAttr) error {
|
||||
b := t.CopyScratchBuffer(int(linux.SizeOfStat))[:0]
|
||||
|
||||
// Dev (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(sattr.DeviceID))
|
||||
// Ino (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(sattr.InodeID))
|
||||
// Mode (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, sattr.Type.LinuxType()|uint32(uattr.Perms.LinuxMode()))
|
||||
// Nlink (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, uint32(uattr.Links))
|
||||
// UID (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, uint32(uattr.Owner.UID.In(t.UserNamespace()).OrOverflow()))
|
||||
// GID (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, uint32(uattr.Owner.GID.In(t.UserNamespace()).OrOverflow()))
|
||||
// Rdev (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(linux.MakeDeviceID(sattr.DeviceFileMajor, sattr.DeviceFileMinor)))
|
||||
// Padding (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, 0)
|
||||
// Size (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(uattr.Size))
|
||||
// Blksize (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, uint32(sattr.BlockSize))
|
||||
// Padding (uint32)
|
||||
b = binary.AppendUint32(b, usermem.ByteOrder, 0)
|
||||
// Blocks (uint64)
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(uattr.Usage/512))
|
||||
|
||||
// ATime
|
||||
atime := uattr.AccessTime.Timespec()
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(atime.Sec))
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(atime.Nsec))
|
||||
|
||||
// MTime
|
||||
mtime := uattr.ModificationTime.Timespec()
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(mtime.Sec))
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(mtime.Nsec))
|
||||
|
||||
// CTime
|
||||
ctime := uattr.StatusChangeTime.Timespec()
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(ctime.Sec))
|
||||
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(ctime.Nsec))
|
||||
|
||||
_, err := t.CopyOutBytes(dst, b)
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user