github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/fdimport/fdimport.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 fdimport provides the Import function.
    16  package fdimport
    17  
    18  import (
    19  	"fmt"
    20  
    21  	"github.com/nicocha30/gvisor-ligolo/pkg/context"
    22  	"github.com/nicocha30/gvisor-ligolo/pkg/fd"
    23  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/fsimpl/host"
    24  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel"
    25  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel/auth"
    26  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/vfs"
    27  )
    28  
    29  // Import imports a map of FDs into the given FDTable. If console is true,
    30  // sets up TTY for sentry stdin, stdout, and stderr FDs. Used FDs are either
    31  // closed or released. It's safe for the caller to close any remaining files
    32  // upon return.
    33  func Import(ctx context.Context, fdTable *kernel.FDTable, console bool, uid auth.KUID, gid auth.KGID, stdioFDs map[int]*fd.FD) (*host.TTYFileDescription, error) {
    34  	k := kernel.KernelFromContext(ctx)
    35  	if k == nil {
    36  		return nil, fmt.Errorf("cannot find kernel from context")
    37  	}
    38  
    39  	var ttyFile *vfs.FileDescription
    40  	for appFD, hostFD := range stdioFDs {
    41  		var appFile *vfs.FileDescription
    42  
    43  		if console && appFD < 3 {
    44  			// Import the file as a host TTY file.
    45  			if ttyFile == nil {
    46  				var err error
    47  				appFile, err = host.NewFD(ctx, k.HostMount(), hostFD.FD(), &host.NewFDOptions{
    48  					Savable:      true,
    49  					IsTTY:        true,
    50  					VirtualOwner: true,
    51  					UID:          uid,
    52  					GID:          gid,
    53  				})
    54  				if err != nil {
    55  					return nil, err
    56  				}
    57  				defer appFile.DecRef(ctx)
    58  				hostFD.Release() // FD is transfered to host FD.
    59  
    60  				// Remember this in the TTY file, as we will use it for the other stdio
    61  				// FDs.
    62  				ttyFile = appFile
    63  			} else {
    64  				// Re-use the existing TTY file, as all three stdio FDs must point to
    65  				// the same fs.File in order to share TTY state, specifically the
    66  				// foreground process group id.
    67  				appFile = ttyFile
    68  			}
    69  		} else {
    70  			var err error
    71  			appFile, err = host.NewFD(ctx, k.HostMount(), hostFD.FD(), &host.NewFDOptions{
    72  				Savable:      true,
    73  				VirtualOwner: true,
    74  				UID:          uid,
    75  				GID:          gid,
    76  			})
    77  			if err != nil {
    78  				return nil, err
    79  			}
    80  			defer appFile.DecRef(ctx)
    81  			hostFD.Release() // FD is transfered to host FD.
    82  		}
    83  
    84  		if err := fdTable.NewFDAt(ctx, int32(appFD), appFile, kernel.FDFlags{}); err != nil {
    85  			return nil, err
    86  		}
    87  	}
    88  
    89  	if ttyFile == nil {
    90  		return nil, nil
    91  	}
    92  	return ttyFile.Impl().(*host.TTYFileDescription), nil
    93  }