Skip to content

Commit

Permalink
Merge pull request #1327 from stgraber/idmap
Browse files Browse the repository at this point in the history
Fix idmap issues
  • Loading branch information
hallyn authored Oct 22, 2024
2 parents 941ca3a + c3dcb98 commit f28bc83
Showing 1 changed file with 66 additions and 82 deletions.
148 changes: 66 additions & 82 deletions internal/server/instance/drivers/driver_lxc.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,15 +269,7 @@ func lxcCreate(s *state.State, args db.InstanceArgs, p api.Project, op *operatio
var idmapSet *idmap.Set
base := int64(0)
if !d.IsPrivileged() {
idmapSet, base, err = findIdmap(
s,
args.Name,
d.expandedConfig["security.idmap.isolated"],
d.expandedConfig["security.idmap.base"],
d.expandedConfig["security.idmap.size"],
d.expandedConfig["raw.idmap"],
)

idmapSet, base, err = d.findIdmap()
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -446,85 +438,93 @@ type lxc struct {
idmapset *idmap.Set
}

func idmapSize(state *state.State, isolatedStr string, size string) (int64, error) {
isolated := false
if util.IsTrue(isolatedStr) {
isolated = true
}
var idmapLock sync.Mutex

var idMapSize int64
if size == "" || size == "auto" {
if isolated {
idMapSize = 65536
func (d *lxc) findIdmap() (*idmap.Set, int64, error) {
idmapSize := func(size string) (int64, error) {
var idMapSize int64
if size == "" || size == "auto" {
if util.IsTrue(d.expandedConfig["security.idmap.isolated"]) {
idMapSize = 65536
} else {
if len(d.state.OS.IdmapSet.Entries) != 2 {
return 0, fmt.Errorf("Bad initial idmap: %v", d.state.OS.IdmapSet)
}

idMapSize = d.state.OS.IdmapSet.Entries[0].MapRange
}
} else {
if len(state.OS.IdmapSet.Entries) != 2 {
return 0, fmt.Errorf("Bad initial idmap: %v", state.OS.IdmapSet)
size, err := strconv.ParseInt(size, 10, 64)
if err != nil {
return 0, err
}

idMapSize = state.OS.IdmapSet.Entries[0].MapRange
}
} else {
size, err := strconv.ParseInt(size, 10, 64)
if err != nil {
return 0, err
idMapSize = size
}

idMapSize = size
return idMapSize, nil
}

return idMapSize, nil
}

var idmapLock sync.Mutex

func findIdmap(s *state.State, cName string, isolatedStr string, configBase string, configSize string, rawIdmap string) (*idmap.Set, int64, error) {
isolated := false
if util.IsTrue(isolatedStr) {
isolated = true
}

rawMaps, err := idmap.NewSetFromIncusIDMap(rawIdmap)
rawMaps, err := idmap.NewSetFromIncusIDMap(d.expandedConfig["raw.idmap"])
if err != nil {
return nil, 0, err
}

if !isolated {
newIdmapset := idmap.Set{Entries: make([]idmap.Entry, len(s.OS.IdmapSet.Entries))}
copy(newIdmapset.Entries, s.OS.IdmapSet.Entries)
mkIdmap := func(offset int64, size int64) (*idmap.Set, error) {
set := &idmap.Set{Entries: []idmap.Entry{
{IsUID: true, NSID: 0, HostID: offset, MapRange: size},
{IsGID: true, NSID: 0, HostID: offset, MapRange: size},
}}

for _, ent := range rawMaps.Entries {
err := newIdmapset.AddSafe(ent)
err := set.AddSafe(ent)
if err != nil && err == idmap.ErrHostIDIsSubID {
return nil, 0, err
return nil, err
}
}

return &newIdmapset, 0, nil
return set, nil
}

size, err := idmapSize(s, isolatedStr, configSize)
if err != nil {
return nil, 0, err
}
if !util.IsTrue(d.expandedConfig["security.idmap.isolated"]) {
// Create a new set based from the global one.
newIdmapset := idmap.Set{Entries: make([]idmap.Entry, len(d.state.OS.IdmapSet.Entries))}
copy(newIdmapset.Entries, d.state.OS.IdmapSet.Entries)

mkIdmap := func(offset int64, size int64) (*idmap.Set, error) {
set := &idmap.Set{Entries: []idmap.Entry{
{IsUID: true, NSID: 0, HostID: offset, MapRange: size},
{IsGID: true, NSID: 0, HostID: offset, MapRange: size},
}}
// Restrict the range sizes if specified.
if d.expandedConfig["security.idmap.size"] != "" {
size, err := idmapSize(d.expandedConfig["security.idmap.size"])
if err != nil {
return nil, 0, err
}

for k, ent := range newIdmapset.Entries {
if ent.MapRange < size {
continue
}

newIdmapset.Entries[k].MapRange = size
}
}

// Apply the raw idmap entries.
for _, ent := range rawMaps.Entries {
err := set.AddSafe(ent)
err := newIdmapset.AddSafe(ent)
if err != nil && err == idmap.ErrHostIDIsSubID {
return nil, err
return nil, 0, err
}
}

return set, nil
return &newIdmapset, 0, nil
}

if configBase != "" {
offset, err := strconv.ParseInt(configBase, 10, 64)
size, err := idmapSize(d.expandedConfig["security.idmap.size"])
if err != nil {
return nil, 0, err
}

if d.expandedConfig["security.idmap.base"] != "" {
offset, err := strconv.ParseInt(d.expandedConfig["security.idmap.base"], 10, 64)
if err != nil {
return nil, 0, err
}
Expand All @@ -540,23 +540,21 @@ func findIdmap(s *state.State, cName string, isolatedStr string, configBase stri
idmapLock.Lock()
defer idmapLock.Unlock()

cts, err := instance.LoadNodeAll(s, instancetype.Container)
cts, err := instance.LoadNodeAll(d.state, instancetype.Container)
if err != nil {
return nil, 0, err
}

offset := s.OS.IdmapSet.Entries[0].HostID + 65536
offset := d.state.OS.IdmapSet.Entries[0].HostID + 65536

mapentries := idmap.ByHostID{}
for _, container := range cts {
if container.Type() != instancetype.Container {
continue
}

name := container.Name()

/* Don't change our map Just Because. */
if name == cName {
if container.ID() == d.id {
continue
}

Expand All @@ -576,7 +574,7 @@ func findIdmap(s *state.State, cName string, isolatedStr string, configBase stri
}
}

cSize, err := idmapSize(s, container.ExpandedConfig()["security.idmap.isolated"], container.ExpandedConfig()["security.idmap.size"])
cSize, err := idmapSize(container.ExpandedConfig()["security.idmap.size"])
if err != nil {
return nil, 0, err
}
Expand Down Expand Up @@ -619,7 +617,7 @@ func findIdmap(s *state.State, cName string, isolatedStr string, configBase stri
offset = mapentries.Entries[i].HostID + mapentries.Entries[i].MapRange
}

if offset+size < s.OS.IdmapSet.Entries[0].HostID+s.OS.IdmapSet.Entries[0].MapRange {
if offset+size <= d.state.OS.IdmapSet.Entries[0].HostID+d.state.OS.IdmapSet.Entries[0].MapRange {
set, err := mkIdmap(offset, size)
if err != nil && err == idmap.ErrHostIDIsSubID {
return nil, 0, err
Expand Down Expand Up @@ -1932,14 +1930,7 @@ func (d *lxc) startCommon() (string, []func() error, error) {
// Check if we need to change idmap.
if nextMap != nil && d.state.OS.IdmapSet != nil && !d.state.OS.IdmapSet.Includes(nextMap) {
// Update the idmap.
idmapSet, base, err := findIdmap(
d.state,
d.Name(),
d.expandedConfig["security.idmap.isolated"],
d.expandedConfig["security.idmap.base"],
d.expandedConfig["security.idmap.size"],
d.expandedConfig["raw.idmap"],
)
idmapSet, base, err := d.findIdmap()
if err != nil {
return "", nil, fmt.Errorf("Failed to get ID map: %w", err)
}
Expand Down Expand Up @@ -4669,14 +4660,7 @@ func (d *lxc) Update(args db.InstanceArgs, userRequested bool) error {
base := int64(0)
if !d.IsPrivileged() {
// Update the idmap.
idmapSet, base, err = findIdmap(
d.state,
d.Name(),
d.expandedConfig["security.idmap.isolated"],
d.expandedConfig["security.idmap.base"],
d.expandedConfig["security.idmap.size"],
d.expandedConfig["raw.idmap"],
)
idmapSet, base, err = d.findIdmap()
if err != nil {
return fmt.Errorf("Failed to get ID map: %w", err)
}
Expand Down

0 comments on commit f28bc83

Please sign in to comment.