mirror of https://github.com/containers/podman.git
Merge pull request #17522 from giuseppe/relative-idmapping
libpod: support relative positions for idmaps
This commit is contained in:
commit
b8b386b7ea
|
|
@ -40,7 +40,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and
|
||||||
The idmap option supports a custom mapping that can be different than the user namespace used by the container.
|
The idmap option supports a custom mapping that can be different than the user namespace used by the container.
|
||||||
The mapping can be specified after the idmap option like: `idmap=uids=0-1-10#10-11-10;gids=0-100-10`. For each triplet, the first value is the
|
The mapping can be specified after the idmap option like: `idmap=uids=0-1-10#10-11-10;gids=0-100-10`. For each triplet, the first value is the
|
||||||
start of the backing file system IDs that are mapped to the second value on the host. The length of this mapping is given in the third value.
|
start of the backing file system IDs that are mapped to the second value on the host. The length of this mapping is given in the third value.
|
||||||
Multiple ranges are separated with #.
|
Multiple ranges are separated with #. If the specified mapping is prepended with a '@' then the mapping is considered relative to the container
|
||||||
|
user namespace. The host ID for the mapping is changed to account for the relative position of the container user in the container user namespace.
|
||||||
|
|
||||||
Options specific to image:
|
Options specific to image:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,11 +57,17 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseOptionIDs(option string) ([]idtools.IDMap, error) {
|
func parseOptionIDs(ctrMappings []idtools.IDMap, option string) ([]idtools.IDMap, error) {
|
||||||
ranges := strings.Split(option, "#")
|
ranges := strings.Split(option, "#")
|
||||||
ret := make([]idtools.IDMap, len(ranges))
|
ret := make([]idtools.IDMap, len(ranges))
|
||||||
for i, m := range ranges {
|
for i, m := range ranges {
|
||||||
var v idtools.IDMap
|
var v idtools.IDMap
|
||||||
|
|
||||||
|
relative := false
|
||||||
|
if m[0] == '@' {
|
||||||
|
relative = true
|
||||||
|
m = m[1:]
|
||||||
|
}
|
||||||
_, err := fmt.Sscanf(m, "%d-%d-%d", &v.ContainerID, &v.HostID, &v.Size)
|
_, err := fmt.Sscanf(m, "%d-%d-%d", &v.ContainerID, &v.HostID, &v.Size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -69,6 +75,20 @@ func parseOptionIDs(option string) ([]idtools.IDMap, error) {
|
||||||
if v.ContainerID < 0 || v.HostID < 0 || v.Size < 1 {
|
if v.ContainerID < 0 || v.HostID < 0 || v.Size < 1 {
|
||||||
return nil, fmt.Errorf("invalid value for %q", option)
|
return nil, fmt.Errorf("invalid value for %q", option)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if relative {
|
||||||
|
found := false
|
||||||
|
for _, m := range ctrMappings {
|
||||||
|
if v.ContainerID >= m.ContainerID && v.ContainerID < m.ContainerID+m.Size {
|
||||||
|
v.HostID += m.HostID - m.ContainerID
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return nil, fmt.Errorf("could not find a user namespace mapping for the relative mapping %q", option)
|
||||||
|
}
|
||||||
|
}
|
||||||
ret[i] = v
|
ret[i] = v
|
||||||
}
|
}
|
||||||
return ret, nil
|
return ret, nil
|
||||||
|
|
@ -83,12 +103,12 @@ func parseIDMapMountOption(idMappings stypes.IDMappingOptions, option string, in
|
||||||
for _, i := range options {
|
for _, i := range options {
|
||||||
switch {
|
switch {
|
||||||
case strings.HasPrefix(i, "uids="):
|
case strings.HasPrefix(i, "uids="):
|
||||||
uidMap, err = parseOptionIDs(strings.Replace(i, "uids=", "", 1))
|
uidMap, err = parseOptionIDs(idMappings.UIDMap, strings.Replace(i, "uids=", "", 1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
case strings.HasPrefix(i, "gids="):
|
case strings.HasPrefix(i, "gids="):
|
||||||
gidMap, err = parseOptionIDs(strings.Replace(i, "gids=", "", 1))
|
gidMap, err = parseOptionIDs(idMappings.GIDMap, strings.Replace(i, "gids=", "", 1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,18 @@ import (
|
||||||
var hookPath string
|
var hookPath string
|
||||||
|
|
||||||
func TestParseOptionIDs(t *testing.T) {
|
func TestParseOptionIDs(t *testing.T) {
|
||||||
_, err := parseOptionIDs("uids=100-200-2")
|
idMap := []idtools.IDMap{
|
||||||
|
{
|
||||||
|
ContainerID: 0,
|
||||||
|
HostID: 1,
|
||||||
|
Size: 10000,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := parseOptionIDs(idMap, "uids=100-200-2")
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
mappings, err := parseOptionIDs("100-200-2")
|
mappings, err := parseOptionIDs(idMap, "100-200-2")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.NotNil(t, mappings)
|
assert.NotNil(t, mappings)
|
||||||
|
|
||||||
|
|
@ -31,7 +39,7 @@ func TestParseOptionIDs(t *testing.T) {
|
||||||
assert.Equal(t, mappings[0].HostID, 200)
|
assert.Equal(t, mappings[0].HostID, 200)
|
||||||
assert.Equal(t, mappings[0].Size, 2)
|
assert.Equal(t, mappings[0].Size, 2)
|
||||||
|
|
||||||
mappings, err = parseOptionIDs("100-200-2#300-400-5")
|
mappings, err = parseOptionIDs(idMap, "100-200-2#300-400-5")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.NotNil(t, mappings)
|
assert.NotNil(t, mappings)
|
||||||
|
|
||||||
|
|
@ -44,6 +52,23 @@ func TestParseOptionIDs(t *testing.T) {
|
||||||
assert.Equal(t, mappings[1].ContainerID, 300)
|
assert.Equal(t, mappings[1].ContainerID, 300)
|
||||||
assert.Equal(t, mappings[1].HostID, 400)
|
assert.Equal(t, mappings[1].HostID, 400)
|
||||||
assert.Equal(t, mappings[1].Size, 5)
|
assert.Equal(t, mappings[1].Size, 5)
|
||||||
|
|
||||||
|
mappings, err = parseOptionIDs(idMap, "@100-200-2#@300-400-5")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, mappings)
|
||||||
|
|
||||||
|
assert.Equal(t, len(mappings), 2)
|
||||||
|
|
||||||
|
assert.Equal(t, mappings[0].ContainerID, 100)
|
||||||
|
assert.Equal(t, mappings[0].HostID, 201)
|
||||||
|
assert.Equal(t, mappings[0].Size, 2)
|
||||||
|
|
||||||
|
assert.Equal(t, mappings[1].ContainerID, 300)
|
||||||
|
assert.Equal(t, mappings[1].HostID, 401)
|
||||||
|
assert.Equal(t, mappings[1].Size, 5)
|
||||||
|
|
||||||
|
_, err = parseOptionIDs(idMap, "@10000-20000-2")
|
||||||
|
assert.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseIDMapMountOption(t *testing.T) {
|
func TestParseIDMapMountOption(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue