mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Start cleaning up VFS1.
PiperOrigin-RevId: 486586072
This commit is contained in:
@@ -34,8 +34,6 @@ go_library(
|
||||
"//pkg/fspath",
|
||||
"//pkg/log",
|
||||
"//pkg/sentry/fdimport",
|
||||
"//pkg/sentry/fs",
|
||||
"//pkg/sentry/fs/host",
|
||||
"//pkg/sentry/fs/user",
|
||||
"//pkg/sentry/fsimpl/host",
|
||||
"//pkg/sentry/fsmetric",
|
||||
|
||||
@@ -246,7 +246,7 @@ func (l *Lifecycle) StartContainer(args *StartContainerArgs, _ *uint32) error {
|
||||
for i, appFD := range args.DonatedFDs {
|
||||
fdMap[appFD] = hostFDs[i]
|
||||
}
|
||||
if _, _, err := fdimport.Import(ctx, fdTable, false, args.KUID, args.KGID, fdMap); err != nil {
|
||||
if _, err := fdimport.Import(ctx, fdTable, false, args.KUID, args.KGID, fdMap); err != nil {
|
||||
return fmt.Errorf("error importing host files: %w", err)
|
||||
}
|
||||
initArgs.FDTable = fdTable
|
||||
@@ -258,9 +258,9 @@ func (l *Lifecycle) StartContainer(args *StartContainerArgs, _ *uint32) error {
|
||||
l.mu.RUnlock()
|
||||
return fmt.Errorf("mount namespace is nil for %s", initArgs.ContainerID)
|
||||
}
|
||||
initArgs.MountNamespaceVFS2 = mntns
|
||||
initArgs.MountNamespace = mntns
|
||||
l.mu.RUnlock()
|
||||
initArgs.MountNamespaceVFS2.IncRef()
|
||||
initArgs.MountNamespace.IncRef()
|
||||
|
||||
if args.ResolveBinaryPath {
|
||||
resolved, err := user.ResolveExecutablePath(ctx, &initArgs)
|
||||
@@ -271,7 +271,7 @@ func (l *Lifecycle) StartContainer(args *StartContainerArgs, _ *uint32) error {
|
||||
}
|
||||
|
||||
if args.ResolveHome {
|
||||
envVars, err := user.MaybeAddExecUserHomeVFS2(ctx, initArgs.MountNamespaceVFS2, creds.RealKUID, initArgs.Envv)
|
||||
envVars, err := user.MaybeAddExecUserHome(ctx, initArgs.MountNamespace, creds.RealKUID, initArgs.Envv)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get user home dir: %w", err)
|
||||
}
|
||||
|
||||
+20
-48
@@ -26,10 +26,8 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/fd"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fdimport"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs/host"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs/user"
|
||||
hostvfs2 "gvisor.dev/gvisor/pkg/sentry/fsimpl/host"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fsimpl/host"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
|
||||
@@ -63,13 +61,7 @@ type ExecArgs struct {
|
||||
// A reference on MountNamespace must be held for the lifetime of the
|
||||
// ExecArgs. If MountNamespace is nil, it will default to the init
|
||||
// process's MountNamespace.
|
||||
MountNamespace *fs.MountNamespace
|
||||
|
||||
// MountNamespaceVFS2 is the mount namespace to execute the new process in.
|
||||
// A reference on MountNamespace must be held for the lifetime of the
|
||||
// ExecArgs. If MountNamespace is nil, it will default to the init
|
||||
// process's MountNamespace.
|
||||
MountNamespaceVFS2 *vfs.MountNamespace
|
||||
MountNamespace *vfs.MountNamespace
|
||||
|
||||
// WorkingDirectory defines the working directory for the new process.
|
||||
WorkingDirectory string `json:"wd"`
|
||||
@@ -119,7 +111,7 @@ func (args ExecArgs) String() string {
|
||||
|
||||
// Exec runs a new task.
|
||||
func (proc *Proc) Exec(args *ExecArgs, waitStatus *uint32) error {
|
||||
newTG, _, _, _, err := proc.execAsync(args)
|
||||
newTG, _, _, err := proc.execAsync(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -132,14 +124,14 @@ func (proc *Proc) Exec(args *ExecArgs, waitStatus *uint32) error {
|
||||
|
||||
// ExecAsync runs a new task, but doesn't wait for it to finish. It is defined
|
||||
// as a function rather than a method to avoid exposing execAsync as an RPC.
|
||||
func ExecAsync(proc *Proc, args *ExecArgs) (*kernel.ThreadGroup, kernel.ThreadID, *host.TTYFileOperations, *hostvfs2.TTYFileDescription, error) {
|
||||
func ExecAsync(proc *Proc, args *ExecArgs) (*kernel.ThreadGroup, kernel.ThreadID, *host.TTYFileDescription, error) {
|
||||
return proc.execAsync(args)
|
||||
}
|
||||
|
||||
// execAsync runs a new task, but doesn't wait for it to finish. It returns the
|
||||
// newly created thread group and its PID. If the stdio FDs are TTYs, then a
|
||||
// TTYFileOperations that wraps the TTY is also returned.
|
||||
func (proc *Proc) execAsync(args *ExecArgs) (*kernel.ThreadGroup, kernel.ThreadID, *host.TTYFileOperations, *hostvfs2.TTYFileDescription, error) {
|
||||
func (proc *Proc) execAsync(args *ExecArgs) (*kernel.ThreadGroup, kernel.ThreadID, *host.TTYFileDescription, error) {
|
||||
// Import file descriptors.
|
||||
fdTable := proc.Kernel.NewFDTable()
|
||||
|
||||
@@ -164,7 +156,6 @@ func (proc *Proc) execAsync(args *ExecArgs) (*kernel.ThreadGroup, kernel.ThreadI
|
||||
Envv: args.Envv,
|
||||
WorkingDirectory: args.WorkingDirectory,
|
||||
MountNamespace: args.MountNamespace,
|
||||
MountNamespaceVFS2: args.MountNamespaceVFS2,
|
||||
Credentials: creds,
|
||||
FDTable: fdTable,
|
||||
Umask: 0022,
|
||||
@@ -177,46 +168,30 @@ func (proc *Proc) execAsync(args *ExecArgs) (*kernel.ThreadGroup, kernel.ThreadI
|
||||
PIDNamespace: pidns,
|
||||
}
|
||||
if initArgs.MountNamespace != nil {
|
||||
// initArgs must hold a reference on MountNamespace, which will
|
||||
// be donated to the new process in CreateProcess.
|
||||
initArgs.MountNamespace.IncRef()
|
||||
}
|
||||
if initArgs.MountNamespaceVFS2 != nil {
|
||||
// initArgs must hold a reference on MountNamespaceVFS2, which will
|
||||
// be donated to the new process in CreateProcess.
|
||||
initArgs.MountNamespaceVFS2.IncRef()
|
||||
initArgs.MountNamespace.IncRef()
|
||||
}
|
||||
ctx := initArgs.NewContext(proc.Kernel)
|
||||
defer fdTable.DecRef(ctx)
|
||||
|
||||
if kernel.VFS2Enabled {
|
||||
// Get the full path to the filename from the PATH env variable.
|
||||
if initArgs.MountNamespaceVFS2 == nil {
|
||||
// Set initArgs so that 'ctx' returns the namespace.
|
||||
//
|
||||
// Add a reference to the namespace, which is transferred to the new process.
|
||||
initArgs.MountNamespaceVFS2 = proc.Kernel.GlobalInit().Leader().MountNamespaceVFS2()
|
||||
initArgs.MountNamespaceVFS2.IncRef()
|
||||
}
|
||||
} else {
|
||||
if initArgs.MountNamespace == nil {
|
||||
// Set initArgs so that 'ctx' returns the namespace.
|
||||
initArgs.MountNamespace = proc.Kernel.GlobalInit().Leader().MountNamespace()
|
||||
|
||||
// initArgs must hold a reference on MountNamespace, which will
|
||||
// be donated to the new process in CreateProcess.
|
||||
initArgs.MountNamespace.IncRef()
|
||||
}
|
||||
// Get the full path to the filename from the PATH env variable.
|
||||
if initArgs.MountNamespace == nil {
|
||||
// Set initArgs so that 'ctx' returns the namespace.
|
||||
//
|
||||
// Add a reference to the namespace, which is transferred to the new process.
|
||||
initArgs.MountNamespace = proc.Kernel.GlobalInit().Leader().MountNamespaceVFS2()
|
||||
initArgs.MountNamespace.IncRef()
|
||||
}
|
||||
resolved, err := user.ResolveExecutablePath(ctx, &initArgs)
|
||||
if err != nil {
|
||||
return nil, 0, nil, nil, err
|
||||
return nil, 0, nil, err
|
||||
}
|
||||
initArgs.Filename = resolved
|
||||
|
||||
fds, err := fd.NewFromFiles(args.Files)
|
||||
if err != nil {
|
||||
return nil, 0, nil, nil, fmt.Errorf("duplicating payload files: %w", err)
|
||||
return nil, 0, nil, fmt.Errorf("duplicating payload files: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
for _, fd := range fds {
|
||||
@@ -227,28 +202,25 @@ func (proc *Proc) execAsync(args *ExecArgs) (*kernel.ThreadGroup, kernel.ThreadI
|
||||
for appFD, hostFD := range fds {
|
||||
fdMap[appFD] = hostFD
|
||||
}
|
||||
ttyFile, ttyFileVFS2, err := fdimport.Import(ctx, fdTable, args.StdioIsPty, args.KUID, args.KGID, fdMap)
|
||||
ttyFile, err := fdimport.Import(ctx, fdTable, args.StdioIsPty, args.KUID, args.KGID, fdMap)
|
||||
if err != nil {
|
||||
return nil, 0, nil, nil, err
|
||||
return nil, 0, nil, err
|
||||
}
|
||||
|
||||
tg, tid, err := proc.Kernel.CreateProcess(initArgs)
|
||||
if err != nil {
|
||||
return nil, 0, nil, nil, err
|
||||
return nil, 0, nil, err
|
||||
}
|
||||
|
||||
// Set the foreground process group on the TTY before starting the process.
|
||||
switch {
|
||||
case ttyFile != nil:
|
||||
if ttyFile != nil {
|
||||
ttyFile.InitForegroundProcessGroup(tg.ProcessGroup())
|
||||
case ttyFileVFS2 != nil:
|
||||
ttyFileVFS2.InitForegroundProcessGroup(tg.ProcessGroup())
|
||||
}
|
||||
|
||||
// Start the newly created process.
|
||||
proc.Kernel.StartProcess(tg)
|
||||
|
||||
return tg, tid, ttyFile, ttyFileVFS2, nil
|
||||
return tg, tid, ttyFile, nil
|
||||
}
|
||||
|
||||
// PsArgs is the set of arguments to ps.
|
||||
|
||||
@@ -11,8 +11,6 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/context",
|
||||
"//pkg/fd",
|
||||
"//pkg/sentry/fs",
|
||||
"//pkg/sentry/fs/host",
|
||||
"//pkg/sentry/fsimpl/host",
|
||||
"//pkg/sentry/kernel",
|
||||
"//pkg/sentry/kernel/auth",
|
||||
|
||||
@@ -20,9 +20,7 @@ import (
|
||||
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/fd"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs/host"
|
||||
hostvfs2 "gvisor.dev/gvisor/pkg/sentry/fsimpl/host"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fsimpl/host"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
@@ -32,65 +30,7 @@ import (
|
||||
// sets up TTY for sentry stdin, stdout, and stderr FDs. Used FDs are either
|
||||
// closed or released. It's safe for the caller to close any remaining files
|
||||
// upon return.
|
||||
func Import(ctx context.Context, fdTable *kernel.FDTable, console bool, uid auth.KUID, gid auth.KGID, fds map[int]*fd.FD) (*host.TTYFileOperations, *hostvfs2.TTYFileDescription, error) {
|
||||
if kernel.VFS2Enabled {
|
||||
ttyFile, err := importVFS2(ctx, fdTable, console, uid, gid, fds)
|
||||
return nil, ttyFile, err
|
||||
}
|
||||
ttyFile, err := importFS(ctx, fdTable, console, fds)
|
||||
return ttyFile, nil, err
|
||||
}
|
||||
|
||||
func importFS(ctx context.Context, fdTable *kernel.FDTable, console bool, fds map[int]*fd.FD) (*host.TTYFileOperations, error) {
|
||||
var ttyFile *fs.File
|
||||
for appFD, hostFD := range fds {
|
||||
var appFile *fs.File
|
||||
|
||||
if console && appFD < 3 {
|
||||
// Import the file as a host TTY file.
|
||||
if ttyFile == nil {
|
||||
var err error
|
||||
appFile, err = host.ImportFile(ctx, hostFD.FD(), true /* isTTY */)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer appFile.DecRef(ctx)
|
||||
_ = hostFD.Close() // FD is dup'd i ImportFile.
|
||||
|
||||
// Remember this in the TTY file, as we will
|
||||
// use it for the other stdio FDs.
|
||||
ttyFile = appFile
|
||||
} else {
|
||||
// Re-use the existing TTY file, as all three
|
||||
// stdio FDs must point to the same fs.File in
|
||||
// order to share TTY state, specifically the
|
||||
// foreground process group id.
|
||||
appFile = ttyFile
|
||||
}
|
||||
} else {
|
||||
// Import the file as a regular host file.
|
||||
var err error
|
||||
appFile, err = host.ImportFile(ctx, hostFD.FD(), false /* isTTY */)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer appFile.DecRef(ctx)
|
||||
_ = hostFD.Close() // FD is dup'd i ImportFile.
|
||||
}
|
||||
|
||||
// Add the file to the FD map.
|
||||
if err := fdTable.NewFDAt(ctx, int32(appFD), appFile, kernel.FDFlags{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if ttyFile == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return ttyFile.FileOperations.(*host.TTYFileOperations), nil
|
||||
}
|
||||
|
||||
func importVFS2(ctx context.Context, fdTable *kernel.FDTable, console bool, uid auth.KUID, gid auth.KGID, stdioFDs map[int]*fd.FD) (*hostvfs2.TTYFileDescription, error) {
|
||||
func Import(ctx context.Context, fdTable *kernel.FDTable, console bool, uid auth.KUID, gid auth.KGID, stdioFDs map[int]*fd.FD) (*host.TTYFileDescription, error) {
|
||||
k := kernel.KernelFromContext(ctx)
|
||||
if k == nil {
|
||||
return nil, fmt.Errorf("cannot find kernel from context")
|
||||
@@ -104,7 +44,7 @@ func importVFS2(ctx context.Context, fdTable *kernel.FDTable, console bool, uid
|
||||
// Import the file as a host TTY file.
|
||||
if ttyFile == nil {
|
||||
var err error
|
||||
appFile, err = hostvfs2.NewFD(ctx, k.HostMount(), hostFD.FD(), &hostvfs2.NewFDOptions{
|
||||
appFile, err = host.NewFD(ctx, k.HostMount(), hostFD.FD(), &host.NewFDOptions{
|
||||
Savable: true,
|
||||
IsTTY: true,
|
||||
VirtualOwner: true,
|
||||
@@ -128,7 +68,7 @@ func importVFS2(ctx context.Context, fdTable *kernel.FDTable, console bool, uid
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
appFile, err = hostvfs2.NewFD(ctx, k.HostMount(), hostFD.FD(), &hostvfs2.NewFDOptions{
|
||||
appFile, err = host.NewFD(ctx, k.HostMount(), hostFD.FD(), &host.NewFDOptions{
|
||||
Savable: true,
|
||||
VirtualOwner: true,
|
||||
UID: uid,
|
||||
@@ -149,5 +89,5 @@ func importVFS2(ctx context.Context, fdTable *kernel.FDTable, console bool, uid
|
||||
if ttyFile == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return ttyFile.Impl().(*hostvfs2.TTYFileDescription), nil
|
||||
return ttyFile.Impl().(*host.TTYFileDescription), nil
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ go_library(
|
||||
"//pkg/errors/linuxerr",
|
||||
"//pkg/fspath",
|
||||
"//pkg/log",
|
||||
"//pkg/sentry/fs",
|
||||
"//pkg/sentry/kernel",
|
||||
"//pkg/sentry/kernel/auth",
|
||||
"//pkg/sentry/vfs",
|
||||
@@ -31,10 +30,11 @@ go_test(
|
||||
deps = [
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/context",
|
||||
"//pkg/sentry/fs",
|
||||
"//pkg/sentry/fs/tmpfs",
|
||||
"//pkg/fspath",
|
||||
"//pkg/sentry/fsimpl/tmpfs",
|
||||
"//pkg/sentry/kernel/auth",
|
||||
"//pkg/sentry/kernel/contexttest",
|
||||
"//pkg/sentry/vfs",
|
||||
"//pkg/usermem",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/fspath"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
@@ -66,65 +65,14 @@ func ResolveExecutablePath(ctx context.Context, args *kernel.CreateProcessArgs)
|
||||
|
||||
// Otherwise, We must lookup the name in the paths.
|
||||
paths := getPath(args.Envv)
|
||||
if kernel.VFS2Enabled {
|
||||
f, err := resolveVFS2(ctx, args.Credentials, args.MountNamespaceVFS2, paths, name)
|
||||
if err != nil {
|
||||
return "", &ExecutableResolveError{fmt.Errorf("error finding executable %q in PATH %v: %v", name, paths, err)}
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
f, err := resolve(ctx, args.MountNamespace, paths, name)
|
||||
f, err := resolve(ctx, args.Credentials, args.MountNamespace, paths, name)
|
||||
if err != nil {
|
||||
return "", &ExecutableResolveError{fmt.Errorf("error finding executable %q in PATH %v: %v", name, paths, err)}
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func resolve(ctx context.Context, mns *fs.MountNamespace, paths []string, name string) (string, error) {
|
||||
root := fs.RootFromContext(ctx)
|
||||
if root == nil {
|
||||
// Caller has no root. Don't bother traversing anything.
|
||||
return "", linuxerr.ENOENT
|
||||
}
|
||||
defer root.DecRef(ctx)
|
||||
for _, p := range paths {
|
||||
if !path.IsAbs(p) {
|
||||
// Relative paths aren't safe, no one should be using them.
|
||||
log.Warningf("Skipping relative path %q in $PATH", p)
|
||||
continue
|
||||
}
|
||||
|
||||
binPath := path.Join(p, name)
|
||||
traversals := uint(linux.MaxSymlinkTraversals)
|
||||
d, err := mns.FindInode(ctx, root, nil, binPath, &traversals)
|
||||
if linuxerr.Equals(linuxerr.ENOENT, err) || linuxerr.Equals(linuxerr.EACCES, err) {
|
||||
// Didn't find it here.
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer d.DecRef(ctx)
|
||||
|
||||
// Check that it is a regular file.
|
||||
if !fs.IsRegular(d.Inode.StableAttr) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check whether we can read and execute the found file.
|
||||
if err := d.Inode.CheckPermission(ctx, fs.PermMask{Read: true, Execute: true}); err != nil {
|
||||
log.Infof("Found executable at %q, but user cannot execute it: %v", binPath, err)
|
||||
continue
|
||||
}
|
||||
return path.Join("/", p, name), nil
|
||||
}
|
||||
|
||||
// Couldn't find it.
|
||||
return "", linuxerr.ENOENT
|
||||
}
|
||||
|
||||
func resolveVFS2(ctx context.Context, creds *auth.Credentials, mns *vfs.MountNamespace, paths []string, name string) (string, error) {
|
||||
func resolve(ctx context.Context, creds *auth.Credentials, mns *vfs.MountNamespace, paths []string, name string) (string, error) {
|
||||
root := mns.Root()
|
||||
root.IncRef()
|
||||
defer root.DecRef(ctx)
|
||||
|
||||
+14
-90
@@ -26,82 +26,22 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/fspath"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
type fileReader struct {
|
||||
// Ctx is the context for the file reader.
|
||||
Ctx context.Context
|
||||
|
||||
// File is the file to read from.
|
||||
File *fs.File
|
||||
}
|
||||
|
||||
// Read implements io.Reader.Read.
|
||||
func (r *fileReader) Read(buf []byte) (int, error) {
|
||||
n, err := r.File.Readv(r.Ctx, usermem.BytesIOSequence(buf))
|
||||
return int(n), err
|
||||
}
|
||||
|
||||
// getExecUserHome returns the home directory of the executing user read from
|
||||
// /etc/passwd as read from the container filesystem.
|
||||
func getExecUserHome(ctx context.Context, rootMns *fs.MountNamespace, uid auth.KUID) (string, error) {
|
||||
// The default user home directory to return if no user matching the user
|
||||
// if found in the /etc/passwd found in the image.
|
||||
const defaultHome = "/"
|
||||
|
||||
// Open the /etc/passwd file from the dirent via the root mount namespace.
|
||||
mnsRoot := rootMns.Root()
|
||||
maxTraversals := uint(linux.MaxSymlinkTraversals)
|
||||
dirent, err := rootMns.FindInode(ctx, mnsRoot, nil, "/etc/passwd", &maxTraversals)
|
||||
if err != nil {
|
||||
// NOTE: Ignore errors opening the passwd file. If the passwd file
|
||||
// doesn't exist we will return the default home directory.
|
||||
return defaultHome, nil
|
||||
}
|
||||
defer dirent.DecRef(ctx)
|
||||
|
||||
// Check read permissions on the file.
|
||||
if err := dirent.Inode.CheckPermission(ctx, fs.PermMask{Read: true}); err != nil {
|
||||
// NOTE: Ignore permissions errors here and return default root dir.
|
||||
return defaultHome, nil
|
||||
}
|
||||
|
||||
// Only open regular files. We don't open other files like named pipes as
|
||||
// they may block and might present some attack surface to the container.
|
||||
// Note that runc does not seem to do this kind of checking.
|
||||
if !fs.IsRegular(dirent.Inode.StableAttr) {
|
||||
return defaultHome, nil
|
||||
}
|
||||
|
||||
f, err := dirent.Inode.GetFile(ctx, dirent, fs.FileFlags{Read: true, Directory: false})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer f.DecRef(ctx)
|
||||
|
||||
r := &fileReader{
|
||||
Ctx: ctx,
|
||||
File: f,
|
||||
}
|
||||
|
||||
return findHomeInPasswd(uint32(uid), r, defaultHome)
|
||||
}
|
||||
|
||||
type fileReaderVFS2 struct {
|
||||
ctx context.Context
|
||||
fd *vfs.FileDescription
|
||||
}
|
||||
|
||||
func (r *fileReaderVFS2) Read(buf []byte) (int, error) {
|
||||
func (r *fileReader) Read(buf []byte) (int, error) {
|
||||
n, err := r.fd.Read(r.ctx, usermem.BytesIOSequence(buf), vfs.ReadOptions{})
|
||||
return int(n), err
|
||||
}
|
||||
|
||||
func getExecUserHomeVFS2(ctx context.Context, mns *vfs.MountNamespace, uid auth.KUID) (string, error) {
|
||||
func getExecUserHome(ctx context.Context, mns *vfs.MountNamespace, uid auth.KUID) (string, error) {
|
||||
const defaultHome = "/"
|
||||
|
||||
root := mns.Root()
|
||||
@@ -116,17 +56,24 @@ func getExecUserHomeVFS2(ctx context.Context, mns *vfs.MountNamespace, uid auth.
|
||||
Path: fspath.Parse("/etc/passwd"),
|
||||
}
|
||||
|
||||
stat, err := root.Mount().Filesystem().VirtualFilesystem().StatAt(ctx, creds, target, &vfs.StatOptions{Mask: linux.STATX_TYPE})
|
||||
if err != nil {
|
||||
return defaultHome, nil
|
||||
}
|
||||
if stat.Mask&linux.STATX_TYPE == 0 || stat.Mode&linux.FileTypeMask != linux.ModeRegular {
|
||||
return defaultHome, nil
|
||||
}
|
||||
|
||||
opts := &vfs.OpenOptions{
|
||||
Flags: linux.O_RDONLY,
|
||||
}
|
||||
|
||||
fd, err := root.Mount().Filesystem().VirtualFilesystem().OpenAt(ctx, creds, target, opts)
|
||||
if err != nil {
|
||||
return defaultHome, nil
|
||||
}
|
||||
defer fd.DecRef(ctx)
|
||||
|
||||
r := &fileReaderVFS2{
|
||||
r := &fileReader{
|
||||
ctx: ctx,
|
||||
fd: fd,
|
||||
}
|
||||
@@ -139,33 +86,10 @@ func getExecUserHomeVFS2(ctx context.Context, mns *vfs.MountNamespace, uid auth.
|
||||
return homeDir, nil
|
||||
}
|
||||
|
||||
// MaybeAddExecUserHome returns a new slice with the HOME enviroment variable
|
||||
// set if the slice does not already contain it, otherwise it returns the
|
||||
// original slice unmodified.
|
||||
func MaybeAddExecUserHome(ctx context.Context, mns *fs.MountNamespace, uid auth.KUID, envv []string) ([]string, error) {
|
||||
// Check if the envv already contains HOME.
|
||||
for _, env := range envv {
|
||||
if strings.HasPrefix(env, "HOME=") {
|
||||
// We have it. Return the original slice unmodified.
|
||||
return envv, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Read /etc/passwd for the user's HOME directory and set the HOME
|
||||
// environment variable as required by POSIX if it is not overridden by
|
||||
// the user.
|
||||
homeDir, err := getExecUserHome(ctx, mns, uid)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading exec user: %v", err)
|
||||
}
|
||||
|
||||
return append(envv, "HOME="+homeDir), nil
|
||||
}
|
||||
|
||||
// MaybeAddExecUserHomeVFS2 returns a new slice with the HOME enviroment
|
||||
// MaybeAddExecUserHome returns a new slice with the HOME environment
|
||||
// variable set if the slice does not already contain it, otherwise it returns
|
||||
// the original slice unmodified.
|
||||
func MaybeAddExecUserHomeVFS2(ctx context.Context, vmns *vfs.MountNamespace, uid auth.KUID, envv []string) ([]string, error) {
|
||||
func MaybeAddExecUserHome(ctx context.Context, vmns *vfs.MountNamespace, uid auth.KUID, envv []string) ([]string, error) {
|
||||
// Check if the envv already contains HOME.
|
||||
for _, env := range envv {
|
||||
if strings.HasPrefix(env, "HOME=") {
|
||||
@@ -177,7 +101,7 @@ func MaybeAddExecUserHomeVFS2(ctx context.Context, vmns *vfs.MountNamespace, uid
|
||||
// Read /etc/passwd for the user's HOME directory and set the HOME
|
||||
// environment variable as required by POSIX if it is not overridden by
|
||||
// the user.
|
||||
homeDir, err := getExecUserHomeVFS2(ctx, vmns, uid)
|
||||
homeDir, err := getExecUserHome(ctx, vmns, uid)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading exec user: %v", err)
|
||||
}
|
||||
|
||||
@@ -21,43 +21,50 @@ import (
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs/tmpfs"
|
||||
"gvisor.dev/gvisor/pkg/fspath"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fsimpl/tmpfs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/contexttest"
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
// createEtcPasswd creates /etc/passwd with the given contents and mode. If
|
||||
// mode is empty, then no file will be created. If mode is not a regular file
|
||||
// mode, then contents is ignored.
|
||||
func createEtcPasswd(ctx context.Context, root *fs.Dirent, contents string, mode linux.FileMode) error {
|
||||
if err := root.CreateDirectory(ctx, root, "etc", fs.FilePermsFromMode(0755)); err != nil {
|
||||
return err
|
||||
func createEtcPasswd(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials, root vfs.VirtualDentry, contents string, mode linux.FileMode) error {
|
||||
pop := vfs.PathOperation{
|
||||
Root: root,
|
||||
Start: root,
|
||||
Path: fspath.Parse("etc"),
|
||||
}
|
||||
etc, err := root.Walk(ctx, root, "etc")
|
||||
if err != nil {
|
||||
return err
|
||||
if err := vfsObj.MkdirAt(ctx, creds, &pop, &vfs.MkdirOptions{
|
||||
Mode: 0755,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to create directory etc: %v", err)
|
||||
}
|
||||
|
||||
pop = vfs.PathOperation{
|
||||
Root: root,
|
||||
Start: root,
|
||||
Path: fspath.Parse("etc/passwd"),
|
||||
}
|
||||
defer etc.DecRef(ctx)
|
||||
switch mode.FileType() {
|
||||
case 0:
|
||||
// Don't create anything.
|
||||
return nil
|
||||
case linux.S_IFREG:
|
||||
passwd, err := etc.Create(ctx, root, "passwd", fs.FileFlags{Write: true}, fs.FilePermsFromMode(mode))
|
||||
fd, err := vfsObj.OpenAt(ctx, creds, &pop, &vfs.OpenOptions{Flags: linux.O_CREAT | linux.O_WRONLY, Mode: mode})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer passwd.DecRef(ctx)
|
||||
if _, err := passwd.Writev(ctx, usermem.BytesIOSequence([]byte(contents))); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
defer fd.DecRef(ctx)
|
||||
_, err = fd.Write(ctx, usermem.BytesIOSequence([]byte(contents)), vfs.WriteOptions{})
|
||||
return err
|
||||
case linux.S_IFDIR:
|
||||
return etc.CreateDirectory(ctx, root, "passwd", fs.FilePermsFromMode(mode))
|
||||
return vfsObj.MkdirAt(ctx, creds, &pop, &vfs.MkdirOptions{Mode: mode})
|
||||
case linux.S_IFIFO:
|
||||
return etc.CreateFifo(ctx, root, "passwd", fs.FilePermsFromMode(mode))
|
||||
return vfsObj.MknodAt(ctx, creds, &pop, &vfs.MknodOptions{Mode: mode})
|
||||
default:
|
||||
return fmt.Errorf("unknown file type %x", mode.FileType())
|
||||
}
|
||||
@@ -103,22 +110,26 @@ func TestGetExecUserHome(t *testing.T) {
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
ctx := contexttest.Context(t)
|
||||
msrc := fs.NewPseudoMountSource(ctx)
|
||||
rootInode, err := tmpfs.NewDir(ctx, nil, fs.RootOwner, fs.FilePermsFromMode(0777), msrc, nil /* parent */)
|
||||
if err != nil {
|
||||
t.Fatalf("tmpfs.NewDir failed: %v", err)
|
||||
}
|
||||
creds := auth.CredentialsFromContext(ctx)
|
||||
|
||||
mns, err := fs.NewMountNamespace(ctx, rootInode)
|
||||
// Create VFS.
|
||||
vfsObj := vfs.VirtualFilesystem{}
|
||||
if err := vfsObj.Init(ctx); err != nil {
|
||||
t.Fatalf("VFS init: %v", err)
|
||||
}
|
||||
vfsObj.MustRegisterFilesystemType("tmpfs", tmpfs.FilesystemType{}, &vfs.RegisterFilesystemTypeOptions{
|
||||
AllowUserMount: true,
|
||||
})
|
||||
mns, err := vfsObj.NewMountNamespace(ctx, creds, "", "tmpfs", &vfs.MountOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("NewMountNamespace failed: %v", err)
|
||||
t.Fatalf("failed to create tmpfs root mount: %v", err)
|
||||
}
|
||||
defer mns.DecRef(ctx)
|
||||
root := mns.Root()
|
||||
root.IncRef()
|
||||
defer root.DecRef(ctx)
|
||||
ctx = fs.WithRoot(ctx, root)
|
||||
|
||||
if err := createEtcPasswd(ctx, root, tc.passwdContents, tc.passwdMode); err != nil {
|
||||
if err := createEtcPasswd(ctx, &vfsObj, creds, root, tc.passwdContents, tc.passwdMode); err != nil {
|
||||
t.Fatalf("createEtcPasswd failed: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,6 @@ func Boot() (*kernel.Kernel, error) {
|
||||
return nil, fmt.Errorf("creating platform: %v", err)
|
||||
}
|
||||
|
||||
kernel.VFS2Enabled = true
|
||||
k := &kernel.Kernel{
|
||||
Platform: plat,
|
||||
}
|
||||
@@ -142,8 +141,8 @@ func CreateTask(ctx context.Context, name string, tc *kernel.ThreadGroup, mntns
|
||||
UTSNamespace: kernel.UTSNamespaceFromContext(ctx),
|
||||
IPCNamespace: kernel.IPCNamespaceFromContext(ctx),
|
||||
AbstractSocketNamespace: kernel.NewAbstractSocketNamespace(),
|
||||
MountNamespaceVFS2: mntns,
|
||||
FSContext: kernel.NewFSContextVFS2(root, cwd, 0022),
|
||||
MountNamespace: mntns,
|
||||
FSContext: kernel.NewFSContext(root, cwd, 0022),
|
||||
FDTable: k.NewFDTable(),
|
||||
UserCounters: k.GetUserCounters(creds.RealKUID),
|
||||
}
|
||||
|
||||
@@ -54,21 +54,8 @@ type FSContext struct {
|
||||
umask uint
|
||||
}
|
||||
|
||||
// newFSContext returns a new filesystem context.
|
||||
func newFSContext(root, cwd *fs.Dirent, umask uint) *FSContext {
|
||||
root.IncRef()
|
||||
cwd.IncRef()
|
||||
f := FSContext{
|
||||
root: root,
|
||||
cwd: cwd,
|
||||
umask: umask,
|
||||
}
|
||||
f.InitRefs()
|
||||
return &f
|
||||
}
|
||||
|
||||
// NewFSContextVFS2 returns a new filesystem context.
|
||||
func NewFSContextVFS2(root, cwd vfs.VirtualDentry, umask uint) *FSContext {
|
||||
// NewFSContext returns a new filesystem context.
|
||||
func NewFSContext(root, cwd vfs.VirtualDentry, umask uint) *FSContext {
|
||||
root.IncRef()
|
||||
cwd.IncRef()
|
||||
f := FSContext{
|
||||
@@ -95,17 +82,10 @@ func (f *FSContext) DecRef(ctx context.Context) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
|
||||
if VFS2Enabled {
|
||||
f.rootVFS2.DecRef(ctx)
|
||||
f.rootVFS2 = vfs.VirtualDentry{}
|
||||
f.cwdVFS2.DecRef(ctx)
|
||||
f.cwdVFS2 = vfs.VirtualDentry{}
|
||||
} else {
|
||||
f.root.DecRef(ctx)
|
||||
f.root = nil
|
||||
f.cwd.DecRef(ctx)
|
||||
f.cwd = nil
|
||||
}
|
||||
f.rootVFS2.DecRef(ctx)
|
||||
f.rootVFS2 = vfs.VirtualDentry{}
|
||||
f.cwdVFS2.DecRef(ctx)
|
||||
f.cwdVFS2 = vfs.VirtualDentry{}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -116,19 +96,11 @@ func (f *FSContext) Fork() *FSContext {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
|
||||
if VFS2Enabled {
|
||||
if !f.cwdVFS2.Ok() {
|
||||
panic("FSContext.Fork() called after destroy")
|
||||
}
|
||||
f.cwdVFS2.IncRef()
|
||||
f.rootVFS2.IncRef()
|
||||
} else {
|
||||
if f.cwd == nil {
|
||||
panic("FSContext.Fork() called after destroy")
|
||||
}
|
||||
f.cwd.IncRef()
|
||||
f.root.IncRef()
|
||||
if !f.cwdVFS2.Ok() {
|
||||
panic("FSContext.Fork() called after destroy")
|
||||
}
|
||||
f.cwdVFS2.IncRef()
|
||||
f.rootVFS2.IncRef()
|
||||
|
||||
ctx := &FSContext{
|
||||
cwd: f.cwd,
|
||||
|
||||
+99
-223
@@ -49,7 +49,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/refs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
oldtimerfd "gvisor.dev/gvisor/pkg/sentry/fs/timerfd"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fsbridge"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fsimpl/pipefs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fsimpl/sockfs"
|
||||
@@ -79,12 +78,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
)
|
||||
|
||||
// VFS2Enabled is set to true when VFS2 is enabled. Added as a global to allow
|
||||
// easy access everywhere.
|
||||
//
|
||||
// TODO(gvisor.dev/issue/1624): Remove when VFS1 is no longer used.
|
||||
var VFS2Enabled = false
|
||||
|
||||
// LISAFSEnabled is set to true when lisafs protocol is enabled. Added as a
|
||||
// global to allow easy access everywhere.
|
||||
//
|
||||
@@ -442,44 +435,42 @@ func (k *Kernel) Init(args InitKernelArgs) error {
|
||||
k.YAMAPtraceScope = atomicbitops.FromInt32(linux.YAMA_SCOPE_RELATIONAL)
|
||||
k.userCountersMap = make(map[auth.KUID]*userCounters)
|
||||
|
||||
if VFS2Enabled {
|
||||
ctx := k.SupervisorContext()
|
||||
if err := k.vfs.Init(ctx); err != nil {
|
||||
return fmt.Errorf("failed to initialize VFS: %v", err)
|
||||
}
|
||||
|
||||
err := k.rootIPCNamespace.InitPosixQueues(ctx, &k.vfs, auth.CredentialsFromContext(ctx))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create mqfs filesystem: %v", err)
|
||||
}
|
||||
|
||||
pipeFilesystem, err := pipefs.NewFilesystem(&k.vfs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create pipefs filesystem: %v", err)
|
||||
}
|
||||
defer pipeFilesystem.DecRef(ctx)
|
||||
pipeMount := k.vfs.NewDisconnectedMount(pipeFilesystem, nil, &vfs.MountOptions{})
|
||||
k.pipeMount = pipeMount
|
||||
|
||||
tmpfsFilesystem, tmpfsRoot, err := tmpfs.NewFilesystem(ctx, &k.vfs, auth.NewRootCredentials(k.rootUserNamespace))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create tmpfs filesystem: %v", err)
|
||||
}
|
||||
defer tmpfsFilesystem.DecRef(ctx)
|
||||
defer tmpfsRoot.DecRef(ctx)
|
||||
k.shmMount = k.vfs.NewDisconnectedMount(tmpfsFilesystem, tmpfsRoot, &vfs.MountOptions{})
|
||||
|
||||
socketFilesystem, err := sockfs.NewFilesystem(&k.vfs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create sockfs filesystem: %v", err)
|
||||
}
|
||||
defer socketFilesystem.DecRef(ctx)
|
||||
k.socketMount = k.vfs.NewDisconnectedMount(socketFilesystem, nil, &vfs.MountOptions{})
|
||||
|
||||
k.socketsVFS2 = make(map[*vfs.FileDescription]*SocketRecord)
|
||||
|
||||
k.cgroupRegistry = newCgroupRegistry()
|
||||
ctx := k.SupervisorContext()
|
||||
if err := k.vfs.Init(ctx); err != nil {
|
||||
return fmt.Errorf("failed to initialize VFS: %v", err)
|
||||
}
|
||||
|
||||
err := k.rootIPCNamespace.InitPosixQueues(ctx, &k.vfs, auth.CredentialsFromContext(ctx))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create mqfs filesystem: %v", err)
|
||||
}
|
||||
|
||||
pipeFilesystem, err := pipefs.NewFilesystem(&k.vfs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create pipefs filesystem: %v", err)
|
||||
}
|
||||
defer pipeFilesystem.DecRef(ctx)
|
||||
pipeMount := k.vfs.NewDisconnectedMount(pipeFilesystem, nil, &vfs.MountOptions{})
|
||||
k.pipeMount = pipeMount
|
||||
|
||||
tmpfsFilesystem, tmpfsRoot, err := tmpfs.NewFilesystem(ctx, &k.vfs, auth.NewRootCredentials(k.rootUserNamespace))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create tmpfs filesystem: %v", err)
|
||||
}
|
||||
defer tmpfsFilesystem.DecRef(ctx)
|
||||
defer tmpfsRoot.DecRef(ctx)
|
||||
k.shmMount = k.vfs.NewDisconnectedMount(tmpfsFilesystem, tmpfsRoot, &vfs.MountOptions{})
|
||||
|
||||
socketFilesystem, err := sockfs.NewFilesystem(&k.vfs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create sockfs filesystem: %v", err)
|
||||
}
|
||||
defer socketFilesystem.DecRef(ctx)
|
||||
k.socketMount = k.vfs.NewDisconnectedMount(socketFilesystem, nil, &vfs.MountOptions{})
|
||||
|
||||
k.socketsVFS2 = make(map[*vfs.FileDescription]*SocketRecord)
|
||||
|
||||
k.cgroupRegistry = newCgroupRegistry()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -501,50 +492,16 @@ func (k *Kernel) SaveTo(ctx context.Context, w wire.Writer) error {
|
||||
k.mf.StartEvictions()
|
||||
k.mf.WaitForEvictions()
|
||||
|
||||
if VFS2Enabled {
|
||||
// Discard unsavable mappings, such as those for host file descriptors.
|
||||
if err := k.invalidateUnsavableMappings(ctx); err != nil {
|
||||
return fmt.Errorf("failed to invalidate unsavable mappings: %v", err)
|
||||
}
|
||||
// Discard unsavable mappings, such as those for host file descriptors.
|
||||
if err := k.invalidateUnsavableMappings(ctx); err != nil {
|
||||
return fmt.Errorf("failed to invalidate unsavable mappings: %v", err)
|
||||
}
|
||||
|
||||
// Prepare filesystems for saving. This must be done after
|
||||
// invalidateUnsavableMappings(), since dropping memory mappings may
|
||||
// affect filesystem state (e.g. page cache reference counts).
|
||||
if err := k.vfs.PrepareSave(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Flush cached file writes to backing storage. This must come after
|
||||
// MemoryFile eviction since eviction may cause file writes.
|
||||
if err := k.flushWritesToFiles(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Clear the dirent cache before saving because Dirents must be Loaded in a
|
||||
// particular order (parents before children), and Loading dirents from a cache
|
||||
// breaks that order.
|
||||
if err := k.flushMountSourceRefs(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure that all inode and mount release operations have completed.
|
||||
fs.AsyncBarrier()
|
||||
|
||||
// Once all fs work has completed (flushed references have all been released),
|
||||
// reset mount mappings. This allows individual mounts to save how inodes map
|
||||
// to filesystem resources. Without this, fs.Inodes cannot be restored.
|
||||
fs.SaveInodeMappings()
|
||||
|
||||
// Discard unsavable mappings, such as those for host file descriptors.
|
||||
// This must be done after waiting for "asynchronous fs work", which
|
||||
// includes async I/O that may touch application memory.
|
||||
//
|
||||
// TODO(gvisor.dev/issue/1624): This rationale is believed to be
|
||||
// obsolete since AIO callbacks are now waited-for by Kernel.Pause(),
|
||||
// but this order is conservatively retained for VFS1.
|
||||
if err := k.invalidateUnsavableMappings(ctx); err != nil {
|
||||
return fmt.Errorf("failed to invalidate unsavable mappings: %v", err)
|
||||
}
|
||||
// Prepare filesystems for saving. This must be done after
|
||||
// invalidateUnsavableMappings(), since dropping memory mappings may
|
||||
// affect filesystem state (e.g. page cache reference counts).
|
||||
if err := k.vfs.PrepareSave(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Save the CPUID FeatureSet before the rest of the kernel so we can
|
||||
@@ -746,17 +703,8 @@ func (k *Kernel) LoadFrom(ctx context.Context, r wire.Reader, timeReady chan str
|
||||
net.Resume()
|
||||
}
|
||||
|
||||
if VFS2Enabled {
|
||||
if err := k.vfs.CompleteRestore(ctx, vfsOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Ensure that all pending asynchronous work is complete:
|
||||
// - namedpipe opening
|
||||
// - inode file opening
|
||||
if err := fs.AsyncErrorBarrier(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := k.vfs.CompleteRestore(ctx, vfsOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tcpip.AsyncLoading.Wait()
|
||||
@@ -843,14 +791,7 @@ type CreateProcessArgs struct {
|
||||
//
|
||||
// Anyone setting MountNamespace must donate a reference (i.e.
|
||||
// increment it).
|
||||
MountNamespace *fs.MountNamespace
|
||||
|
||||
// MountNamespaceVFS2 optionally contains the mount namespace for this
|
||||
// process. If nil, the init process's mount namespace is used.
|
||||
//
|
||||
// Anyone setting MountNamespaceVFS2 must donate a reference (i.e.
|
||||
// increment it).
|
||||
MountNamespaceVFS2 *vfs.MountNamespace
|
||||
MountNamespace *vfs.MountNamespace
|
||||
|
||||
// ContainerID is the container that the process belongs to.
|
||||
ContainerID string
|
||||
@@ -889,17 +830,11 @@ func (ctx *createProcessContext) Value(key interface{}) interface{} {
|
||||
return ipcns
|
||||
case auth.CtxCredentials:
|
||||
return ctx.args.Credentials
|
||||
case fs.CtxRoot:
|
||||
if ctx.args.MountNamespace != nil {
|
||||
// MountNamespace.Root() will take a reference on the root dirent for us.
|
||||
return ctx.args.MountNamespace.Root()
|
||||
}
|
||||
return nil
|
||||
case vfs.CtxRoot:
|
||||
if ctx.args.MountNamespaceVFS2 == nil {
|
||||
if ctx.args.MountNamespace == nil {
|
||||
return nil
|
||||
}
|
||||
root := ctx.args.MountNamespaceVFS2.Root()
|
||||
root := ctx.args.MountNamespace.Root()
|
||||
root.IncRef()
|
||||
return root
|
||||
case vfs.CtxMountNamespace:
|
||||
@@ -953,86 +888,47 @@ func (k *Kernel) CreateProcess(args CreateProcessArgs) (*ThreadGroup, ThreadID,
|
||||
log.Infof("EXEC: %v", args.Argv)
|
||||
|
||||
ctx := args.NewContext(k)
|
||||
|
||||
var (
|
||||
opener fsbridge.Lookup
|
||||
fsContext *FSContext
|
||||
mntns *fs.MountNamespace
|
||||
mntnsVFS2 *vfs.MountNamespace
|
||||
)
|
||||
|
||||
if VFS2Enabled {
|
||||
mntnsVFS2 = args.MountNamespaceVFS2
|
||||
if mntnsVFS2 == nil {
|
||||
if k.globalInit == nil {
|
||||
return nil, 0, fmt.Errorf("mount namespace is nil")
|
||||
}
|
||||
// Add a reference to the namespace, which is transferred to the new process.
|
||||
mntnsVFS2 = k.globalInit.Leader().MountNamespaceVFS2()
|
||||
mntnsVFS2.IncRef()
|
||||
mntns := args.MountNamespace
|
||||
if mntns == nil {
|
||||
if k.globalInit == nil {
|
||||
return nil, 0, fmt.Errorf("mount namespace is nil")
|
||||
}
|
||||
// Get the root directory from the MountNamespace.
|
||||
root := mntnsVFS2.Root()
|
||||
root.IncRef()
|
||||
defer root.DecRef(ctx)
|
||||
|
||||
// Grab the working directory.
|
||||
wd := root // Default.
|
||||
if args.WorkingDirectory != "" {
|
||||
pop := vfs.PathOperation{
|
||||
Root: root,
|
||||
Start: wd,
|
||||
Path: fspath.Parse(args.WorkingDirectory),
|
||||
FollowFinalSymlink: true,
|
||||
}
|
||||
// NOTE(b/236028361): Do not set CheckSearchable flag to true.
|
||||
// Application is allowed to start with a working directory that it can
|
||||
// not access/search. This is consistent with Docker and VFS1. Runc
|
||||
// explicitly allows for this in 6ce2d63a5db6 ("libct/init_linux: retry
|
||||
// chdir to fix EPERM"). As described in the commit, runc unintentionally
|
||||
// allowed this behavior in a couple of releases and applications started
|
||||
// relying on it. So they decided to allow it for backward compatibility.
|
||||
var err error
|
||||
wd, err = k.VFS().GetDentryAt(ctx, args.Credentials, &pop, &vfs.GetDentryOptions{})
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to find initial working directory %q: %v", args.WorkingDirectory, err)
|
||||
}
|
||||
defer wd.DecRef(ctx)
|
||||
}
|
||||
opener = fsbridge.NewVFSLookup(mntnsVFS2, root, wd)
|
||||
fsContext = NewFSContextVFS2(root, wd, args.Umask)
|
||||
|
||||
} else {
|
||||
mntns = args.MountNamespace
|
||||
if mntns == nil {
|
||||
if k.globalInit == nil {
|
||||
return nil, 0, fmt.Errorf("mount namespace is nil")
|
||||
}
|
||||
mntns = k.GlobalInit().Leader().MountNamespace()
|
||||
mntns.IncRef()
|
||||
}
|
||||
// Get the root directory from the MountNamespace.
|
||||
root := mntns.Root()
|
||||
// The call to newFSContext below will take a reference on root, so we
|
||||
// don't need to hold this one.
|
||||
defer root.DecRef(ctx)
|
||||
|
||||
// Grab the working directory.
|
||||
remainingTraversals := args.MaxSymlinkTraversals
|
||||
wd := root // Default.
|
||||
if args.WorkingDirectory != "" {
|
||||
var err error
|
||||
wd, err = mntns.FindInode(ctx, root, nil, args.WorkingDirectory, &remainingTraversals)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to find initial working directory %q: %v", args.WorkingDirectory, err)
|
||||
}
|
||||
defer wd.DecRef(ctx)
|
||||
}
|
||||
opener = fsbridge.NewFSLookup(mntns, root, wd)
|
||||
fsContext = newFSContext(root, wd, args.Umask)
|
||||
// Add a reference to the namespace, which is transferred to the new process.
|
||||
mntns = k.globalInit.Leader().MountNamespaceVFS2()
|
||||
mntns.IncRef()
|
||||
}
|
||||
// Get the root directory from the MountNamespace.
|
||||
root := mntns.Root()
|
||||
root.IncRef()
|
||||
defer root.DecRef(ctx)
|
||||
|
||||
tg := k.NewThreadGroup(mntns, args.PIDNamespace, NewSignalHandlers(), linux.SIGCHLD, args.Limits)
|
||||
// Grab the working directory.
|
||||
wd := root // Default.
|
||||
if args.WorkingDirectory != "" {
|
||||
pop := vfs.PathOperation{
|
||||
Root: root,
|
||||
Start: wd,
|
||||
Path: fspath.Parse(args.WorkingDirectory),
|
||||
FollowFinalSymlink: true,
|
||||
}
|
||||
// NOTE(b/236028361): Do not set CheckSearchable flag to true.
|
||||
// Application is allowed to start with a working directory that it can
|
||||
// not access/search. This is consistent with Docker and VFS1. Runc
|
||||
// explicitly allows for this in 6ce2d63a5db6 ("libct/init_linux: retry
|
||||
// chdir to fix EPERM"). As described in the commit, runc unintentionally
|
||||
// allowed this behavior in a couple of releases and applications started
|
||||
// relying on it. So they decided to allow it for backward compatibility.
|
||||
var err error
|
||||
wd, err = k.VFS().GetDentryAt(ctx, args.Credentials, &pop, &vfs.GetDentryOptions{})
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to find initial working directory %q: %v", args.WorkingDirectory, err)
|
||||
}
|
||||
defer wd.DecRef(ctx)
|
||||
}
|
||||
opener := fsbridge.NewVFSLookup(mntns, root, wd)
|
||||
fsContext := NewFSContext(root, wd, args.Umask)
|
||||
|
||||
tg := k.NewThreadGroup(nil, args.PIDNamespace, NewSignalHandlers(), linux.SIGCHLD, args.Limits)
|
||||
cu := cleanup.Make(func() {
|
||||
tg.Release(ctx)
|
||||
})
|
||||
@@ -1094,7 +990,7 @@ func (k *Kernel) CreateProcess(args CreateProcessArgs) (*ThreadGroup, ThreadID,
|
||||
UTSNamespace: args.UTSNamespace,
|
||||
IPCNamespace: args.IPCNamespace,
|
||||
AbstractSocketNamespace: args.AbstractSocketNamespace,
|
||||
MountNamespaceVFS2: mntnsVFS2,
|
||||
MountNamespace: mntns,
|
||||
ContainerID: args.ContainerID,
|
||||
UserCounters: k.GetUserCounters(args.Credentials.RealKUID),
|
||||
}
|
||||
@@ -1193,14 +1089,8 @@ func (k *Kernel) pauseTimeLocked(ctx context.Context) {
|
||||
// but ktime.Timer.Pause is idempotent so this is harmless.
|
||||
if t.fdTable != nil {
|
||||
t.fdTable.forEach(ctx, func(_ int32, file *fs.File, fd *vfs.FileDescription, _ FDFlags) {
|
||||
if VFS2Enabled {
|
||||
if tfd, ok := fd.Impl().(*timerfd.TimerFileDescription); ok {
|
||||
tfd.PauseTimer()
|
||||
}
|
||||
} else {
|
||||
if tfd, ok := file.FileOperations.(*oldtimerfd.TimerOperations); ok {
|
||||
tfd.PauseTimer()
|
||||
}
|
||||
if tfd, ok := fd.Impl().(*timerfd.TimerFileDescription); ok {
|
||||
tfd.PauseTimer()
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1229,14 +1119,8 @@ func (k *Kernel) resumeTimeLocked(ctx context.Context) {
|
||||
}
|
||||
if t.fdTable != nil {
|
||||
t.fdTable.forEach(ctx, func(_ int32, file *fs.File, fd *vfs.FileDescription, _ FDFlags) {
|
||||
if VFS2Enabled {
|
||||
if tfd, ok := fd.Impl().(*timerfd.TimerFileDescription); ok {
|
||||
tfd.ResumeTimer()
|
||||
}
|
||||
} else {
|
||||
if tfd, ok := file.FileOperations.(*oldtimerfd.TimerOperations); ok {
|
||||
tfd.ResumeTimer()
|
||||
}
|
||||
if tfd, ok := fd.Impl().(*timerfd.TimerFileDescription); ok {
|
||||
tfd.ResumeTimer()
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1678,14 +1562,8 @@ func (k *Kernel) DeleteSocketVFS2(sock *vfs.FileDescription) {
|
||||
func (k *Kernel) ListSockets() []*SocketRecord {
|
||||
k.extMu.Lock()
|
||||
var socks []*SocketRecord
|
||||
if VFS2Enabled {
|
||||
for _, s := range k.socketsVFS2 {
|
||||
socks = append(socks, s)
|
||||
}
|
||||
} else {
|
||||
for s := k.sockets.Front(); s != nil; s = s.Next() {
|
||||
socks = append(socks, &s.SocketRecord)
|
||||
}
|
||||
for _, s := range k.socketsVFS2 {
|
||||
socks = append(socks, s)
|
||||
}
|
||||
k.extMu.Unlock()
|
||||
return socks
|
||||
@@ -1847,13 +1725,11 @@ func (k *Kernel) CgroupRegistry() *CgroupRegistry {
|
||||
// initialized, e.g. after k.Start() has been called.
|
||||
func (k *Kernel) Release() {
|
||||
ctx := k.SupervisorContext()
|
||||
if VFS2Enabled {
|
||||
k.hostMount.DecRef(ctx)
|
||||
k.pipeMount.DecRef(ctx)
|
||||
k.shmMount.DecRef(ctx)
|
||||
k.socketMount.DecRef(ctx)
|
||||
k.vfs.Release(ctx)
|
||||
}
|
||||
k.hostMount.DecRef(ctx)
|
||||
k.pipeMount.DecRef(ctx)
|
||||
k.shmMount.DecRef(ctx)
|
||||
k.socketMount.DecRef(ctx)
|
||||
k.vfs.Release(ctx)
|
||||
k.timekeeper.Destroy()
|
||||
k.vdso.Release(ctx)
|
||||
k.RootNetworkNamespace().DecRef()
|
||||
|
||||
@@ -123,11 +123,6 @@ func (t *Task) CanTrace(target *Task, attach bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// YAMA only supported for vfs2.
|
||||
if !VFS2Enabled {
|
||||
return true
|
||||
}
|
||||
|
||||
if t.k.YAMAPtraceScope.Load() == linux.YAMA_SCOPE_RELATIONAL {
|
||||
t.tg.pidns.owner.mu.RLock()
|
||||
defer t.tg.pidns.owner.mu.RUnlock()
|
||||
@@ -149,11 +144,6 @@ func (t *Task) canTraceLocked(target *Task, attach bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// YAMA only supported for vfs2.
|
||||
if !VFS2Enabled {
|
||||
return true
|
||||
}
|
||||
|
||||
if t.k.YAMAPtraceScope.Load() == linux.YAMA_SCOPE_RELATIONAL {
|
||||
if !t.canTraceYAMALocked(target) {
|
||||
return false
|
||||
|
||||
@@ -104,13 +104,11 @@ func (s *syslog) Log() []byte {
|
||||
s.msg = append(s.msg, []byte(fmt.Sprintf(format, time, selectMessage()))...)
|
||||
}
|
||||
|
||||
if VFS2Enabled {
|
||||
time += rand.Float64() / 2
|
||||
s.msg = append(s.msg, []byte(fmt.Sprintf(format, time, "Setting up VFS..."))...)
|
||||
if FUSEEnabled {
|
||||
time += rand.Float64() / 2
|
||||
s.msg = append(s.msg, []byte(fmt.Sprintf(format, time, "Setting up VFS2..."))...)
|
||||
if FUSEEnabled {
|
||||
time += rand.Float64() / 2
|
||||
s.msg = append(s.msg, []byte(fmt.Sprintf(format, time, "Setting up FUSE..."))...)
|
||||
}
|
||||
s.msg = append(s.msg, []byte(fmt.Sprintf(format, time, "Setting up FUSE..."))...)
|
||||
}
|
||||
|
||||
time += rand.Float64() / 2
|
||||
|
||||
@@ -447,10 +447,10 @@ type Task struct {
|
||||
// abstractSockets is protected by mu.
|
||||
abstractSockets *AbstractSocketNamespace
|
||||
|
||||
// mountNamespaceVFS2 is the task's mount namespace.
|
||||
// mountNamespace is the task's mount namespace.
|
||||
//
|
||||
// It is protected by mu. It is owned by the task goroutine.
|
||||
mountNamespaceVFS2 *vfs.MountNamespace
|
||||
mountNamespace *vfs.MountNamespace
|
||||
|
||||
// parentDeathSignal is sent to this task's thread group when its parent exits.
|
||||
//
|
||||
@@ -705,19 +705,9 @@ func (t *Task) SyscallRestartBlock() SyscallRestartBlock {
|
||||
// Preconditions: The caller must be running on the task goroutine, or t.mu
|
||||
// must be locked.
|
||||
func (t *Task) IsChrooted() bool {
|
||||
if VFS2Enabled {
|
||||
realRoot := t.mountNamespaceVFS2.Root()
|
||||
root := t.fsContext.RootDirectoryVFS2()
|
||||
defer root.DecRef(t)
|
||||
return root != realRoot
|
||||
}
|
||||
|
||||
realRoot := t.tg.mounts.Root()
|
||||
defer realRoot.DecRef(t)
|
||||
root := t.fsContext.RootDirectory()
|
||||
if root != nil {
|
||||
defer root.DecRef(t)
|
||||
}
|
||||
realRoot := t.mountNamespace.Root()
|
||||
root := t.fsContext.RootDirectoryVFS2()
|
||||
defer root.DecRef(t)
|
||||
return root != realRoot
|
||||
}
|
||||
|
||||
@@ -839,7 +829,7 @@ func (t *Task) MountNamespace() *fs.MountNamespace {
|
||||
func (t *Task) MountNamespaceVFS2() *vfs.MountNamespace {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
return t.mountNamespaceVFS2
|
||||
return t.mountNamespace
|
||||
}
|
||||
|
||||
// AbstractSockets returns t's AbstractSocketNamespace.
|
||||
|
||||
@@ -103,9 +103,7 @@ func (t *Task) Clone(args *linux.CloneArgs) (ThreadID, *SyscallControl, error) {
|
||||
ipcns := t.IPCNamespace()
|
||||
if args.Flags&linux.CLONE_NEWIPC != 0 {
|
||||
ipcns = NewIPCNamespace(userns)
|
||||
if VFS2Enabled {
|
||||
ipcns.InitPosixQueues(t, t.k.VFS(), creds)
|
||||
}
|
||||
ipcns.InitPosixQueues(t, t.k.VFS(), creds)
|
||||
} else {
|
||||
ipcns.IncRef()
|
||||
}
|
||||
@@ -125,11 +123,11 @@ func (t *Task) Clone(args *linux.CloneArgs) (ThreadID, *SyscallControl, error) {
|
||||
})
|
||||
|
||||
// TODO(b/63601033): Implement CLONE_NEWNS.
|
||||
mntnsVFS2 := t.mountNamespaceVFS2
|
||||
if mntnsVFS2 != nil {
|
||||
mntnsVFS2.IncRef()
|
||||
mntns := t.mountNamespace
|
||||
if mntns != nil {
|
||||
mntns.IncRef()
|
||||
cu.Add(func() {
|
||||
mntnsVFS2.DecRef(t)
|
||||
mntns.DecRef(t)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -210,7 +208,7 @@ func (t *Task) Clone(args *linux.CloneArgs) (ThreadID, *SyscallControl, error) {
|
||||
UTSNamespace: utsns,
|
||||
IPCNamespace: ipcns,
|
||||
AbstractSocketNamespace: t.abstractSockets,
|
||||
MountNamespaceVFS2: mntnsVFS2,
|
||||
MountNamespace: mntns,
|
||||
RSeqAddr: rseqAddr,
|
||||
RSeqSignature: rseqSignature,
|
||||
ContainerID: t.ContainerID(),
|
||||
@@ -487,9 +485,7 @@ func (t *Task) Unshare(flags int32) error {
|
||||
// namespace"
|
||||
oldIPCNS = t.ipcns
|
||||
t.ipcns = NewIPCNamespace(creds.UserNamespace)
|
||||
if VFS2Enabled {
|
||||
t.ipcns.InitPosixQueues(t, t.k.VFS(), creds)
|
||||
}
|
||||
t.ipcns.InitPosixQueues(t, t.k.VFS(), creds)
|
||||
}
|
||||
var oldFDTable *FDTable
|
||||
if flags&linux.CLONE_FILES != 0 {
|
||||
|
||||
@@ -105,8 +105,8 @@ func (t *Task) contextValue(key interface{}, isTaskGoroutine bool) interface{} {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
}
|
||||
t.mountNamespaceVFS2.IncRef()
|
||||
return t.mountNamespaceVFS2
|
||||
t.mountNamespace.IncRef()
|
||||
return t.mountNamespace
|
||||
case fs.CtxDirentCacheLimiter:
|
||||
return t.k.DirentCacheLimiter
|
||||
case inet.CtxStack:
|
||||
|
||||
@@ -285,8 +285,8 @@ func (*runExitMain) execute(t *Task) taskRunState {
|
||||
t.LeaveCgroups()
|
||||
|
||||
t.mu.Lock()
|
||||
mntns := t.mountNamespaceVFS2
|
||||
t.mountNamespaceVFS2 = nil
|
||||
mntns := t.mountNamespace
|
||||
t.mountNamespace = nil
|
||||
ipcns := t.ipcns
|
||||
netns := t.NetworkNamespace()
|
||||
t.mu.Unlock()
|
||||
|
||||
@@ -85,8 +85,8 @@ type TaskConfig struct {
|
||||
// AbstractSocketNamespace is the AbstractSocketNamespace of the new task.
|
||||
AbstractSocketNamespace *AbstractSocketNamespace
|
||||
|
||||
// MountNamespaceVFS2 is the MountNamespace of the new task.
|
||||
MountNamespaceVFS2 *vfs.MountNamespace
|
||||
// MountNamespace is the MountNamespace of the new task.
|
||||
MountNamespace *vfs.MountNamespace
|
||||
|
||||
// RSeqAddr is a pointer to the the userspace linux.RSeq structure.
|
||||
RSeqAddr hostarch.Addr
|
||||
@@ -116,8 +116,8 @@ func (ts *TaskSet) NewTask(ctx context.Context, cfg *TaskConfig) (*Task, error)
|
||||
cfg.FDTable.DecRef(ctx)
|
||||
cfg.IPCNamespace.DecRef(ctx)
|
||||
cfg.NetworkNamespace.DecRef()
|
||||
if cfg.MountNamespaceVFS2 != nil {
|
||||
cfg.MountNamespaceVFS2.DecRef(ctx)
|
||||
if cfg.MountNamespace != nil {
|
||||
cfg.MountNamespace.DecRef(ctx)
|
||||
}
|
||||
}
|
||||
if err := cfg.UserCounters.incRLimitNProc(ctx); err != nil {
|
||||
@@ -145,29 +145,29 @@ func (ts *TaskSet) newTask(ctx context.Context, cfg *TaskConfig) (*Task, error)
|
||||
parent: cfg.Parent,
|
||||
children: make(map[*Task]struct{}),
|
||||
},
|
||||
runState: (*runApp)(nil),
|
||||
interruptChan: make(chan struct{}, 1),
|
||||
signalMask: atomicbitops.FromUint64(uint64(cfg.SignalMask)),
|
||||
signalStack: linux.SignalStack{Flags: linux.SS_DISABLE},
|
||||
image: *image,
|
||||
fsContext: cfg.FSContext,
|
||||
fdTable: cfg.FDTable,
|
||||
k: cfg.Kernel,
|
||||
ptraceTracees: make(map[*Task]struct{}),
|
||||
allowedCPUMask: cfg.AllowedCPUMask.Copy(),
|
||||
ioUsage: &usage.IO{},
|
||||
niceness: cfg.Niceness,
|
||||
utsns: cfg.UTSNamespace,
|
||||
ipcns: cfg.IPCNamespace,
|
||||
abstractSockets: cfg.AbstractSocketNamespace,
|
||||
mountNamespaceVFS2: cfg.MountNamespaceVFS2,
|
||||
rseqCPU: -1,
|
||||
rseqAddr: cfg.RSeqAddr,
|
||||
rseqSignature: cfg.RSeqSignature,
|
||||
futexWaiter: futex.NewWaiter(),
|
||||
containerID: cfg.ContainerID,
|
||||
cgroups: make(map[Cgroup]struct{}),
|
||||
userCounters: cfg.UserCounters,
|
||||
runState: (*runApp)(nil),
|
||||
interruptChan: make(chan struct{}, 1),
|
||||
signalMask: atomicbitops.FromUint64(uint64(cfg.SignalMask)),
|
||||
signalStack: linux.SignalStack{Flags: linux.SS_DISABLE},
|
||||
image: *image,
|
||||
fsContext: cfg.FSContext,
|
||||
fdTable: cfg.FDTable,
|
||||
k: cfg.Kernel,
|
||||
ptraceTracees: make(map[*Task]struct{}),
|
||||
allowedCPUMask: cfg.AllowedCPUMask.Copy(),
|
||||
ioUsage: &usage.IO{},
|
||||
niceness: cfg.Niceness,
|
||||
utsns: cfg.UTSNamespace,
|
||||
ipcns: cfg.IPCNamespace,
|
||||
abstractSockets: cfg.AbstractSocketNamespace,
|
||||
mountNamespace: cfg.MountNamespace,
|
||||
rseqCPU: -1,
|
||||
rseqAddr: cfg.RSeqAddr,
|
||||
rseqSignature: cfg.RSeqSignature,
|
||||
futexWaiter: futex.NewWaiter(),
|
||||
containerID: cfg.ContainerID,
|
||||
cgroups: make(map[Cgroup]struct{}),
|
||||
userCounters: cfg.UserCounters,
|
||||
}
|
||||
t.netns.Store(cfg.NetworkNamespace)
|
||||
t.creds.Store(cfg.Credentials)
|
||||
@@ -238,10 +238,8 @@ func (ts *TaskSet) newTask(ctx context.Context, cfg *TaskConfig) (*Task, error)
|
||||
t.parent.children[t] = struct{}{}
|
||||
}
|
||||
|
||||
if VFS2Enabled {
|
||||
// srcT may be nil, in which case we default to root cgroups.
|
||||
t.EnterInitialCgroups(srcT)
|
||||
}
|
||||
// srcT may be nil, in which case we default to root cgroups.
|
||||
t.EnterInitialCgroups(srcT)
|
||||
|
||||
if tg.leader == nil {
|
||||
// New thread group.
|
||||
|
||||
@@ -712,19 +712,11 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
|
||||
}
|
||||
|
||||
if len(fds) > 0 {
|
||||
if kernel.VFS2Enabled {
|
||||
rights, err := NewSCMRightsVFS2(t, fds)
|
||||
if err != nil {
|
||||
return socket.ControlMessages{}, err
|
||||
}
|
||||
cmsgs.Unix.Rights = rights
|
||||
} else {
|
||||
rights, err := NewSCMRights(t, fds)
|
||||
if err != nil {
|
||||
return socket.ControlMessages{}, err
|
||||
}
|
||||
cmsgs.Unix.Rights = rights
|
||||
rights, err := NewSCMRightsVFS2(t, fds)
|
||||
if err != nil {
|
||||
return socket.ControlMessages{}, err
|
||||
}
|
||||
cmsgs.Unix.Rights = rights
|
||||
}
|
||||
|
||||
return cmsgs, nil
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user