Skip to content

Commit 7d8ac63

Browse files
committed
cdi: inject mount UID/GID mappings if user NS is in use.
When injecting mounts to a container with user namespaces in use, inject the mounts with UID and GID mappings taken from the OCI Spec. Signed-off-by: Krisztian Litkey <[email protected]>
1 parent e17a161 commit 7d8ac63

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

pkg/cdi/container-edits.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"fmt"
2222
"os"
2323
"path/filepath"
24+
"slices"
2425
"sort"
2526
"strings"
2627

@@ -114,9 +115,18 @@ func (e *ContainerEdits) Apply(spec *oci.Spec) error {
114115
}
115116

116117
if len(e.Mounts) > 0 {
118+
var (
119+
uids []oci.LinuxIDMapping
120+
gids []oci.LinuxIDMapping
121+
)
122+
123+
if specHasUserNamespace(spec) {
124+
uids = slices.Clone(spec.Linux.UIDMappings)
125+
gids = slices.Clone(spec.Linux.GIDMappings)
126+
}
117127
for _, m := range e.Mounts {
118128
specgen.RemoveMount(m.ContainerPath)
119-
specgen.AddMount((&Mount{m}).toOCI())
129+
specgen.AddMount((&Mount{m}).toOCI(withMountIDMappings(uids, gids)))
120130
}
121131
sortMounts(&specgen)
122132
}
@@ -387,3 +397,16 @@ func (m orderedMounts) Swap(i, j int) {
387397
func (m orderedMounts) parts(i int) int {
388398
return strings.Count(filepath.Clean(m[i].Destination), string(os.PathSeparator))
389399
}
400+
401+
// specHasUserNamespace returns true ifthe OCI Spec has a Linux UserNamespace.
402+
func specHasUserNamespace(spec *oci.Spec) bool {
403+
if spec == nil || spec.Linux == nil {
404+
return false
405+
}
406+
for _, ns := range spec.Linux.Namespaces {
407+
if ns.Type == oci.UserNamespace {
408+
return true
409+
}
410+
}
411+
return false
412+
}

pkg/cdi/oci.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,33 @@ func (h *Hook) toOCI() spec.Hook {
3030
}
3131
}
3232

33+
// Extra OCI mount option to apply to injected mounts.
34+
type extraOCIMountOption func(*spec.Mount)
35+
36+
// withMountIDMappings adds UID and GID mappings for the given mount.
37+
func withMountIDMappings(uid, gid []spec.LinuxIDMapping) extraOCIMountOption {
38+
return func(m *spec.Mount) {
39+
if uid != nil {
40+
m.UIDMappings = uid
41+
}
42+
if gid != nil {
43+
m.GIDMappings = gid
44+
}
45+
}
46+
}
47+
3348
// toOCI returns the opencontainers runtime Spec Mount for this Mount.
34-
func (m *Mount) toOCI() spec.Mount {
35-
return spec.Mount{
49+
func (m *Mount) toOCI(options ...extraOCIMountOption) spec.Mount {
50+
om := spec.Mount{
3651
Source: m.HostPath,
3752
Destination: m.ContainerPath,
3853
Options: m.Options,
3954
Type: m.Type,
4055
}
56+
for _, o := range options {
57+
o(&om)
58+
}
59+
return om
4160
}
4261

4362
// toOCI returns the opencontainers runtime Spec LinuxDevice for this DeviceNode.

0 commit comments

Comments
 (0)