gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/fsimpl/sys/kcov.go (about) 1 // Copyright 2020 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package sys 16 17 import ( 18 "gvisor.dev/gvisor/pkg/abi/linux" 19 "gvisor.dev/gvisor/pkg/context" 20 "gvisor.dev/gvisor/pkg/errors/linuxerr" 21 "gvisor.dev/gvisor/pkg/sentry/arch" 22 "gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs" 23 "gvisor.dev/gvisor/pkg/sentry/kernel" 24 "gvisor.dev/gvisor/pkg/sentry/kernel/auth" 25 "gvisor.dev/gvisor/pkg/sentry/memmap" 26 "gvisor.dev/gvisor/pkg/sentry/vfs" 27 "gvisor.dev/gvisor/pkg/usermem" 28 ) 29 30 func (fs *filesystem) newKcovFile(ctx context.Context, creds *auth.Credentials) kernfs.Inode { 31 k := &kcovInode{} 32 k.InodeAttrs.Init(ctx, creds, 0, 0, fs.NextIno(), linux.S_IFREG|0600) 33 return k 34 } 35 36 // kcovInode implements kernfs.Inode. 37 // 38 // +stateify savable 39 type kcovInode struct { 40 kernfs.InodeAttrs 41 kernfs.InodeNoopRefCount 42 kernfs.InodeNotAnonymous 43 kernfs.InodeNotDirectory 44 kernfs.InodeNotSymlink 45 kernfs.InodeWatches 46 implStatFS 47 } 48 49 func (i *kcovInode) Open(ctx context.Context, rp *vfs.ResolvingPath, d *kernfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) { 50 k := kernel.KernelFromContext(ctx) 51 if k == nil { 52 panic("KernelFromContext returned nil") 53 } 54 fd := &kcovFD{ 55 inode: i, 56 kcov: k.NewKcov(), 57 } 58 59 if err := fd.vfsfd.Init(fd, opts.Flags, rp.Mount(), d.VFSDentry(), &vfs.FileDescriptionOptions{ 60 DenyPRead: true, 61 DenyPWrite: true, 62 }); err != nil { 63 return nil, err 64 } 65 return &fd.vfsfd, nil 66 } 67 68 // +stateify savable 69 type kcovFD struct { 70 vfs.FileDescriptionDefaultImpl 71 vfs.NoLockFD 72 73 vfsfd vfs.FileDescription 74 inode *kcovInode 75 kcov *kernel.Kcov 76 } 77 78 // Ioctl implements vfs.FileDescriptionImpl.Ioctl. 79 func (fd *kcovFD) Ioctl(ctx context.Context, uio usermem.IO, sysno uintptr, args arch.SyscallArguments) (uintptr, error) { 80 cmd := uint32(args[1].Int()) 81 arg := args[2].Uint64() 82 switch uint32(cmd) { 83 case linux.KCOV_INIT_TRACE: 84 return 0, fd.kcov.InitTrace(arg) 85 case linux.KCOV_ENABLE: 86 return 0, fd.kcov.EnableTrace(ctx, uint8(arg)) 87 case linux.KCOV_DISABLE: 88 if arg != 0 { 89 // This arg is unused; it should be 0. 90 return 0, linuxerr.EINVAL 91 } 92 return 0, fd.kcov.DisableTrace(ctx) 93 default: 94 return 0, linuxerr.ENOTTY 95 } 96 } 97 98 // ConfigureMmap implements vfs.FileDescriptionImpl.ConfigureMmap. 99 func (fd *kcovFD) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error { 100 return fd.kcov.ConfigureMMap(ctx, opts) 101 } 102 103 // Release implements vfs.FileDescriptionImpl.Release. 104 func (fd *kcovFD) Release(ctx context.Context) { 105 // kcov instances have reference counts in Linux, but this seems sufficient 106 // for our purposes. 107 fd.kcov.Clear(ctx) 108 } 109 110 // SetStat implements vfs.FileDescriptionImpl.SetStat. 111 func (fd *kcovFD) SetStat(ctx context.Context, opts vfs.SetStatOptions) error { 112 creds := auth.CredentialsFromContext(ctx) 113 fs := fd.vfsfd.VirtualDentry().Mount().Filesystem() 114 return fd.inode.SetStat(ctx, fs, creds, opts) 115 } 116 117 // Stat implements vfs.FileDescriptionImpl.Stat. 118 func (fd *kcovFD) Stat(ctx context.Context, opts vfs.StatOptions) (linux.Statx, error) { 119 return fd.inode.Stat(ctx, fd.vfsfd.Mount().Filesystem(), opts) 120 }