Repository: google/gvisor
File: pkg/sentry/control/proc.go (Go)

Code before:
	if initArgs.MountNamespace != nil {
		// initArgs must hold a reference on MountNamespace, which will
		// be donated to the new process in CreateProcess.
		initArgs.MountNamespace.IncRef()
	}
	ctx := initArgs.NewContext(proc.Kernel)

	// Import file descriptors.
	var fdTable *kernel.FDTable
	if args.FDTable != nil {
		fdTable = args.FDTable
		// reference borrowed from the caller
	} else {
		fdTable = proc.Kernel.NewFDTable()
		defer fdTable.DecRef(ctx)
	}
	initArgs.FDTable = fdTable

	// 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().MountNamespace()
		initArgs.MountNamespace.IncRef()
	}
	mntnsCu := cleanup.Make(func() { initArgs.MountNamespace.DecRef(ctx) })
	defer mntnsCu.Clean()

	fdMap, execFD, err := args.unpackFiles()
	if err != nil {
		return nil, 0, nil, fmt.Errorf("creating fd map: %w", err)
	}
	defer func() {
		for _, hostFD := range fdMap {
			_ = hostFD.Close()
		}
	}()

	if execFD != nil {
		if initArgs.Filename != "" {
			return nil, 0, nil, fmt.Errorf("process must either be started from a file or a filename, not both")
		}
		file, err := host.NewFD(ctx, proc.Kernel.HostMount(), execFD.FD(), &host.NewFDOptions{
			Readonly:     true,
			Savable:      true,
			VirtualOwner: true,
			UID:          args.KUID,
			GID:          args.KGID,
		})
		if err != nil {

Review comment (suggestion):
Move line 240-246 up to line 221 and the `mntnsCu` stuff should also go there. That way the `IncRef()` can happen outside the `if` condition and the corresponding defer Decref happens right after it (less error prone):
```
	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()
	mntnsCu := cleanup.Make(func() { initArgs.MountNamespace.DecRef(ctx) })
	defer mntnsCu.Clean()
	...
```

Code after:
	ctx := initArgs.NewContext(proc.Kernel)

	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()
	mntnsCu := cleanup.Make(func() { initArgs.MountNamespace.DecRef(ctx) })
	defer mntnsCu.Clean()

	// Import file descriptors.
	var fdTable *kernel.FDTable
	if args.FDTable != nil {
		fdTable = args.FDTable
		// reference borrowed from the caller
	} else {
		fdTable = proc.Kernel.NewFDTable()
		defer fdTable.DecRef(ctx)
	}
	initArgs.FDTable = fdTable

	fdMap, execFD, err := args.unpackFiles()
	if err != nil {
		return nil, 0, nil, fmt.Errorf("creating fd map: %w", err)
	}
	defer func() {
		for _, hostFD := range fdMap {
			_ = hostFD.Close()
		}
	}()

	if execFD != nil {
		if initArgs.Filename != "" {
			return nil, 0, nil, fmt.Errorf("process must either be started from a file or a filename, not both")
		}
		file, err := host.NewFD(ctx, proc.Kernel.HostMount(), execFD.FD(), &host.NewFDOptions{
			Readonly:     true,
			Savable:      true,
			VirtualOwner: true,
			UID:          args.KUID,
			GID:          args.KGID,
		})
		if err != nil {
			return nil, 0, nil, err
		}
		defer file.DecRef(ctx)
		execFD.Release()
		initArgs.File = file
	} else {