@@ -23,6 +23,7 @@ import (
23
23
"os/exec"
24
24
"path/filepath"
25
25
"strings"
26
+ "sync"
26
27
"syscall"
27
28
28
29
"github.com/firecracker-microvm/firecracker-go-sdk"
@@ -46,8 +47,11 @@ type runcJailer struct {
46
47
runcBinaryPath string
47
48
uid uint32
48
49
gid uint32
50
+ once sync.Once
49
51
}
50
52
53
+ var configSpec * specs.Spec
54
+
51
55
func newRuncJailer (ctx context.Context , logger * logrus.Entry , ociBundlePath , runcBinPath string , uid , gid uint32 ) (* runcJailer , error ) {
52
56
l := logger .WithField ("ociBundlePath" , ociBundlePath ).
53
57
WithField ("runcBinaryPath" , runcBinPath )
@@ -75,17 +79,17 @@ func newRuncJailer(ctx context.Context, logger *logrus.Entry, ociBundlePath, run
75
79
76
80
// JailPath returns the base directory from where the jail binary will be ran
77
81
// from
78
- func (j runcJailer ) OCIBundlePath () string {
82
+ func (j * runcJailer ) OCIBundlePath () string {
79
83
return j .ociBundlePath
80
84
}
81
85
82
86
// RootPath returns the root fs of the jailed system.
83
- func (j runcJailer ) RootPath () string {
87
+ func (j * runcJailer ) RootPath () string {
84
88
return filepath .Join (j .OCIBundlePath (), rootfsFolder )
85
89
}
86
90
87
91
// JailPath will return the OCI bundle rootfs path
88
- func (j runcJailer ) JailPath () vm.Dir {
92
+ func (j * runcJailer ) JailPath () vm.Dir {
89
93
return vm .Dir (j .RootPath ())
90
94
}
91
95
@@ -98,6 +102,12 @@ func (j *runcJailer) BuildJailedMachine(cfg *Config, machineConfig *firecracker.
98
102
// Build a new client since BuildJailedRootHandler modifies the socket path value.
99
103
client := firecracker .NewClient (machineConfig .SocketPath , j .logger , machineConfig .Debug )
100
104
105
+ if machineConfig .NetNS == "" {
106
+ if netns := getNetNS (configSpec ); netns != "" {
107
+ machineConfig .NetNS = netns
108
+ }
109
+ }
110
+
101
111
opts := []firecracker.Opt {
102
112
firecracker .WithProcessRunner (j .jailerCommand (vmID , cfg .Debug )),
103
113
firecracker .WithClient (client ),
@@ -213,7 +223,7 @@ func (j *runcJailer) BuildJailedRootHandler(cfg *Config, socketPath *string, vmI
213
223
214
224
// BuildLinkFifoHandler will return a new firecracker.Handler with the function
215
225
// that will allow linking of the fifos making them visible to Firecracker.
216
- func (j runcJailer ) BuildLinkFifoHandler () firecracker.Handler {
226
+ func (j * runcJailer ) BuildLinkFifoHandler () firecracker.Handler {
217
227
return firecracker.Handler {
218
228
Name : jailerFifoHandlerName ,
219
229
Fn : func (ctx context.Context , m * firecracker.Machine ) error {
@@ -239,7 +249,7 @@ func (j runcJailer) BuildLinkFifoHandler() firecracker.Handler {
239
249
240
250
// StubDrivesOptions will return a set of options used to create a new stub
241
251
// drive handler.
242
- func (j runcJailer ) StubDrivesOptions () []stubDrivesOpt {
252
+ func (j * runcJailer ) StubDrivesOptions () []stubDrivesOpt {
243
253
return []stubDrivesOpt {
244
254
func (drives []models.Drive ) error {
245
255
for _ , drive := range drives {
@@ -258,7 +268,7 @@ func (j runcJailer) StubDrivesOptions() []stubDrivesOpt {
258
268
// the jail. For block devices we will use mknod to create the device and then
259
269
// set the correct permissions to ensure visibility in the jail. Regular files
260
270
// will be copied into the jail.
261
- func (j runcJailer ) ExposeFileToJail (srcPath string ) error {
271
+ func (j * runcJailer ) ExposeFileToJail (srcPath string ) error {
262
272
uid := j .uid
263
273
gid := j .gid
264
274
@@ -340,7 +350,7 @@ func copyFile(src, dst string, mode os.FileMode) error {
340
350
return nil
341
351
}
342
352
343
- func (j runcJailer ) jailerCommand (containerName string , isDebug bool ) * exec.Cmd {
353
+ func (j * runcJailer ) jailerCommand (containerName string , isDebug bool ) * exec.Cmd {
344
354
cmd := exec .CommandContext (j .ctx , j .runcBinaryPath , "run" , containerName )
345
355
cmd .Dir = j .OCIBundlePath ()
346
356
@@ -353,36 +363,48 @@ func (j runcJailer) jailerCommand(containerName string, isDebug bool) *exec.Cmd
353
363
}
354
364
355
365
// overwriteConfig will set the proper default values if a field had not been set.
356
- //
357
- // TODO: Add netns
358
- func (j runcJailer ) overwriteConfig (cfg * Config , socketPath , configPath string ) error {
359
- spec := specs.Spec {}
360
- configBytes , err := ioutil .ReadFile (configPath )
361
- if err != nil {
362
- return err
363
- }
366
+ func (j * runcJailer ) overwriteConfig (cfg * Config , socketPath , configPath string ) error {
367
+ var err error
368
+ j .once .Do (func () {
369
+ if configSpec == nil {
370
+ spec := specs.Spec {}
371
+ var configBytes []byte
372
+ configBytes , err = ioutil .ReadFile (configPath )
373
+ if err != nil {
374
+ return
375
+ }
364
376
365
- if err : = json .Unmarshal (configBytes , & spec ); err != nil {
366
- return err
367
- }
377
+ if err = json .Unmarshal (configBytes , & spec ); err != nil {
378
+ return
379
+ }
368
380
369
- if spec .Process .User .UID != 0 ||
370
- spec .Process .User .GID != 0 {
371
- return fmt .Errorf (
372
- "using UID %d and GID %d, these values must not be set" ,
373
- spec .Process .User .UID ,
374
- spec .Process .User .GID ,
375
- )
376
- }
381
+ configSpec = & spec
377
382
378
- spec = j .setDefaultConfigValues (cfg , socketPath , spec )
383
+ if spec .Process .User .UID != 0 ||
384
+ spec .Process .User .GID != 0 {
385
+ err = fmt .Errorf (
386
+ "using UID %d and GID %d, these values must not be set" ,
387
+ spec .Process .User .UID ,
388
+ spec .Process .User .GID ,
389
+ )
390
+ return
391
+ }
379
392
380
- spec .Root .Path = rootfsFolder
381
- spec .Root .Readonly = false
393
+ spec = j .setDefaultConfigValues (cfg , socketPath , spec )
394
+ spec .Root .Path = rootfsFolder
395
+ spec .Root .Readonly = false
396
+ }
397
+ })
398
+
399
+ if err != nil {
400
+ return err
401
+ }
402
+
403
+ spec := * configSpec
382
404
spec .Process .User .UID = j .uid
383
405
spec .Process .User .GID = j .gid
384
406
385
- configBytes , err = json .Marshal (& spec )
407
+ configBytes , err : = json .Marshal (& spec )
386
408
if err != nil {
387
409
return err
388
410
}
@@ -396,7 +418,7 @@ func (j runcJailer) overwriteConfig(cfg *Config, socketPath, configPath string)
396
418
397
419
// setDefaultConfigValues will process the spec file provided and allow any
398
420
// empty/zero values to be replaced with default values.
399
- func (j runcJailer ) setDefaultConfigValues (cfg * Config , socketPath string , spec specs.Spec ) specs.Spec {
421
+ func (j * runcJailer ) setDefaultConfigValues (cfg * Config , socketPath string , spec specs.Spec ) specs.Spec {
400
422
if spec .Process == nil {
401
423
spec .Process = & specs.Process {}
402
424
}
@@ -448,3 +470,17 @@ func mkdirAllWithPermissions(path string, mode os.FileMode, uid, gid uint32) err
448
470
449
471
return nil
450
472
}
473
+
474
+ func getNetNS (spec * specs.Spec ) string {
475
+ if spec == nil {
476
+ return ""
477
+ }
478
+
479
+ for _ , ns := range spec .Linux .Namespaces {
480
+ if ns .Type == "network" {
481
+ return ns .Path
482
+ }
483
+ }
484
+
485
+ return ""
486
+ }
0 commit comments