@@ -245,16 +245,17 @@ func (u *Unikontainer) SetRunningState() error {
245245 return u .saveContainerState ()
246246}
247247
248- func (u * Unikontainer ) SetupNet () (types.NetDevParams , error ) {
249- networkType := u .getNetworkType ()
248+ // SetupNet creates the sandbox's network device (tap) in the current network
249+ // namespace and returns its parameters; uid and gid own the tap device.
250+ func SetupNet (networkType string , uid , gid uint32 ) (types.NetDevParams , error ) {
250251 uniklog .WithField ("network type" , networkType ).Debug ("Retrieved network type" )
251252 netArgs := types.NetDevParams {}
252253 netManager , err := network .NewNetworkManager (networkType )
253254 if err != nil {
254255 return netArgs , fmt .Errorf ("failed to create network manager for %s type: %v" , networkType , err )
255256 }
256257
257- networkInfo , err := netManager .NetworkSetup (u . Spec . Process . User . UID , u . Spec . Process . User . GID )
258+ networkInfo , err := netManager .NetworkSetup (uid , gid )
258259 if err != nil {
259260 // TODO: Handle this case better. We do not need to show an error
260261 // since there was no network in the container. Therefore, we
@@ -443,9 +444,6 @@ func monitorMemoryBytes(defaultMem uint, resources *specs.LinuxResources) uint64
443444 return mem
444445}
445446
446- // buildMonitorSpec assembles the base MonitorSpec: everything the monitor needs
447- // that can be derived from the OCI spec, the container's annotations and the
448- // monitor resources gathered during InitialSetup.
449447func (u * Unikontainer ) buildMonitorSpec (rootfsParams types.RootfsParams , monRes monitorResources ) types.MonitorSpec {
450448 var mSpec types.MonitorSpec
451449
@@ -596,7 +594,7 @@ func (u *Unikontainer) Exec(metrics m.Writer) error {
596594 }
597595
598596 // handle network
599- netArgs , err := u . SetupNet ( )
597+ netArgs , err := SetupNet ( u . getNetworkType (), u . Spec . Process . User . UID , u . Spec . Process . User . GID )
600598 if err != nil {
601599 uniklog .Errorf ("failed to setup network: %v" , err )
602600 return err
@@ -646,20 +644,11 @@ func (u *Unikontainer) Exec(metrics m.Writer) error {
646644 }
647645
648646 // unikernel
649- err = unikernel .Init (unikernelParams )
650- if errors .Is (err , unikernels .ErrUndefinedVersion ) ||
651- errors .Is (err , unikernels .ErrVersionParsing ) {
652- uniklog .WithError (err ).Error ("an error occurred while initializing the unikernel" )
653- } else if err != nil {
654- return err
655- }
656-
657647 // build the unikernel command
658- unikernelCmd , err := unikernel . CommandString ( )
648+ vmmArgs . Command , err = buildUnikernelCommand ( unikernel , unikernelParams )
659649 if err != nil {
660650 return err
661651 }
662- vmmArgs .Command = unikernelCmd
663652
664653 // pivot
665654 _ , err = findNS (u .Spec .Linux .Namespaces , specs .MountNamespace )
@@ -697,38 +686,57 @@ func (u *Unikontainer) Exec(metrics m.Writer) error {
697686 return err
698687 }
699688
700- uniklog .Debug ("calling vmm execve" )
701- metrics .Capture (m .TS18 )
702-
703- // Build the VMM command once and verify it can be constructed successfully.
704- // This ensures we don't report the container as started if command building fails.
689+ // Build the VMM command once and verify it can be constructed successfully, so
690+ // we do not report the container as started if command building fails.
705691 execCmd , err := vmm .BuildExecCmd (vmmArgs , unikernel )
706692 if err != nil {
707693 uniklog .WithError (err ).Error ("failed to build VMM command" )
708694 return err
709695 }
710696
711- // Notify urunc start that the monitor is ready to execute.
712- // We send this after BuildExecCmd succeeds to avoid reporting a container
713- // as started when the VMM command cannot be built.
714- // TODO: The container can still be reported as running if the PreExec step
715- // (e.g., BPF/seccomp filter setup) fails after this point. We should find
716- // a way to handle that case as well.
697+ // Notify urunc start that the monitor is ready to execute, only after the
698+ // command builds so a container is never reported started when it cannot be.
717699 err = u .SendMessage (StartSuccess )
718700 if err != nil {
719701 return err
720702 }
721703
704+ return execMonitor (metrics , vmm , vmmArgs , execCmd )
705+ }
706+
707+ // buildUnikernelCommand initializes the unikernel with the collected parameters
708+ // and returns its command line.
709+ func buildUnikernelCommand (unikernel types.Unikernel , params types.UnikernelParams ) (string , error ) {
710+ err := unikernel .Init (params )
711+ if errors .Is (err , unikernels .ErrUndefinedVersion ) ||
712+ errors .Is (err , unikernels .ErrVersionParsing ) {
713+ uniklog .WithError (err ).Error ("an error occurred while initializing the unikernel" )
714+ } else if err != nil {
715+ return "" , err
716+ }
717+
718+ return unikernel .CommandString ()
719+ }
720+
721+ // execMonitor runs the monitor's pre-exec setup and finally execve's the monitor.
722+ // It does not return on success:
723+ //
724+ // TODO: The container can still be reported as running if the PreExec step
725+ // (e.g., BPF/seccomp filter setup) fails after the caller reported success. We
726+ // should find a way to handle that case as well.
727+ func execMonitor (metrics m.Writer , vmm types.VMM , execArgs types.ExecArgs , execCmd []string ) error {
728+ uniklog .Debug ("calling vmm execve" )
729+ metrics .Capture (m .TS18 )
722730 // Perform any monitor-specific pre-exec setup (e.g., seccomp filters for HVT).
723- err = vmm .PreExec (vmmArgs )
731+ err : = vmm .PreExec (execArgs )
724732 if err != nil {
725733 uniklog .WithError (err ).Error ("failed to perform pre-exec setup" )
726734 return err
727735 }
728736
729737 // Execute the VMM using the command we built earlier.
730738 uniklog .WithField ("command" , execCmd ).Debug ("Ready to execve VMM" )
731- return syscall .Exec (vmm .Path (), execCmd , vmmArgs .Environment ) //nolint: gosec
739+ return syscall .Exec (vmm .Path (), execCmd , execArgs .Environment ) //nolint: gosec
732740}
733741
734742func setupUser (user specs.User ) error {
0 commit comments