github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/pkg/sentry/control/fs.go (about)

     1  // Copyright 2021 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 control
    16  
    17  import (
    18  	"fmt"
    19  	"io"
    20  	"os"
    21  
    22  	"github.com/metacubex/gvisor/pkg/abi/linux"
    23  	"github.com/metacubex/gvisor/pkg/context"
    24  	"github.com/metacubex/gvisor/pkg/fspath"
    25  	"github.com/metacubex/gvisor/pkg/sentry/kernel"
    26  	"github.com/metacubex/gvisor/pkg/sentry/kernel/auth"
    27  	"github.com/metacubex/gvisor/pkg/sentry/vfs"
    28  	"github.com/metacubex/gvisor/pkg/urpc"
    29  	"github.com/metacubex/gvisor/pkg/usermem"
    30  )
    31  
    32  // CatOpts contains options for the Cat RPC call.
    33  type CatOpts struct {
    34  	// Files are the filesystem paths for the files to cat.
    35  	Files []string `json:"files"`
    36  
    37  	// FilePayload contains the destination for output.
    38  	urpc.FilePayload
    39  }
    40  
    41  // Fs includes fs-related functions.
    42  type Fs struct {
    43  	Kernel *kernel.Kernel
    44  }
    45  
    46  // Cat is a RPC stub which prints out and returns the content of the files.
    47  func (f *Fs) Cat(o *CatOpts, _ *struct{}) error {
    48  	// Create an output stream.
    49  	if len(o.FilePayload.Files) != 1 {
    50  		return ErrInvalidFiles
    51  	}
    52  
    53  	output := o.FilePayload.Files[0]
    54  	for _, file := range o.Files {
    55  		if err := cat(f.Kernel, file, output); err != nil {
    56  			return fmt.Errorf("cannot read from file %s: %v", file, err)
    57  		}
    58  	}
    59  
    60  	return nil
    61  }
    62  
    63  // fdReader provides an io.Reader interface for a vfs.FileDescription.
    64  type fdReader struct {
    65  	ctx context.Context
    66  	fd  *vfs.FileDescription
    67  }
    68  
    69  // Read implements io.Reader.Read.
    70  func (f *fdReader) Read(p []byte) (int, error) {
    71  	n, err := f.fd.Read(f.ctx, usermem.BytesIOSequence(p), vfs.ReadOptions{})
    72  	return int(n), err
    73  }
    74  
    75  func cat(k *kernel.Kernel, path string, output *os.File) error {
    76  	ctx := k.SupervisorContext()
    77  	creds := auth.NewRootCredentials(k.RootUserNamespace())
    78  	mns := k.GlobalInit().Leader().MountNamespace()
    79  	root := mns.Root(ctx)
    80  	defer root.DecRef(ctx)
    81  
    82  	fd, err := k.VFS().OpenAt(ctx, creds, &vfs.PathOperation{
    83  		Root:  root,
    84  		Start: root,
    85  		Path:  fspath.Parse(path),
    86  	}, &vfs.OpenOptions{
    87  		Flags: linux.O_RDONLY,
    88  	})
    89  	if err != nil {
    90  		return fmt.Errorf("failed to open file %s: %v", path, err)
    91  	}
    92  	defer fd.DecRef(ctx)
    93  
    94  	_, err = io.Copy(output, &fdReader{ctx: ctx, fd: fd})
    95  	return err
    96  }