mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Implement ioctl(fd, FIONREAD) for host FDs
Closes #6796 PiperOrigin-RevId: 409013591
This commit is contained in:
committed by
gVisor bot
parent
ffc3a0d840
commit
07836a3ff1
@@ -11,3 +11,4 @@ RUN gcc -O2 -o test_copy_up test_copy_up.c
|
||||
RUN gcc -O2 -o test_rewinddir test_rewinddir.c
|
||||
RUN gcc -O2 -o link_test link_test.c
|
||||
RUN gcc -O2 -o test_sticky test_sticky.c
|
||||
RUN gcc -O2 -o host_fd host_fd.c
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#include <err.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Tests that FIONREAD is supported with host FD.
|
||||
int main(int argc, char** argv) {
|
||||
int size = 0;
|
||||
if (ioctl(STDOUT_FILENO, FIONREAD, &size) < 0) {
|
||||
err(1, "ioctl(stdin, FIONREAD)");
|
||||
}
|
||||
if (size != 0) {
|
||||
err(1, "FIONREAD wrong size, want: 0, got: %d", size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -31,6 +31,7 @@ go_library(
|
||||
"connected_endpoint_refs.go",
|
||||
"control.go",
|
||||
"host.go",
|
||||
"host_unsafe.go",
|
||||
"inode_refs.go",
|
||||
"ioctl_unsafe.go",
|
||||
"save_restore.go",
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/fspath"
|
||||
"gvisor.dev/gvisor/pkg/hostarch"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/hostfd"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel"
|
||||
@@ -910,3 +911,21 @@ func (f *fileDescription) EventUnregister(e *waiter.Entry) {
|
||||
func (f *fileDescription) Readiness(mask waiter.EventMask) waiter.EventMask {
|
||||
return fdnotifier.NonBlockingPoll(int32(f.inode.hostFD), mask)
|
||||
}
|
||||
|
||||
// Ioctl queries the underlying FD for allowed ioctl commands.
|
||||
func (f *fileDescription) Ioctl(ctx context.Context, uio usermem.IO, args arch.SyscallArguments) (uintptr, error) {
|
||||
switch cmd := args[1].Int(); cmd {
|
||||
case linux.FIONREAD:
|
||||
v, err := ioctlFionread(f.inode.hostFD)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var buf [4]byte
|
||||
hostarch.ByteOrder.PutUint32(buf[:], v)
|
||||
_, err = uio.CopyOut(ctx, args[2].Pointer(), buf[:], usermem.IOOpts{})
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return f.FileDescriptionDefaultImpl.Ioctl(ctx, uio, args)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright 2021 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 host
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
)
|
||||
|
||||
func ioctlFionread(fd int) (uint32, error) {
|
||||
var v uint32
|
||||
if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), linux.FIONREAD, uintptr(unsafe.Pointer(&v))); errno != 0 {
|
||||
return 0, errno
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
@@ -134,9 +134,15 @@ var allowedSyscalls = seccomp.SyscallRules{
|
||||
},
|
||||
unix.SYS_GETTID: {},
|
||||
unix.SYS_GETTIMEOFDAY: {},
|
||||
// SYS_IOCTL is needed for terminal support, but we only allow
|
||||
// setting/getting termios and winsize.
|
||||
unix.SYS_IOCTL: []seccomp.Rule{
|
||||
// These commands are needed for host FD.
|
||||
{
|
||||
seccomp.MatchAny{}, /* fd */
|
||||
seccomp.EqualTo(linux.FIONREAD),
|
||||
seccomp.MatchAny{}, /* int* */
|
||||
},
|
||||
// These commands are needed for terminal support, but we only allow
|
||||
// setting/getting termios and winsize.
|
||||
{
|
||||
seccomp.MatchAny{}, /* fd */
|
||||
seccomp.EqualTo(linux.TCGETS),
|
||||
|
||||
@@ -612,6 +612,16 @@ func TestStickyDir(t *testing.T) {
|
||||
runIntegrationTest(t, nil, "./test_sticky")
|
||||
}
|
||||
|
||||
func TestHostFD(t *testing.T) {
|
||||
if vfs2Used, err := dockerutil.UsingVFS2(); err != nil {
|
||||
t.Fatalf("failed to read config for runtime %s: %v", dockerutil.Runtime(), err)
|
||||
} else if !vfs2Used {
|
||||
t.Skip("test fails on VFS1.")
|
||||
}
|
||||
|
||||
runIntegrationTest(t, nil, "./host_fd")
|
||||
}
|
||||
|
||||
func runIntegrationTest(t *testing.T, capAdd []string, args ...string) {
|
||||
ctx := context.Background()
|
||||
d := dockerutil.MakeContainer(ctx, t)
|
||||
|
||||
Reference in New Issue
Block a user