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  }