github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/sentry/syscalls/linux/path.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 linux
    16  
    17  import (
    18  	"github.com/MerlinKodo/gvisor/pkg/abi/linux"
    19  	"github.com/MerlinKodo/gvisor/pkg/errors/linuxerr"
    20  	"github.com/MerlinKodo/gvisor/pkg/fspath"
    21  	"github.com/MerlinKodo/gvisor/pkg/hostarch"
    22  	"github.com/MerlinKodo/gvisor/pkg/sentry/kernel"
    23  	"github.com/MerlinKodo/gvisor/pkg/sentry/vfs"
    24  )
    25  
    26  func copyInPath(t *kernel.Task, addr hostarch.Addr) (fspath.Path, error) {
    27  	pathname, err := t.CopyInString(addr, linux.PATH_MAX)
    28  	if err != nil {
    29  		return fspath.Path{}, err
    30  	}
    31  	return fspath.Parse(pathname), nil
    32  }
    33  
    34  type taskPathOperation struct {
    35  	pop          vfs.PathOperation
    36  	haveStartRef bool
    37  }
    38  
    39  func getTaskPathOperation(t *kernel.Task, dirfd int32, path fspath.Path, shouldAllowEmptyPath shouldAllowEmptyPath, shouldFollowFinalSymlink shouldFollowFinalSymlink) (taskPathOperation, error) {
    40  	root := t.FSContext().RootDirectory()
    41  	start := root
    42  	haveStartRef := false
    43  	if !path.Absolute {
    44  		if !path.HasComponents() && !bool(shouldAllowEmptyPath) {
    45  			root.DecRef(t)
    46  			return taskPathOperation{}, linuxerr.ENOENT
    47  		}
    48  		if dirfd == linux.AT_FDCWD {
    49  			start = t.FSContext().WorkingDirectory()
    50  			haveStartRef = true
    51  		} else {
    52  			dirfile := t.GetFile(dirfd)
    53  			if dirfile == nil {
    54  				root.DecRef(t)
    55  				return taskPathOperation{}, linuxerr.EBADF
    56  			}
    57  			start = dirfile.VirtualDentry()
    58  			start.IncRef()
    59  			haveStartRef = true
    60  			dirfile.DecRef(t)
    61  		}
    62  	}
    63  	return taskPathOperation{
    64  		pop: vfs.PathOperation{
    65  			Root:               root,
    66  			Start:              start,
    67  			Path:               path,
    68  			FollowFinalSymlink: bool(shouldFollowFinalSymlink),
    69  		},
    70  		haveStartRef: haveStartRef,
    71  	}, nil
    72  }
    73  
    74  func (tpop *taskPathOperation) Release(t *kernel.Task) {
    75  	tpop.pop.Root.DecRef(t)
    76  	if tpop.haveStartRef {
    77  		tpop.pop.Start.DecRef(t)
    78  		tpop.haveStartRef = false
    79  	}
    80  }
    81  
    82  type shouldAllowEmptyPath bool
    83  
    84  const (
    85  	disallowEmptyPath shouldAllowEmptyPath = false
    86  	allowEmptyPath    shouldAllowEmptyPath = true
    87  )
    88  
    89  type shouldFollowFinalSymlink bool
    90  
    91  const (
    92  	nofollowFinalSymlink shouldFollowFinalSymlink = false
    93  	followFinalSymlink   shouldFollowFinalSymlink = true
    94  )