Skip to content

Commit 8981af7

Browse files
cmainasurunc-bot[bot]
authored andcommitted
feat(update initrd): Copy files from mount struct inside initrd
The Linux kernel is able to properly read and unpack multiple initrds that are concatenated in a single file. This commit takes advantage of this feature and in the case the Linux guest is using initrd, it appends the files from the mount struct in the container's spec inside the given initrd. PR: #293 Signed-off-by: Charalampos Mainas <cmainas@nubificus.co.uk> Reviewed-by: Anastassios Nanos <ananos@nubificus.co.uk> Approved-by: Anastassios Nanos <ananos@nubificus.co.uk>
1 parent 34df098 commit 8981af7

6 files changed

Lines changed: 111 additions & 2 deletions

File tree

.github/linters/urunc-dict.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,3 +359,7 @@ vhost
359359
libexec
360360
sonarcloud
361361
NOSONAR
362+
cavaliergopher
363+
Msec
364+
Mtim
365+
Nsec

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ URUNC_SRC += $(wildcard $(CURDIR)/pkg/unikontainers/*.go)
6969
URUNC_SRC += $(wildcard $(CURDIR)/pkg/unikontainers/hypervisors/*.go)
7070
URUNC_SRC += $(wildcard $(CURDIR)/pkg/unikontainers/unikernels/*.go)
7171
URUNC_SRC += $(wildcard $(CURDIR)/pkg/unikontainers/types/*.go)
72+
URUNC_SRC += $(wildcard $(CURDIR)/pkg/unikontainers/initrd/*.go)
7273
URUNC_SRC += $(wildcard $(CURDIR)/pkg/network/*.go)
7374
SHIM_SRC := $(wildcard $(CURDIR)/cmd/containerd-shim-urunc-v2/*.go)
7475

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ toolchain go1.24.6
77
require (
88
github.com/BurntSushi/toml v1.5.0
99
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
10+
github.com/cavaliergopher/cpio v1.0.1
1011
github.com/containerd/containerd v1.7.27
1112
github.com/creack/pty v1.1.24
1213
github.com/elastic/go-seccomp-bpf v1.6.0
@@ -55,6 +56,7 @@ require (
5556
github.com/klauspost/compress v1.18.0 // indirect
5657
github.com/mattn/go-colorable v0.1.14 // indirect
5758
github.com/mattn/go-isatty v0.0.20 // indirect
59+
github.com/mdlayher/socket v0.5.1 // indirect
5860
github.com/moby/sys/mountinfo v0.7.2 // indirect
5961
github.com/moby/sys/sequential v0.6.0 // indirect
6062
github.com/moby/sys/user v0.4.0 // indirect

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ github.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWS
88
github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=
99
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
1010
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
11+
github.com/cavaliergopher/cpio v1.0.1 h1:KQFSeKmZhv0cr+kawA3a0xTQCU4QxXF1vhU7P7av2KM=
12+
github.com/cavaliergopher/cpio v1.0.1/go.mod h1:pBdaqQjnvXxdS/6CvNDwIANIFSP0xRKI16PX4xejRQc=
1113
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
1214
github.com/checkpoint-restore/go-criu/v6 v6.3.0 h1:mIdrSO2cPNWQY1truPg6uHLXyKHk3Z5Odx4wjKOASzA=
1315
github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI=
@@ -126,8 +128,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
126128
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
127129
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
128130
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
129-
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
130-
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
131+
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
132+
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
131133
github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk=
132134
github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
133135
github.com/moby/sys/mount v0.3.4 h1:yn5jq4STPztkkzSKpZkLcmjue+bZJ0u2AuQY1iNI1Ww=

pkg/unikontainers/initrd/initrd.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Copyright (c) 2023-2025, Nubificus LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package initrd
16+
17+
import (
18+
"fmt"
19+
"os"
20+
"syscall"
21+
"time"
22+
23+
"github.com/cavaliergopher/cpio"
24+
"github.com/opencontainers/runtime-spec/specs-go"
25+
)
26+
27+
func AddInitrdRecord(w *cpio.Writer, content []byte, fileInfo *syscall.Stat_t, name string) error {
28+
hdr := &cpio.Header{
29+
Name: name,
30+
Mode: cpio.FileMode(fileInfo.Mode),
31+
Uid: int(fileInfo.Uid),
32+
Guid: int(fileInfo.Gid),
33+
ModTime: time.Unix(fileInfo.Mtim.Sec, fileInfo.Mtim.Nsec),
34+
Size: fileInfo.Size,
35+
}
36+
err := w.WriteHeader(hdr)
37+
if err != nil {
38+
return fmt.Errorf("could not write header in initrd: %v", err)
39+
}
40+
_, err = w.Write(content)
41+
if err != nil {
42+
return fmt.Errorf("could not write contents in initrd: %v", err)
43+
}
44+
45+
return nil
46+
}
47+
48+
func AddFileToInitrd(w *cpio.Writer, srcFile string, destFile string) error {
49+
// Get the info of the original file
50+
fi, err := os.Stat(srcFile)
51+
if err != nil {
52+
return fmt.Errorf("Could not Stat file %s: %w", srcFile, err)
53+
}
54+
fileInfo := fi.Sys().(*syscall.Stat_t)
55+
if fi.Mode().IsRegular() {
56+
content, err := os.ReadFile(srcFile)
57+
if err != nil {
58+
return fmt.Errorf("could not read file %s: %w", srcFile, err)
59+
}
60+
err = AddInitrdRecord(w, content, fileInfo, destFile)
61+
if err != nil {
62+
return fmt.Errorf("could not add record for %s: %w", srcFile, err)
63+
}
64+
}
65+
66+
return nil
67+
}
68+
69+
func CopyFileMountsToInitrd(oldInitrd string, mounts []specs.Mount) error {
70+
f, err := os.OpenFile(oldInitrd, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
71+
if err != nil {
72+
return fmt.Errorf("Could not open %s: %v", oldInitrd, err)
73+
}
74+
defer f.Close()
75+
76+
w := cpio.NewWriter(f)
77+
for _, m := range mounts {
78+
if m.Type != "bind" {
79+
continue
80+
}
81+
err = AddFileToInitrd(w, m.Source, m.Destination)
82+
if err != nil {
83+
return fmt.Errorf("Could not add file %s to initrd: %v", m.Source, err)
84+
}
85+
}
86+
err = w.Close()
87+
if err != nil {
88+
return fmt.Errorf("Could not close initrd %v", err)
89+
}
90+
91+
return nil
92+
}

pkg/unikontainers/unikontainers.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333

3434
"github.com/urunc-dev/urunc/pkg/network"
3535
"github.com/urunc-dev/urunc/pkg/unikontainers/hypervisors"
36+
"github.com/urunc-dev/urunc/pkg/unikontainers/initrd"
3637
"github.com/urunc-dev/urunc/pkg/unikontainers/types"
3738
"github.com/urunc-dev/urunc/pkg/unikontainers/unikernels"
3839
"github.com/vishvananda/netlink/nl"
@@ -339,6 +340,13 @@ func (u *Unikontainer) Exec(metrics m.Writer) error {
339340
uniklog.Errorf("could not setup block based rootfs: %v", err)
340341
return err
341342
}
343+
case "initrd":
344+
initrdHostFullPath := filepath.Join(rootfsParams.MonRootfs, rootfsParams.Path)
345+
err = initrd.CopyFileMountsToInitrd(initrdHostFullPath, u.Spec.Mounts)
346+
if err != nil {
347+
uniklog.Errorf("could not update guest's initrd: %v", err)
348+
return err
349+
}
342350
case "virtiofs":
343351
tmpfsSize = chooseTmpfsSize(vmmArgs.MemSizeB)
344352
fallthrough

0 commit comments

Comments
 (0)