gvisor gofer chroot

 

Files in the sandbox may be backed by different implementations. For host-native files (where a file descriptor is available), the Gofer may return a file descriptor to the Sentry via SCM_RIGHTS1.

These files may be read from and written to through standard system calls, and also mapped into the associated application’s address space. This allows the same host memory to be shared across multiple sandboxes, although this mechanism does not preclude the use of side-channels (see Security Model.

Note that some file systems exist only within the context of the sandbox. For example, in many cases a tmpfs mount will be available at /tmp or /dev/shm, which allocates memory directly from the sandbox memory file (see below). Ultimately, these will be accounted against relevant limits in a similar way as the host native case.

root@cloud:~# ps -elf | grep docker
4 S root     926586      1  0  80   0 - 1392756 futex_ Jan14 ?      00:06:08 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
0 S root     941940  22795  0  80   0 - 177146 futex_ 10:11 ?       00:00:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/f1663b36dc38560d1c77639273944c2da612e5c11571bdeb717d371a78b06486 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runsc-kvm
0 S root     942946 940675  0  80   0 - 538568 futex_ 10:45 pts/0   00:00:00 docker run -it --runtime=runsc-kvm --rm debian /bin/bash
0 S root     942983  22795  0  80   0 - 177146 futex_ 10:45 ?       00:00:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/13802c34815d499799af132ae792b796d3cbf52b5792aa536dd756c2c6d993a0 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runsc-kvm
4 S root     942997 942983  0  80   0 - 186593 futex_ 10:45 ?       00:00:03 runsc-gofer --root=/var/run/docker/runtime-runsc-kvm/moby --log=/run/containerd/io.containerd.runtime.v1.linux/moby/13802c34815d499799af132ae792b796d3cbf52b5792aa536dd756c2c6d993a0/log.json --log-format=json --platform=kvm --log-fd=3 gofer --bundle /run/containerd/io.containerd.runtime.v1.linux/moby/13802c34815d499799af132ae792b796d3cbf52b5792aa536dd756c2c6d993a0 --spec-fd=4 --mounts-fd=5 --io-fds=6 --io-fds=7 --io-fds=8 --io-fds=9 --apply-caps=false --setup-root=false
4 S nobody   943010 942983  2  80   0 - 68452017770 ep_pol 10:45 pts/3 00:00:41 runsc-sandbox --root=/var/run/docker/runtime-runsc-kvm/moby --log=/run/containerd/io.containerd.runtime.v1.linux/moby/13802c34815d499799af132ae792b796d3cbf52b5792aa536dd756c2c6d993a0/log.json --log-format=json --platform=kvm --log-fd=3 boot --bundle=/run/containerd/io.containerd.runtime.v1.linux/moby/13802c34815d499799af132ae792b796d3cbf52b5792aa536dd756c2c6d993a0 --controller-fd=4 --mounts-fd=5 --spec-fd=6 --start-sync-fd=7 --io-fds=8 --io-fds=9 --io-fds=10 --io-fds=11 --device-fd=12 --stdio-fds=13 --stdio-fds=14 --stdio-fds=15 --pidns=true --cpu-num 64 13802c34815d499799af132ae792b796d3cbf52b5792aa536dd756c2c6d993a0
0 S root     943339 940908  0  80   0 -  1418 pipe_r 11:19 pts/1    00:00:00 grep --color=auto docker
root@cloud:~# dlv attach  942997
(dlv) bt
0  0x000000000008dccc in syscall.Syscall6
   at src/syscall/asm_linux_arm64.s:43
1  0x00000000002c1ce8 in gvisor.dev/gvisor/pkg/flipcall.(*Endpoint).futexWaitConnState
   at pkg/flipcall/futex_linux.go:76
2  0x00000000002c1b58 in gvisor.dev/gvisor/pkg/flipcall.(*Endpoint).futexWaitUntilActive
   at pkg/flipcall/futex_linux.go:56
3  0x00000000002c08bc in gvisor.dev/gvisor/pkg/flipcall.(*Endpoint).ctrlRoundTrip
   at pkg/flipcall/ctrl_futex.go:133
4  0x00000000002c15c4 in gvisor.dev/gvisor/pkg/flipcall.(*Endpoint).SendRecv
   at pkg/flipcall/flipcall.go:234
5  0x00000000002e791c in gvisor.dev/gvisor/pkg/p9.(*channel).send
   at pkg/p9/transport_flipcall.go:165
6  0x00000000002e74f8 in gvisor.dev/gvisor/pkg/p9.(*channel).service
   at pkg/p9/transport_flipcall.go:88
7  0x00000000002ed06c in gvisor.dev/gvisor/pkg/p9.(*connState).initializeChannels.func1
   at pkg/p9/server.go:457
8  0x0000000000077c84 in runtime.goexit
   at src/runtime/asm_arm64.s:1136
(dlv) 
cmd/help.go
// Execute implements subcommands.Command.Execute.
func (h *Help) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
    switch f.NArg() {
    case 0:
        fmt.Fprintf(h.cdr.Output, "Usage: %s <flags> <subcommand> <subcommand args>

", h.cdr.Name())
        fmt.Fprintf(h.cdr.Output, `runsc is the gVisor container runtime.
Functionality is provided by subcommands. For help with a specific subcommand,
use "%s %s <subcommand>".
`, h.cdr.Name(), h.Name())
        h.cdr.VisitGroups(func(g *subcommands.CommandGroup) {
            h.cdr.ExplainGroup(h.cdr.Output, g)
        })

        fmt.Fprintf(h.cdr.Output, "Additional help topics (Use "%s %s <topic>" to see help on the topic):
", h.cdr.Name(), h.Name())
        for _, cmd := range h.commands {
            fmt.Fprintf(h.cdr.Output, "	%-15s  %s
", cmd.Name(), cmd.Synopsis())
        }
        fmt.Fprintf(h.cdr.Output, "
Use "%s flags" for a list of top-level flags
", h.cdr.Name())
        return subcommands.ExitSuccess
    default:
        // Look for commands registered to the commander and print help explanation if found.
        found := false
        h.cdr.VisitCommands(func(g *subcommands.CommandGroup, cmd subcommands.Command) {
            if f.Arg(0) == cmd.Name() {
                h.cdr.ExplainCommand(h.cdr.Output, cmd)
                found = true
            }
        })
        if found {
            return subcommands.ExitSuccess
        }

        // Next check commands registered to the help command.
        for _, cmd := range h.commands {
            if f.Arg(0) == cmd.Name() {
                fs := flag.NewFlagSet(f.Arg(0), flag.ContinueOnError)
                fs.Usage = func() { h.cdr.ExplainCommand(h.cdr.Error, cmd) }
                cmd.SetFlags(fs)
                if fs.Parse(f.Args()[1:]) != nil {
                    return subcommands.ExitUsageError
                }
                return cmd.Execute(ctx, f, args...)
            }
        }

        fmt.Fprintf(h.cdr.Error, "Subcommand %s not understood
", f.Arg(0))
    }

    f.Usage()
    return subcommands.ExitUsageError
}
// Execute implements subcommands.Command.
func (g *Gofer) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
    if g.bundleDir == "" || len(g.ioFDs) < 1 || g.specFD < 0 {
        f.Usage()
        return subcommands.ExitUsageError
    }

    conf := args[0].(*config.Config)

    specFile := os.NewFile(uintptr(g.specFD), "spec file")
    defer specFile.Close()
    spec, err := specutils.ReadSpecFromFile(g.bundleDir, specFile, conf)
    if err != nil {
        Fatalf("reading spec: %v", err)
    }

    if g.setUpRoot {
        if err := setupRootFS(spec, conf); err != nil {
            Fatalf("Error setting up root FS: %v", err)
        }
    }
    if g.applyCaps {
        // Disable caps when calling myself again.
        // Note: minimal argument handling for the default case to keep it simple.
        args := os.Args
        args = append(args, "--apply-caps=false", "--setup-root=false")
        if err := setCapsAndCallSelf(args, goferCaps); err != nil {
            Fatalf("Unable to apply caps: %v", err)
        }
        panic("unreachable")
    }

    // Find what path is going to be served by this gofer.
    root := spec.Root.Path
    if !conf.TestOnlyAllowRunAsCurrentUserWithoutChroot {
        root = "/root"
    }

    // Resolve mount points paths, then replace mounts from our spec and send the
    // mount list over to the sandbox, so they are both in sync.
    //
    // Note that all mount points have been mounted in the proper location in
    // setupRootFS().
    cleanMounts, err := resolveMounts(conf, spec.Mounts, root)
    if err != nil {
        Fatalf("Failure to resolve mounts: %v", err)
    }
    spec.Mounts = cleanMounts
    go func() {
        if err := g.writeMounts(cleanMounts); err != nil {
            panic(fmt.Sprintf("Failed to write mounts: %v", err))
        }
    }()

    specutils.LogSpec(spec)

    // fsgofer should run with a umask of 0, because we want to preserve file
    // modes exactly as sent by the sandbox, which will have applied its own umask.
    syscall.Umask(0)

    if err := fsgofer.OpenProcSelfFD(); err != nil {
        Fatalf("failed to open /proc/self/fd: %v", err)
    }

    if err := syscall.Chroot(root); err != nil {
        Fatalf("failed to chroot to %q: %v", root, err)
    }
    if err := syscall.Chdir("/"); err != nil {
        Fatalf("changing working dir: %v", err)
    }
    log.Infof("Process chroot'd to %q", root)

    // Start with root mount, then add any other additional mount as needed.
    ats := make([]p9.Attacher, 0, len(spec.Mounts)+1)
    ap, err := fsgofer.NewAttachPoint("/", fsgofer.Config{
        ROMount: spec.Root.Readonly || conf.Overlay,
    })
    if err != nil {
        Fatalf("creating attach point: %v", err)
    }
    ats = append(ats, ap)
    log.Infof("Serving %q mapped to %q on FD %d (ro: %t)", "/", root, g.ioFDs[0], spec.Root.Readonly)

    mountIdx := 1 // first one is the root
    for _, m := range spec.Mounts {
        if specutils.Is9PMount(m) {
            cfg := fsgofer.Config{
                ROMount: isReadonlyMount(m.Options) || conf.Overlay,
                HostUDS: conf.FSGoferHostUDS,
            }
            ap, err := fsgofer.NewAttachPoint(m.Destination, cfg)
            if err != nil {
                Fatalf("creating attach point: %v", err)
            }
            ats = append(ats, ap)

            if mountIdx >= len(g.ioFDs) {
                Fatalf("no FD found for mount. Did you forget --io-fd? mount: %d, %v", len(g.ioFDs), m)
            }
            log.Infof("Serving %q mapped on FD %d (ro: %t)", m.Destination, g.ioFDs[mountIdx], cfg.ROMount)
            mountIdx++
        }
    }
    if mountIdx != len(g.ioFDs) {
        Fatalf("too many FDs passed for mounts. mounts: %d, FDs: %d", mountIdx, len(g.ioFDs))
    }

    if conf.FSGoferHostUDS {
        filter.InstallUDSFilters()
    }

    if err := filter.Install(); err != nil {
        Fatalf("installing seccomp filters: %v", err)
    }

    runServers(ats, g.ioFDs)
    return subcommands.ExitSuccess
}
I0115 09:33:42.721710       1 main.go:210] Args: [runsc-gofer --root=/run/user/0/runsc --debug-log=/tmp/runsc/ --strace=true --debug-log-fd=3 gofer --bundle /mycontainer --spec-fd=4 --mounts-fd=5 --io-fds=6 --apply-caps=false --setup-root=false]
I0115 09:33:42.721755       1 main.go:211] Version release-20201216.0-106-gc49ce8ca8ab9
I0115 09:33:42.721775       1 main.go:212] GOOS: linux
I0115 09:33:42.721794       1 main.go:213] GOARCH: arm64
I0115 09:33:42.721817       1 main.go:214] PID: 1
I0115 09:33:42.721837       1 main.go:215] UID: 0, GID: 0
I0115 09:33:42.721857       1 main.go:216] Configuration:
I0115 09:33:42.721876       1 main.go:217]              RootDir: /run/user/0/runsc
I0115 09:33:42.721896       1 main.go:218]              Platform: ptrace
I0115 09:33:42.721915       1 main.go:219]              FileAccess: 0, overlay: false
I0115 09:33:42.721937       1 main.go:220]              Network: 0, logging: false
I0115 09:33:42.721959       1 main.go:221]              Strace: true, max size: 1024, syscalls:
I0115 09:33:42.721979       1 main.go:222]              VFS2 enabled: false
I0115 09:33:42.721998       1 main.go:223] ***************************
I0115 09:33:42.723379       1 gofer.go:164] Process chroot'd to "/root"
I0115 09:33:42.723409       1 gofer.go:175] Serving "/" mapped to "/root" on FD 6 (ro: true)
I0115 09:33:42.723428       1 seccomp.go:61] Installing seccomp filters for 57 syscalls (action=kill process)
I0115 09:33:42.724207       1 seccomp.go:85] Seccomp filters installed.
I0115 09:34:32.255208       1 gofer.go:231] All 9P servers exited.
I0115 09:34:32.255286       1 main.go:236] Exiting with status: 0
~
~
~
~
~
"/tmp/runsc/runsc.log.20210115-173342.650687.gofer" 40L, 3384C 

 文件系统读写

Let's walk through a read operation from the application:

  1. The application running inside the sandbox issues a read(2) syscall to gVisor.
  2. gVisor looks up the FD from the read call in the task's FD table.
  3. That FD belongs to a file backed by pkg/sentry/fs/gofer.fileOperations.
  4. gofer.fileOperations.Read() is called.
  5. gofer.fileOperations checks whether it has a host FD (note that this is different from the FD in step 2 which is a virtual FD that doesn't exist in the host).
  6. If it does, it can shortcut the read and issues a read(2) syscall to the host.
  7. If it doesn't, then it issues a 9P read call to the gofer.
root@cloud:~# docker run -it --runtime=runsc-kvm  -v share:/share --name test  --rm  debian /bin/bash
root@a6a7c81dcfe9:/# cd share/
root@a6a7c81dcfe9:/share# ls
hello.txt
root@a6a7c81dcfe9:/share# touch  hello.txt  
root@a6a7c81dcfe9:/share# echo hello hello.txt 
hello hello.txt
root@a6a7c81dcfe9:/share# echo hello >> hello.txt 
root@a6a7c81dcfe9:/share# echo hello >> hello.txt  
root@a6a7c81dcfe9:/share# 
root@a6a7c81dcfe9:/share# 
root@a6a7c81dcfe9:/share# 
root@a6a7c81dcfe9:/share# 
root@a6a7c81dcfe9:/share# echo hello >> hello.txt  
root@a6a7c81dcfe9:/share# 

gdb  func (r *ReadWriter) Write(b []byte) (int, error) 

(dlv) b fd/fd.go:110
Breakpoint 4 set at 0x286b40 for gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110
(dlv) c
> gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110 (hits goroutine(102):1 total:1) (PC: 0x286b40)
Warning: debugging optimized function
(dlv) bt
 0  0x0000000000286b40 in gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt
    at pkg/fd/fd.go:110
 1  0x000000000069c3a4 in gvisor.dev/gvisor/pkg/secio.(*SectionWriter).Write
    at pkg/secio/secio.go:84
 2  0x0000000000159dd4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.writeFromBlock
    at pkg/safemem/io.go:295
 3  0x0000000000159bb4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.WriteFromBlocks
    at pkg/safemem/io.go:281
 4  0x00000000006dd784 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*handleReadWriter).WriteFromBlocks
    at pkg/sentry/fs/gofer/handles.go:138
 5  0x00000000006de538 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*inodeFileState).WriteFromBlocksAt
    at pkg/sentry/fs/gofer/inode.go:301
 6  0x00000000003affb0 in gvisor.dev/gvisor/pkg/sentry/fs/fsutil.(*writer).WriteFromBlocks
    at pkg/sentry/fs/fsutil/host_mappable.go:210
 7  0x00000000004033e0 in gvisor.dev/gvisor/pkg/safemem.Writer.WriteFromBlocks-fm
    at pkg/safemem/io.go:46
 8  0x00000000003db314 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withInternalMappings
    at pkg/sentry/mm/io.go:506
 9  0x00000000003dba08 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withVecInternalMappings
    at pkg/sentry/mm/io.go:575
10  0x00000000003d9f14 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).CopyInTo
    at pkg/sentry/mm/io.go:309
11  0x00000000003afe94 in gvisor.dev/gvisor/pkg/usermem.IOSequence.CopyInTo
    at pkg/usermem/usermem.go:514
12  0x00000000003afe94 in gvisor.dev/gvisor/pkg/sentry/fs/fsutil.(*HostMappable).Write
    at pkg/sentry/fs/fsutil/host_mappable.go:197
13  0x00000000006db464 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*fileOperations).Write
    at pkg/sentry/fs/gofer/file.go:252
14  0x000000000031f78c in gvisor.dev/gvisor/pkg/sentry/fs.(*File).Writev
    at pkg/sentry/fs/file.go:306
15  0x0000000000597b28 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.writev
    at pkg/sentry/syscalls/linux/sys_write.go:262
16  0x0000000000596470 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.Write
    at pkg/sentry/syscalls/linux/sys_write.go:72
17  0x0000000000522ea4 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).executeSyscall
    at pkg/sentry/kernel/task_syscall.go:104
18  0x0000000000523c5c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallInvoke
    at pkg/sentry/kernel/task_syscall.go:239
19  0x00000000005238dc in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallEnter
    at pkg/sentry/kernel/task_syscall.go:199
20  0x00000000005233e0 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscall
    at pkg/sentry/kernel/task_syscall.go:174
21  0x0000000000518e00 in gvisor.dev/gvisor/pkg/sentry/kernel.(*runApp).execute
    at pkg/sentry/kernel/task_run.go:282
22  0x0000000000517d9c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).run
    at pkg/sentry/kernel/task_run.go:97
23  0x0000000000077c84 in runtime.goexit
    at src/runtime/asm_arm64.s:1136
(dlv) c
> gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110 (hits goroutine(102):2 total:2) (PC: 0x286b40)
Warning: debugging optimized function
(dlv) bt
 0  0x0000000000286b40 in gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt
    at pkg/fd/fd.go:110
 1  0x000000000069c3a4 in gvisor.dev/gvisor/pkg/secio.(*SectionWriter).Write
    at pkg/secio/secio.go:84
 2  0x0000000000159dd4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.writeFromBlock
    at pkg/safemem/io.go:295
 3  0x0000000000159bb4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.WriteFromBlocks
    at pkg/safemem/io.go:281
 4  0x00000000006dd784 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*handleReadWriter).WriteFromBlocks
    at pkg/sentry/fs/gofer/handles.go:138
 5  0x00000000006de538 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*inodeFileState).WriteFromBlocksAt
    at pkg/sentry/fs/gofer/inode.go:301
 6  0x00000000003affb0 in gvisor.dev/gvisor/pkg/sentry/fs/fsutil.(*writer).WriteFromBlocks
    at pkg/sentry/fs/fsutil/host_mappable.go:210
 7  0x00000000004033e0 in gvisor.dev/gvisor/pkg/safemem.Writer.WriteFromBlocks-fm
    at pkg/safemem/io.go:46
 8  0x00000000003db314 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withInternalMappings
    at pkg/sentry/mm/io.go:506
 9  0x00000000003dba08 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withVecInternalMappings
    at pkg/sentry/mm/io.go:575
10  0x00000000003d9f14 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).CopyInTo
    at pkg/sentry/mm/io.go:309
11  0x00000000003afe94 in gvisor.dev/gvisor/pkg/usermem.IOSequence.CopyInTo
    at pkg/usermem/usermem.go:514
12  0x00000000003afe94 in gvisor.dev/gvisor/pkg/sentry/fs/fsutil.(*HostMappable).Write
    at pkg/sentry/fs/fsutil/host_mappable.go:197
13  0x00000000006db464 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*fileOperations).Write
    at pkg/sentry/fs/gofer/file.go:252
14  0x000000000031f78c in gvisor.dev/gvisor/pkg/sentry/fs.(*File).Writev
    at pkg/sentry/fs/file.go:306
15  0x0000000000597b28 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.writev
    at pkg/sentry/syscalls/linux/sys_write.go:262
16  0x0000000000596470 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.Write
    at pkg/sentry/syscalls/linux/sys_write.go:72
17  0x0000000000522ea4 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).executeSyscall
    at pkg/sentry/kernel/task_syscall.go:104
18  0x0000000000523c5c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallInvoke
    at pkg/sentry/kernel/task_syscall.go:239
19  0x00000000005238dc in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallEnter
    at pkg/sentry/kernel/task_syscall.go:199
20  0x00000000005233e0 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscall
    at pkg/sentry/kernel/task_syscall.go:174
21  0x0000000000518e00 in gvisor.dev/gvisor/pkg/sentry/kernel.(*runApp).execute
    at pkg/sentry/kernel/task_run.go:282
22  0x0000000000517d9c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).run
    at pkg/sentry/kernel/task_run.go:97
23  0x0000000000077c84 in runtime.goexit
    at src/runtime/asm_arm64.s:1136
(dlv) c
I am trying to figure out the whole code path of a write system call from application(the hello-world docker image) under KVM platform.

I find that the control flow actually goes into

Write -- pkg/sentry/fs/host/file.go

Eventually, after a long calling chain, it reaches

Write -- pkg/fd/fd.go
(dlv) b fd/fd.go:80
Breakpoint 2 set at 0x286970 for gvisor.dev/gvisor/pkg/fd.(*ReadWriter).Write() pkg/fd/fd.go:80
(dlv) b fd/fd.go:110
Breakpoint 3 set at 0x286b40 for gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110
(dlv) c
> gvisor.dev/gvisor/pkg/fd.(*ReadWriter).Write() pkg/fd/fd.go:80 (hits goroutine(102):1 total:1) (PC: 0x286970)
Warning: debugging optimized function
(dlv) bt
 0  0x0000000000286970 in gvisor.dev/gvisor/pkg/fd.(*ReadWriter).Write
    at pkg/fd/fd.go:80
 1  0x0000000000159dd4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.writeFromBlock
    at pkg/safemem/io.go:295
 2  0x0000000000159bb4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.WriteFromBlocks
    at pkg/safemem/io.go:281
 3  0x000000000015c480 in gvisor.dev/gvisor/pkg/safemem.(*FromIOWriter).WriteFromBlocks
    at <autogenerated>:1
 4  0x00000000004033e0 in gvisor.dev/gvisor/pkg/safemem.Writer.WriteFromBlocks-fm
    at pkg/safemem/io.go:46
 5  0x00000000003db314 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withInternalMappings
    at pkg/sentry/mm/io.go:506
 6  0x00000000003dba08 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withVecInternalMappings
    at pkg/sentry/mm/io.go:575
 7  0x00000000003d9f14 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).CopyInTo
    at pkg/sentry/mm/io.go:309
 8  0x000000000069e060 in gvisor.dev/gvisor/pkg/usermem.IOSequence.CopyInTo
    at pkg/usermem/usermem.go:514
 9  0x000000000069e060 in gvisor.dev/gvisor/pkg/sentry/fs/host.(*fileOperations).Write
    at pkg/sentry/fs/host/file.go:208
10  0x00000000006a2c90 in gvisor.dev/gvisor/pkg/sentry/fs/host.(*TTYFileOperations).Write
    at pkg/sentry/fs/host/tty.go:113
11  0x000000000031f78c in gvisor.dev/gvisor/pkg/sentry/fs.(*File).Writev
    at pkg/sentry/fs/file.go:306
12  0x0000000000597b28 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.writev
    at pkg/sentry/syscalls/linux/sys_write.go:262
13  0x0000000000596470 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.Write
    at pkg/sentry/syscalls/linux/sys_write.go:72
14  0x0000000000522ea4 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).executeSyscall
    at pkg/sentry/kernel/task_syscall.go:104
15  0x0000000000523c5c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallInvoke
    at pkg/sentry/kernel/task_syscall.go:239
16  0x00000000005238dc in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallEnter
    at pkg/sentry/kernel/task_syscall.go:199
17  0x00000000005233e0 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscall
    at pkg/sentry/kernel/task_syscall.go:174
18  0x0000000000518e00 in gvisor.dev/gvisor/pkg/sentry/kernel.(*runApp).execute
    at pkg/sentry/kernel/task_run.go:282
19  0x0000000000517d9c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).run
    at pkg/sentry/kernel/task_run.go:97
20  0x0000000000077c84 in runtime.goexit
    at src/runtime/asm_arm64.s:1136
(dlv) c
> gvisor.dev/gvisor/pkg/fd.(*ReadWriter).Write() pkg/fd/fd.go:80 (hits goroutine(102):2 total:2) (PC: 0x286970)
Warning: debugging optimized function
(dlv) c
> gvisor.dev/gvisor/pkg/fd.(*ReadWriter).Write() pkg/fd/fd.go:80 (hits goroutine(102):3 total:3) (PC: 0x286970)
Warning: debugging optimized function
(dlv) clearall
Breakpoint 1 cleared at 0x9685b0 for gvisor.dev/gvisor/runsc/fsgofer.(*localFile).Open() runsc/fsgofer/fsgofer.go:381
Breakpoint 2 cleared at 0x286970 for gvisor.dev/gvisor/pkg/fd.(*ReadWriter).Write() pkg/fd/fd.go:80
Breakpoint 3 cleared at 0x286b40 for gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110
(dlv) b fd/fd.go:110
Breakpoint 4 set at 0x286b40 for gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110
(dlv) c
> gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110 (hits goroutine(102):1 total:1) (PC: 0x286b40)
Warning: debugging optimized function
(dlv) bt
 0  0x0000000000286b40 in gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt
    at pkg/fd/fd.go:110
 1  0x000000000069c3a4 in gvisor.dev/gvisor/pkg/secio.(*SectionWriter).Write
    at pkg/secio/secio.go:84
 2  0x0000000000159dd4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.writeFromBlock
    at pkg/safemem/io.go:295
 3  0x0000000000159bb4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.WriteFromBlocks
    at pkg/safemem/io.go:281
 4  0x00000000006dd784 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*handleReadWriter).WriteFromBlocks
    at pkg/sentry/fs/gofer/handles.go:138
 5  0x00000000006de538 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*inodeFileState).WriteFromBlocksAt
    at pkg/sentry/fs/gofer/inode.go:301
 6  0x00000000003affb0 in gvisor.dev/gvisor/pkg/sentry/fs/fsutil.(*writer).WriteFromBlocks
    at pkg/sentry/fs/fsutil/host_mappable.go:210
 7  0x00000000004033e0 in gvisor.dev/gvisor/pkg/safemem.Writer.WriteFromBlocks-fm
    at pkg/safemem/io.go:46
 8  0x00000000003db314 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withInternalMappings
    at pkg/sentry/mm/io.go:506
 9  0x00000000003dba08 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withVecInternalMappings
    at pkg/sentry/mm/io.go:575
10  0x00000000003d9f14 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).CopyInTo
    at pkg/sentry/mm/io.go:309
11  0x00000000003afe94 in gvisor.dev/gvisor/pkg/usermem.IOSequence.CopyInTo
    at pkg/usermem/usermem.go:514
12  0x00000000003afe94 in gvisor.dev/gvisor/pkg/sentry/fs/fsutil.(*HostMappable).Write
    at pkg/sentry/fs/fsutil/host_mappable.go:197
13  0x00000000006db464 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*fileOperations).Write
    at pkg/sentry/fs/gofer/file.go:252
14  0x000000000031f78c in gvisor.dev/gvisor/pkg/sentry/fs.(*File).Writev
    at pkg/sentry/fs/file.go:306
15  0x0000000000597b28 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.writev
    at pkg/sentry/syscalls/linux/sys_write.go:262
16  0x0000000000596470 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.Write
    at pkg/sentry/syscalls/linux/sys_write.go:72
17  0x0000000000522ea4 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).executeSyscall
    at pkg/sentry/kernel/task_syscall.go:104
18  0x0000000000523c5c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallInvoke
    at pkg/sentry/kernel/task_syscall.go:239
19  0x00000000005238dc in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallEnter
    at pkg/sentry/kernel/task_syscall.go:199
20  0x00000000005233e0 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscall
    at pkg/sentry/kernel/task_syscall.go:174
21  0x0000000000518e00 in gvisor.dev/gvisor/pkg/sentry/kernel.(*runApp).execute
    at pkg/sentry/kernel/task_run.go:282
22  0x0000000000517d9c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).run
    at pkg/sentry/kernel/task_run.go:97
23  0x0000000000077c84 in runtime.goexit
    at src/runtime/asm_arm64.s:1136

 SCM_RIGHTS

The gofer mediates file system access, but may pass a FD to the sandbox via SCM_RIGHTS for regular files.

dlv  gofer 进程

root@cloud:~# docker run -it --runtime=runsc-kvm  -v share:/share --name test  --rm  debian /bin/bash
 
root@a6a7c81dcfe9:/share# exit
exit
 
runsc/cmd/gofer.go:213:
func runServers(ats []p9.Attacher, ioFDs []int) {
        // Run the loops and wait for all to exit.
        var wg sync.WaitGroup
        for i, ioFD := range ioFDs {
                wg.Add(1)
                go func(ioFD int, at p9.Attacher) {
                        socket, err := unet.NewSocket(ioFD)
                        if err != nil {
                                Fatalf("creating server on FD %d: %v", ioFD, err)
                        }
                        s := p9.NewServer(at)
                        if err := s.Handle(socket); err != nil {
                                Fatalf("P9 server returned error. Gofer is shutting down. FD: %d, err: %v", ioFD, err)
                        }
                        wg.Done()
                }(ioFD, ats[i])
        }
        wg.Wait()
        log.Infof("All 9P servers exited.")
}
// NewServer returns a new server.
func NewServer(attacher Attacher) *Server {
        return &Server{
                attacher: attacher,
                pathTree: newPathNode(),
        }
}
// Handle handles a single connection.
func (s *Server) Handle(conn *unet.Socket) error {
        cs := &connState{
                server: s,
                fids:   make(map[FID]*fidRef),
                tags:   make(map[Tag]chan struct{}),
                conn:   conn,
        }
        defer cs.stop()

        // Serve requests from conn in the current goroutine; handleRequests() will
        // create more goroutines as needed.
        cs.handleRequests()

        return nil
}

root@cloud:~# dlv attach 944937
Type 'help' for list of commands.
(dlv) b p9/server.go:532
Breakpoint 1 set at 0x2e4ea0 for gvisor.dev/gvisor/pkg/p9.(*connState).handleRequest() pkg/p9/server.go:532
(dlv) c
> gvisor.dev/gvisor/pkg/p9.(*connState).handleRequest() pkg/p9/server.go:532 (hits goroutine(19):1 total:1) (PC: 0x2e4ea0)
Warning: debugging optimized function
(dlv) bt
0  0x00000000002e4ea0 in gvisor.dev/gvisor/pkg/p9.(*connState).handleRequest
   at pkg/p9/server.go:532
1  0x00000000002e5478 in gvisor.dev/gvisor/pkg/p9.(*connState).handleRequests
   at pkg/p9/server.go:590
2  0x00000000002e5788 in gvisor.dev/gvisor/pkg/p9.(*Server).Handle
   at pkg/p9/server.go:645
3  0x00000000009900f4 in gvisor.dev/gvisor/runsc/cmd.runServers.func1
   at runsc/cmd/gofer.go:224
4  0x0000000000077c84 in runtime.goexit
   at src/runtime/asm_arm64.s:1136
(dlv) n
> gvisor.dev/gvisor/pkg/p9.(*connState).handleRequest() pkg/p9/server.go:526 (PC: 0x2e4ec4)
Warning: debugging optimized function
(dlv) list
> gvisor.dev/gvisor/pkg/p9.(*connState).handleRequest() pkg/p9/server.go:526 (PC: 0x2e4ec4)
Warning: debugging optimized function
Command failed: open pkg/p9/server.go: no such file or directory
(dlv) n
> gvisor.dev/gvisor/pkg/p9.(*connState).handleRequest() pkg/p9/server.go:533 (PC: 0x2e4ef4)
Warning: debugging optimized function
(dlv) p m
gvisor.dev/gvisor/pkg/p9.message(*gvisor.dev/gvisor/pkg/p9.Tclunk) *{FID: 77}
(dlv) p cs
*gvisor.dev/gvisor/pkg/p9.connState {
        server: *gvisor.dev/gvisor/pkg/p9.Server {
                attacher: gvisor.dev/gvisor/pkg/p9.Attacher(*gvisor.dev/gvisor/runsc/fsgofer.attachPoint) ...,
                pathTree: *(*"gvisor.dev/gvisor/pkg/p9.pathNode")(0x400048e000),
                renameMu: (*"gvisor.dev/gvisor/pkg/sync.RWMutex")(0x400048c0d8),},
        fidMu: gvisor.dev/gvisor/pkg/sync.Mutex {
                m: (*"gvisor.dev/gvisor/pkg/sync.CrossGoroutineMutex")(0x4000490008),},
        fids: map[gvisor.dev/gvisor/pkg/p9.FID]*gvisor.dev/gvisor/pkg/p9.fidRef [
                4: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e410), 
                64: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40002148c0), 
                67: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40002144b0), 
                75: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000214ff0), 
                5: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e550), 
                39: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018e5f0), 
                50: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f270), 
                73: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000214e10), 
                2: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e190), 
                19: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048f6d0), 
                28: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400081a7d0), 
                37: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018e3c0), 
                15: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048f220), 
                38: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018e4b0), 
                61: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000126a50), 
                68: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40002145a0), 
                70: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000214af0), 
                14: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048f130), 
                18: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048f590), 
                42: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018e9b0), 
                45: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018ed70), 
                72: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000214cd0), 
                9: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048ea50), 
                16: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048f310), 
                48: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f040), 
                49: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f130), 
                60: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000126960), 
                69: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40002149b0), 
                6: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e690), 
                20: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048f7c0), 
                24: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400081a3c0), 
                47: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018ef50), 
                53: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000126320), 
                77: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f9f0), 
                76: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018fae0), 
                12: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048ef00), 
                13: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048eff0), 
                29: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400081a8c0), 
                57: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000214140), 
                11: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048ee10), 
                8: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e910), 
                10: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048eb90), 
                43: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018eaf0), 
                46: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018ee60), 
                52: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40001261e0), 
                54: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000126460), 
                79: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018fd10), 
                41: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018e870), 
                51: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f360), 
                56: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40001266e0), 
                66: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f540), 
                22: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400081a190), 
                36: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018e2d0), 
                23: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400081a280), 
                30: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400081aa00), 
                33: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40007aa0a0), 
                44: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018ec30), 
                65: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f450), 
                1: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e0a0), 
                55: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40001265a0), 
                59: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40001267d0), 
                63: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40002147d0), 
                71: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000214be0), 
                3: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e2d0), 
                ...+14 more
        ],
        tagMu: gvisor.dev/gvisor/pkg/sync.Mutex {
                m: (*"gvisor.dev/gvisor/pkg/sync.CrossGoroutineMutex")(0x4000490018),},
        tags: map[gvisor.dev/gvisor/pkg/p9.Tag]chan struct {} [
                1: {
                        qcount: 0,
                        dataqsiz: 0,
                        buf: *[0]struct struct {} [],
                        elemsize: 0,
                        closed: 0,
                        elemtype: *runtime._type {size: 0, ptrdata: 0, hash: 670477339, tflag: tflagExtraStar|tflagRegularMemory (10), align: 1, fieldAlign: 1, kind: 25, equal: runtime.memequal0, gcdata: *1, str: 54665, ptrToThis: 498784},
                        sendx: 0,
                        recvx: 0,
                        recvq: waitq<struct {}> {
                                first: *sudog<struct {}> nil,
                                last: *sudog<struct {}> nil,},
                        sendq: waitq<struct {}> {
                                first: *sudog<struct {}> nil,
                                last: *sudog<struct {}> nil,},
                        lock: runtime.mutex {
                                lockRankStruct: runtime.lockRankStruct {},
                                key: 0,},}, 
        ],
        messageSize: 1048576,
        version: 12,
        pendingWg: sync.WaitGroup {
                noCopy: sync.noCopy {},
                state1: [3]uint32 [0,0,0],},
        recvMu: gvisor.dev/gvisor/pkg/sync.Mutex {
                m: (*"gvisor.dev/gvisor/pkg/sync.CrossGoroutineMutex")(0x400049003c),},
        recvIdle: 0,
        recvShutdown: false,
        sendMu: gvisor.dev/gvisor/pkg/sync.Mutex {
                m: (*"gvisor.dev/gvisor/pkg/sync.CrossGoroutineMutex")(0x400049004c),},
        conn: *gvisor.dev/gvisor/pkg/unet.Socket {
                gate: (*"gvisor.dev/gvisor/pkg/gate.Gate")(0x400048c000),
                fd: 6,
                efd: 22,
                race: *int32 nil,},
        channelMu: gvisor.dev/gvisor/pkg/sync.Mutex {
                m: (*"gvisor.dev/gvisor/pkg/sync.CrossGoroutineMutex")(0x4000490060),},
        channelWg: sync.WaitGroup {
                noCopy: sync.noCopy {},
                state1: [3]uint32 [0,4,0],},
        channelAlloc: *gvisor.dev/gvisor/pkg/flipcall.PacketWindowAllocator {fd: 23, nextAlloc: 4210688, fileSize: 8388608},
        channels: []*gvisor.dev/gvisor/pkg/p9.channel len: 4, cap: 4, [
                *(*"gvisor.dev/gvisor/pkg/p9.channel")(0x40004a2000),
                *(*"gvisor.dev/gvisor/pkg/p9.channel")(0x40004a20c0),
                *(*"gvisor.dev/gvisor/pkg/p9.channel")(0x40004a2180),
                *(*"gvisor.dev/gvisor/pkg/p9.channel")(0x40004a2240),
        ],}
(dlv) p tag
5

Command

// Register registers a new help command.
func (h *Help) Register(cmd subcommands.Command) {
        h.commands = append(h.commands, cmd)
}

"github.com/google/subcommands"

// A Command represents a single command.
type Command interface {
    // Name returns the name of the command.
    Name() string
    // Synopsis returns a short string (less than one line) describing the command.
    Synopsis() string
    // Usage returns a long string explaining the command and giving usage
    // information.
    Usage() string
    // SetFlags adds the flags for this command to the specified set.
    SetFlags(*flag.FlagSet)
    // Execute executes the command and returns an ExitStatus.
    Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) ExitStatus
}
// Register adds a subcommand to the supported subcommands in the
// specified group. (Help output is sorted and arranged by group
// name.)  The empty string is an acceptable group name; such
// subcommands are explained first before named groups. It is a
// wrapper around DefaultCommander.Register.
func Register(cmd Command, group string) {
    DefaultCommander.Register(cmd, group)
}
func Execute(ctx context.Context, args ...interface{}) ExitStatus {
    return DefaultCommander.Execute(ctx, args...)
}

 

cli/main.go:59: help.Register(new(cmd.Syscalls))
cli/main.go:60: subcommands.Register(help, "")
cli/main.go:61: subcommands.Register(subcommands.FlagsCommand(), "")
cli/main.go:65: subcommands.Register(new(cmd.Install), helperGroup)
cli/main.go:66: subcommands.Register(new(cmd.Uninstall), helperGroup)
cli/main.go:68: // Register user-facing runsc commands.
cli/main.go:69: subcommands.Register(new(cmd.Checkpoint), "")
cli/main.go:70: subcommands.Register(new(cmd.Create), "")
cli/main.go:71: subcommands.Register(new(cmd.Delete), "")
cli/main.go:72: subcommands.Register(new(cmd.Do), "")
cli/main.go:73: subcommands.Register(new(cmd.Events), "")
cli/main.go:74: subcommands.Register(new(cmd.Exec), "")
cli/main.go:75: subcommands.Register(new(cmd.Gofer), "")
cli/main.go:76: subcommands.Register(new(cmd.Kill), "")
cli/main.go:77: subcommands.Register(new(cmd.List), "")
cli/main.go:78: subcommands.Register(new(cmd.Pause), "")
cli/main.go:79: subcommands.Register(new(cmd.PS), "")
cli/main.go:80: subcommands.Register(new(cmd.Restore), "")
cli/main.go:81: subcommands.Register(new(cmd.Resume), "")
cli/main.go:82: subcommands.Register(new(cmd.Run), "")
cli/main.go:83: subcommands.Register(new(cmd.Spec), "")
cli/main.go:84: subcommands.Register(new(cmd.State), "")
cli/main.go:85: subcommands.Register(new(cmd.Start), "")
cli/main.go:86: subcommands.Register(new(cmd.Symbolize), "")
cli/main.go:87: subcommands.Register(new(cmd.Wait), "")
cli/main.go:89: // Register internal commands with the internal group name. This causes
cli/main.go:93: subcommands.Register(new(cmd.Boot), internalGroup)
cli/main.go:94: subcommands.Register(new(cmd.Debug), internalGroup)
cli/main.go:95: subcommands.Register(new(cmd.Gofer), internalGroup)
cli/main.go:96: subcommands.Register(new(cmd.Statefile), internalGroup)
cli/main.go:98: config.RegisterFlags()
var ws syscall.WaitStatus
        subcmdCode := subcommands.Execute(context.Background(), conf, &ws)
        if subcmdCode == subcommands.ExitSuccess {
                log.Infof("Exiting with status: %v", ws)
                if ws.Signaled() {
                        // No good way to return it, emulate what the shell does. Maybe raise
                        // signal to self?
                        os.Exit(128 + int(ws.Signal()))
                }
                os.Exit(ws.ExitStatus())
        }
原文地址:https://www.cnblogs.com/dream397/p/14297135.html