[lxc-devel] [lxd/master] Bugfixes
stgraber on Github
lxc-bot at linuxcontainers.org
Fri Feb 24 00:45:59 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170224/f3fa74e3/attachment.bin>
-------------- next part --------------
From 3cee68ae69df77b922680d3def03a786728c99d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 23 Feb 2017 18:08:45 -0500
Subject: [PATCH 1/4] idmap: Drop GetOwner
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
shared/idmapset_linux.go | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/shared/idmapset_linux.go b/shared/idmapset_linux.go
index 8a3ebf3..b2784ab 100644
--- a/shared/idmapset_linux.go
+++ b/shared/idmapset_linux.go
@@ -319,11 +319,6 @@ func (m IdmapSet) ShiftFromNs(uid int, gid int) (int, int) {
return m.doShiftIntoNs(uid, gid, "out")
}
-func GetOwner(path string) (int, int, error) {
- uid, gid, _, _, _, _, err := GetFileStat(path)
- return uid, gid, err
-}
-
func (set *IdmapSet) doUidshiftIntoContainer(dir string, testmode bool, how string) error {
// Expand any symlink before the final path component
tmp := filepath.Dir(dir)
@@ -335,7 +330,7 @@ func (set *IdmapSet) doUidshiftIntoContainer(dir string, testmode bool, how stri
dir = strings.TrimRight(dir, "/")
convert := func(path string, fi os.FileInfo, err error) (e error) {
- uid, gid, err := GetOwner(path)
+ uid, gid, _, _, _, _, err := GetFileStat(path)
if err != nil {
return err
}
From ea711b7a191c4aaaf471fdf132034e9af189fa08 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 23 Feb 2017 18:33:47 -0500
Subject: [PATCH 2/4] Remove debugging during idmap changes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/container_lxc.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 336d3db..8e93cad 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -1572,7 +1572,7 @@ func (c *containerLXC) startCommon() (string, error) {
}
if !reflect.DeepEqual(idmap, lastIdmap) {
- shared.LogDebugf("Container idmap changed, remapping: %s => %s", lastIdmap, idmap)
+ shared.LogDebugf("Container idmap changed, remapping")
err := c.StorageStart()
if err != nil {
From 8b8aa238a3ba94d5d77d7f00ec4053d3e880c460 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 23 Feb 2017 19:44:40 -0500
Subject: [PATCH 3/4] idmap: Implement Usable() functions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
shared/idmapset_linux.go | 113 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+)
diff --git a/shared/idmapset_linux.go b/shared/idmapset_linux.go
index b2784ab..6565842 100644
--- a/shared/idmapset_linux.go
+++ b/shared/idmapset_linux.go
@@ -7,10 +7,22 @@ import (
"os/exec"
"path"
"path/filepath"
+ "sort"
"strconv"
"strings"
)
+type IdRange struct {
+ Isuid bool
+ Isgid bool
+ Startid int
+ Endid int
+}
+
+func (i *IdRange) Contains(id int) bool {
+ return id >= i.Startid && id <= i.Endid
+}
+
/*
* One entry in id mapping set - a single range of either
* uid or gid mappings.
@@ -83,6 +95,40 @@ func (e *IdmapEntry) Intersects(i IdmapEntry) bool {
return false
}
+func (e *IdmapEntry) Usable() error {
+ kernelIdmap, err := CurrentIdmapSet()
+ if err != nil {
+ return err
+ }
+
+ kernelRanges, err := kernelIdmap.ValidRanges()
+ if err != nil {
+ return err
+ }
+
+ valid := false
+ for _, kernelRange := range kernelRanges {
+ if kernelRange.Isuid != e.Isuid {
+ continue
+ }
+
+ if kernelRange.Isgid != e.Isgid {
+ continue
+ }
+
+ if kernelRange.Contains(e.Hostid) && kernelRange.Contains(e.Hostid+e.Maprange-1) {
+ valid = true
+ break
+ }
+ }
+
+ if !valid {
+ return fmt.Errorf("The '%s' map can't work in the current user namespace.", e.ToLxcString())
+ }
+
+ return nil
+}
+
func (e *IdmapEntry) parse(s string) error {
split := strings.Split(s, ":")
var err error
@@ -184,6 +230,22 @@ func (m IdmapSet) Len() int {
return len(m.Idmap)
}
+func (m IdmapSet) Swap(i, j int) {
+ m.Idmap[i], m.Idmap[j] = m.Idmap[j], m.Idmap[i]
+}
+
+func (m IdmapSet) Less(i, j int) bool {
+ if m.Idmap[i].Isuid != m.Idmap[j].Isuid {
+ return m.Idmap[i].Isuid == true
+ }
+
+ if m.Idmap[i].Isgid != m.Idmap[j].Isgid {
+ return m.Idmap[i].Isgid == true
+ }
+
+ return m.Idmap[i].Nsid < m.Idmap[j].Nsid
+}
+
func (m IdmapSet) Intersects(i IdmapEntry) bool {
for _, e := range m.Idmap {
if i.Intersects(e) {
@@ -202,6 +264,57 @@ func (m IdmapSet) HostidsIntersect(i IdmapEntry) bool {
return false
}
+func (m IdmapSet) Usable() error {
+ for _, e := range m.Idmap {
+ err := e.Usable()
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (m IdmapSet) ValidRanges() ([]*IdRange, error) {
+ ranges := []*IdRange{}
+
+ // Sort the map
+ idmap := IdmapSet{}
+ err := DeepCopy(&m, &idmap)
+ if err != nil {
+ return nil, err
+ }
+ sort.Sort(idmap)
+
+ for _, mapEntry := range idmap.Idmap {
+ var entry *IdRange
+ for _, idEntry := range ranges {
+ if mapEntry.Isuid != idEntry.Isuid || mapEntry.Isgid != idEntry.Isgid {
+ continue
+ }
+
+ if idEntry.Endid+1 == mapEntry.Nsid {
+ entry = idEntry
+ break
+ }
+ }
+
+ if entry != nil {
+ entry.Endid = entry.Endid + mapEntry.Maprange
+ continue
+ }
+
+ ranges = append(ranges, &IdRange{
+ Isuid: mapEntry.Isuid,
+ Isgid: mapEntry.Isgid,
+ Startid: mapEntry.Nsid,
+ Endid: mapEntry.Nsid + mapEntry.Maprange - 1,
+ })
+ }
+
+ return ranges, nil
+}
+
/* AddSafe adds an entry to the idmap set, breaking apart any ranges that the
* new idmap intersects with in the process.
*/
From 4d9832d21142bca9a372df5c4474835c01072c96 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 23 Feb 2017 19:44:54 -0500
Subject: [PATCH 4/4] Check for the validity of the id maps at startup
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #2885
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/daemon.go | 32 ++++++++++++++++++++++++++++----
1 file changed, 28 insertions(+), 4 deletions(-)
diff --git a/lxd/daemon.go b/lxd/daemon.go
index dc3d0ab..0cf27ab 100644
--- a/lxd/daemon.go
+++ b/lxd/daemon.go
@@ -798,12 +798,36 @@ func (d *Daemon) Init() error {
/* Read the uid/gid allocation */
d.IdmapSet, err = shared.DefaultIdmapSet()
if err != nil {
- shared.LogWarn("Error reading idmap", log.Ctx{"err": err.Error()})
+ shared.LogWarn("Error reading default idmap", log.Ctx{"err": err.Error()})
shared.LogWarnf("Only privileged containers will be able to run")
+ d.IdmapSet = nil
} else {
- shared.LogInfof("Available uid/gid map:")
- for _, lxcmap := range d.IdmapSet.ToLxcString() {
- shared.LogInfof(strings.TrimRight(" - "+lxcmap, "\n"))
+ kernelIdmapSet, err := shared.CurrentIdmapSet()
+ if err == nil {
+ shared.LogInfof("Kernel uid/gid map:")
+ for _, lxcmap := range kernelIdmapSet.ToLxcString() {
+ shared.LogInfof(strings.TrimRight(" - "+lxcmap, "\n"))
+ }
+ }
+
+ shared.LogInfof("Configured LXD uid/gid map:")
+ for _, lxcmap := range d.IdmapSet.Idmap {
+ suffix := ""
+
+ if lxcmap.Usable() != nil {
+ suffix = " (unusable)"
+ }
+
+ for _, lxcEntry := range lxcmap.ToLxcString() {
+ shared.LogInfof(" - %s%s", strings.TrimRight(lxcEntry, "\n"), suffix)
+ }
+ }
+
+ err = d.IdmapSet.Usable()
+ if err != nil {
+ shared.LogWarnf("One or more uid/gid map entry isn't usable (typically due to nesting)")
+ shared.LogWarnf("Only privileged containers will be able to run")
+ d.IdmapSet = nil
}
}
More information about the lxc-devel
mailing list