The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/3789
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Move idmap-related functions to the `shared/idmap` package. Fixes #3787
From 662161d239e152f017fa27a9fd6c03a5f9e44432 Mon Sep 17 00:00:00 2001 From: Alberto Donato <[email protected]> Date: Fri, 8 Sep 2017 12:00:38 +0200 Subject: [PATCH] shared: move idmap/acl functions to a separate package Signed-off-by: Alberto Donato <[email protected]> --- fuidshift/main.go | 12 +-- lxd/container.go | 5 +- lxd/container_lxc.go | 33 +++--- lxd/container_lxc_utils.go | 12 +-- lxd/main_activateifneeded.go | 3 +- lxd/main_init.go | 3 +- lxd/migrate.go | 21 ++-- lxd/storage.go | 9 +- lxd/storage_btrfs.go | 3 +- lxd/storage_ceph_migration.go | 3 +- lxd/storage_dir.go | 3 +- lxd/storage_lvm.go | 3 +- lxd/storage_migration.go | 3 +- lxd/storage_mock.go | 4 +- lxd/storage_zfs.go | 3 +- lxd/sys/os.go | 3 +- lxd/util/sys.go | 8 +- shared/{ => idmap}/idmapset_linux.go | 18 ++-- shared/{ => idmap}/idmapset_linux_test.go | 2 +- shared/idmap/shift_linux.go | 170 ++++++++++++++++++++++++++++++ shared/util_linux.go | 145 +------------------------ 21 files changed, 254 insertions(+), 212 deletions(-) rename shared/{ => idmap}/idmapset_linux.go (97%) rename shared/{ => idmap}/idmapset_linux_test.go (99%) create mode 100644 shared/idmap/shift_linux.go diff --git a/fuidshift/main.go b/fuidshift/main.go index 63eb2ffb1..a9fa1382a 100644 --- a/fuidshift/main.go +++ b/fuidshift/main.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/lxc/lxd/shared" + "github.com/lxc/lxd/shared/idmap" ) func help(me string, status int) { @@ -35,7 +35,7 @@ func run() error { } directory := os.Args[1] - idmap := shared.IdmapSet{} + idmapSet := idmap.IdmapSet{} testmode := false reverse := false @@ -48,14 +48,14 @@ func run() error { testmode = true default: var err error - idmap, err = idmap.Append(os.Args[pos]) + idmapSet, err = idmapSet.Append(os.Args[pos]) if err != nil { return err } } } - if idmap.Len() == 0 { + if idmapSet.Len() == 0 { fmt.Printf("No idmaps given\n") help(os.Args[0], 1) } @@ -66,7 +66,7 @@ func run() error { } if reverse { - return idmap.UidshiftFromContainer(directory, testmode) + return idmapSet.UidshiftFromContainer(directory, testmode) } - return idmap.UidshiftIntoContainer(directory, testmode) + return idmapSet.UidshiftIntoContainer(directory, testmode) } diff --git a/lxd/container.go b/lxd/container.go index 1be7f95a1..bde60418a 100644 --- a/lxd/container.go +++ b/lxd/container.go @@ -18,6 +18,7 @@ import ( "github.com/lxc/lxd/lxd/types" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/osarch" ) @@ -494,8 +495,8 @@ type container interface { StorageStart() (bool, error) StorageStop() (bool, error) Storage() storage - IdmapSet() (*shared.IdmapSet, error) - LastIdmapSet() (*shared.IdmapSet, error) + IdmapSet() (*idmap.IdmapSet, error) + LastIdmapSet() (*idmap.IdmapSet, error) TemplateApply(trigger string) error StateObject() *state.State } diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go index d2628583c..eba02ad72 100644 --- a/lxd/container_lxc.go +++ b/lxd/container_lxc.go @@ -30,6 +30,7 @@ import ( "github.com/lxc/lxd/lxd/util" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/logger" "github.com/lxc/lxd/shared/osarch" @@ -331,7 +332,7 @@ func containerLXCCreate(s *state.State, args db.ContainerArgs) (container, error c.storage = cStorage // Setup initial idmap config - var idmap *shared.IdmapSet + var idmap *idmap.IdmapSet base := int64(0) if !c.IsPrivileged() { idmap, base, err = findIdmap( @@ -457,7 +458,7 @@ type containerLXC struct { // Cache c *lxc.Container state *state.State - idmapset *shared.IdmapSet + idmapset *idmap.IdmapSet // Storage storage storage @@ -544,7 +545,7 @@ func idmapSize(state *state.State, isolatedStr string, size string) (int64, erro var idmapLock sync.Mutex -func parseRawIdmap(value string) ([]shared.IdmapEntry, error) { +func parseRawIdmap(value string) ([]idmap.IdmapEntry, error) { getRange := func(r string) (int64, int64, error) { entries := strings.Split(r, "-") if len(entries) > 2 { @@ -570,7 +571,7 @@ func parseRawIdmap(value string) ([]shared.IdmapEntry, error) { return base, size, nil } - ret := shared.IdmapSet{} + ret := idmap.IdmapSet{} for _, line := range strings.Split(value, "\n") { if line == "" { @@ -596,7 +597,7 @@ func parseRawIdmap(value string) ([]shared.IdmapEntry, error) { return nil, fmt.Errorf("idmap ranges of different sizes %s", line) } - entry := shared.IdmapEntry{ + entry := idmap.IdmapEntry{ Hostid: outsideBase, Nsid: insideBase, Maprange: insideSize, @@ -630,7 +631,7 @@ func parseRawIdmap(value string) ([]shared.IdmapEntry, error) { return ret.Idmap, nil } -func findIdmap(state *state.State, cName string, isolatedStr string, configBase string, configSize string, rawIdmap string) (*shared.IdmapSet, int64, error) { +func findIdmap(state *state.State, cName string, isolatedStr string, configBase string, configSize string, rawIdmap string) (*idmap.IdmapSet, int64, error) { isolated := false if shared.IsTrue(isolatedStr) { isolated = true @@ -642,7 +643,7 @@ func findIdmap(state *state.State, cName string, isolatedStr string, configBase } if !isolated { - newIdmapset := shared.IdmapSet{Idmap: make([]shared.IdmapEntry, len(state.OS.IdmapSet.Idmap))} + newIdmapset := idmap.IdmapSet{Idmap: make([]idmap.IdmapEntry, len(state.OS.IdmapSet.Idmap))} copy(newIdmapset.Idmap, state.OS.IdmapSet.Idmap) for _, ent := range rawMaps { @@ -657,8 +658,8 @@ func findIdmap(state *state.State, cName string, isolatedStr string, configBase return nil, 0, err } - mkIdmap := func(offset int64, size int64) *shared.IdmapSet { - set := &shared.IdmapSet{Idmap: []shared.IdmapEntry{ + mkIdmap := func(offset int64, size int64) *idmap.IdmapSet { + set := &idmap.IdmapSet{Idmap: []idmap.IdmapEntry{ {Isuid: true, Nsid: 0, Hostid: offset, Maprange: size}, {Isgid: true, Nsid: 0, Hostid: offset, Maprange: size}, }} @@ -689,7 +690,7 @@ func findIdmap(state *state.State, cName string, isolatedStr string, configBase offset := state.OS.IdmapSet.Idmap[0].Hostid + 65536 - mapentries := shared.ByHostid{} + mapentries := idmap.ByHostid{} for _, name := range cs { /* Don't change our map Just Because. */ if name == cName { @@ -722,7 +723,7 @@ func findIdmap(state *state.State, cName string, isolatedStr string, configBase return nil, 0, err } - mapentries = append(mapentries, &shared.IdmapEntry{Hostid: int64(cBase), Maprange: cSize}) + mapentries = append(mapentries, &idmap.IdmapEntry{Hostid: int64(cBase), Maprange: cSize}) } sort.Sort(mapentries) @@ -3368,7 +3369,7 @@ func (c *containerLXC) Update(args db.ContainerArgs, userRequested bool) error { } if shared.StringInSlice("security.idmap.isolated", changedConfig) || shared.StringInSlice("security.idmap.base", changedConfig) || shared.StringInSlice("security.idmap.size", changedConfig) || shared.StringInSlice("raw.idmap", changedConfig) || shared.StringInSlice("security.privileged", changedConfig) { - var idmap *shared.IdmapSet + var idmap *idmap.IdmapSet base := int64(0) if !c.IsPrivileged() { // update the idmap @@ -6859,7 +6860,7 @@ func (c *containerLXC) Id() int { return c.id } -func (c *containerLXC) IdmapSet() (*shared.IdmapSet, error) { +func (c *containerLXC) IdmapSet() (*idmap.IdmapSet, error) { var err error if c.idmapset != nil { @@ -6896,7 +6897,7 @@ func (c *containerLXC) LocalDevices() types.Devices { return c.localDevices } -func (c *containerLXC) idmapsetFromConfig(k string) (*shared.IdmapSet, error) { +func (c *containerLXC) idmapsetFromConfig(k string) (*idmap.IdmapSet, error) { lastJsonIdmap := c.LocalConfig()[k] if lastJsonIdmap == "" { @@ -6906,7 +6907,7 @@ func (c *containerLXC) idmapsetFromConfig(k string) (*shared.IdmapSet, error) { return idmapsetFromString(lastJsonIdmap) } -func (c *containerLXC) NextIdmapSet() (*shared.IdmapSet, error) { +func (c *containerLXC) NextIdmapSet() (*idmap.IdmapSet, error) { if c.localConfig["volatile.idmap.next"] != "" { return c.idmapsetFromConfig("volatile.idmap.next") } else if c.IsPrivileged() { @@ -6918,7 +6919,7 @@ func (c *containerLXC) NextIdmapSet() (*shared.IdmapSet, error) { return nil, fmt.Errorf("Unable to determine the idmap") } -func (c *containerLXC) LastIdmapSet() (*shared.IdmapSet, error) { +func (c *containerLXC) LastIdmapSet() (*idmap.IdmapSet, error) { return c.idmapsetFromConfig("volatile.last_state.idmap") } diff --git a/lxd/container_lxc_utils.go b/lxd/container_lxc_utils.go index e4c288fc2..9da660f39 100644 --- a/lxd/container_lxc_utils.go +++ b/lxd/container_lxc_utils.go @@ -3,12 +3,12 @@ package main import ( "encoding/json" - "github.com/lxc/lxd/shared" + "github.com/lxc/lxd/shared/idmap" ) -func idmapsetFromString(idmap string) (*shared.IdmapSet, error) { - lastIdmap := new(shared.IdmapSet) - err := json.Unmarshal([]byte(idmap), &lastIdmap.Idmap) +func idmapsetFromString(idmapString string) (*idmap.IdmapSet, error) { + lastIdmap := new(idmap.IdmapSet) + err := json.Unmarshal([]byte(idmapString), &lastIdmap.Idmap) if err != nil { return nil, err } @@ -20,8 +20,8 @@ func idmapsetFromString(idmap string) (*shared.IdmapSet, error) { return lastIdmap, nil } -func idmapsetToJSON(idmap *shared.IdmapSet) (string, error) { - idmapBytes, err := json.Marshal(idmap.Idmap) +func idmapsetToJSON(idmapSet *idmap.IdmapSet) (string, error) { + idmapBytes, err := json.Marshal(idmapSet.Idmap) if err != nil { return "", err } diff --git a/lxd/main_activateifneeded.go b/lxd/main_activateifneeded.go index 592e04a30..0a277b07c 100644 --- a/lxd/main_activateifneeded.go +++ b/lxd/main_activateifneeded.go @@ -7,6 +7,7 @@ import ( "github.com/lxc/lxd/client" "github.com/lxc/lxd/lxd/db" "github.com/lxc/lxd/shared" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/logger" ) @@ -45,7 +46,7 @@ func cmdActivateIfNeeded(args *Args) error { } // Load the idmap for unprivileged containers - d.os.IdmapSet, err = shared.DefaultIdmapSet() + d.os.IdmapSet, err = idmap.DefaultIdmapSet() if err != nil { return err } diff --git a/lxd/main_init.go b/lxd/main_init.go index 009ea41f5..b09724fae 100644 --- a/lxd/main_init.go +++ b/lxd/main_init.go @@ -16,6 +16,7 @@ import ( "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" "github.com/lxc/lxd/shared/cmd" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/logger" ) @@ -810,7 +811,7 @@ func (cmd *CmdInit) askDefaultPrivileged() int { // Detect lack of uid/gid defaultPrivileged := -1 needPrivileged := false - idmapset, err := shared.DefaultIdmapSet() + idmapset, err := idmap.DefaultIdmapSet() if err != nil || len(idmapset.Idmap) == 0 || idmapset.Usable() != nil { needPrivileged = true } diff --git a/lxd/migrate.go b/lxd/migrate.go index 16bcc6fa3..59fa03faa 100644 --- a/lxd/migrate.go +++ b/lxd/migrate.go @@ -24,6 +24,7 @@ import ( "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/logger" ) @@ -854,16 +855,16 @@ func (c *migrationSink) Do(migrateOp *operation) error { restore := make(chan error) go func(c *migrationSink) { imagesDir := "" - srcIdmap := new(shared.IdmapSet) - - for _, idmap := range header.Idmap { - e := shared.IdmapEntry{ - Isuid: *idmap.Isuid, - Isgid: *idmap.Isgid, - Nsid: int64(*idmap.Nsid), - Hostid: int64(*idmap.Hostid), - Maprange: int64(*idmap.Maprange)} - srcIdmap.Idmap = shared.Extend(srcIdmap.Idmap, e) + srcIdmap := new(idmap.IdmapSet) + + for _, idmapSet := range header.Idmap { + e := idmap.IdmapEntry{ + Isuid: *idmapSet.Isuid, + Isgid: *idmapSet.Isgid, + Nsid: int64(*idmapSet.Nsid), + Hostid: int64(*idmapSet.Hostid), + Maprange: int64(*idmapSet.Maprange)} + srcIdmap.Idmap = idmap.Extend(srcIdmap.Idmap, e) } /* We do the fs receive in parallel so we don't have to reason diff --git a/lxd/storage.go b/lxd/storage.go index ddc680c20..355553261 100644 --- a/lxd/storage.go +++ b/lxd/storage.go @@ -15,6 +15,7 @@ import ( "github.com/lxc/lxd/lxd/state" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/ioprogress" "github.com/lxc/lxd/shared/logger" ) @@ -220,7 +221,7 @@ type storage interface { c container, objects []*Snapshot, conn *websocket.Conn, - srcIdmap *shared.IdmapSet, + srcIdmap *idmap.IdmapSet, op *operation, containerOnly bool) error } @@ -392,7 +393,7 @@ func storagePoolVolumeAttachInit(s *state.State, poolName string, volumeName str poolVolumePut := st.GetStoragePoolVolumeWritable() // get last idmapset - var lastIdmap *shared.IdmapSet + var lastIdmap *idmap.IdmapSet if poolVolumePut.Config["volatile.idmap.last"] != "" { lastIdmap, err = idmapsetFromString(poolVolumePut.Config["volatile.idmap.last"]) if err != nil { @@ -709,14 +710,14 @@ func deleteSnapshotMountpoint(snapshotMountpoint string, snapshotsSymlinkTarget // ShiftIfNecessary sets the volatile.last_state.idmap key to the idmap last // used by the container. -func ShiftIfNecessary(container container, srcIdmap *shared.IdmapSet) error { +func ShiftIfNecessary(container container, srcIdmap *idmap.IdmapSet) error { dstIdmap, err := container.IdmapSet() if err != nil { return err } if dstIdmap == nil { - dstIdmap = new(shared.IdmapSet) + dstIdmap = new(idmap.IdmapSet) } if !reflect.DeepEqual(srcIdmap, dstIdmap) { diff --git a/lxd/storage_btrfs.go b/lxd/storage_btrfs.go index 8c46f174d..0b58dd135 100644 --- a/lxd/storage_btrfs.go +++ b/lxd/storage_btrfs.go @@ -19,6 +19,7 @@ import ( "github.com/lxc/lxd/lxd/util" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/logger" ) @@ -1938,7 +1939,7 @@ func (s *storageBtrfs) MigrationSource(c container, containerOnly bool) (Migrati return driver, nil } -func (s *storageBtrfs) MigrationSink(live bool, container container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, containerOnly bool) error { +func (s *storageBtrfs) MigrationSink(live bool, container container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, containerOnly bool) error { if runningInUserns { return rsyncMigrationSink(live, container, snapshots, conn, srcIdmap, op, containerOnly) } diff --git a/lxd/storage_ceph_migration.go b/lxd/storage_ceph_migration.go index f42b706a1..24179fd6e 100644 --- a/lxd/storage_ceph_migration.go +++ b/lxd/storage_ceph_migration.go @@ -9,6 +9,7 @@ import ( "github.com/lxc/lxd/lxd/db" "github.com/lxc/lxd/shared" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/logger" ) @@ -191,7 +192,7 @@ func (s *storageCeph) MigrationSource(c container, containerOnly bool) (Migratio return &driver, nil } -func (s *storageCeph) MigrationSink(live bool, c container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, containerOnly bool) error { +func (s *storageCeph) MigrationSink(live bool, c container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, containerOnly bool) error { // Check that we received a valid root disk device with a pool property // set. parentStoragePool := "" diff --git a/lxd/storage_dir.go b/lxd/storage_dir.go index 681cbfb31..acdbca417 100644 --- a/lxd/storage_dir.go +++ b/lxd/storage_dir.go @@ -12,6 +12,7 @@ import ( "github.com/lxc/lxd/lxd/db" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/logger" ) @@ -910,7 +911,7 @@ func (s *storageDir) MigrationSource(container container, containerOnly bool) (M return rsyncMigrationSource(container, containerOnly) } -func (s *storageDir) MigrationSink(live bool, container container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, containerOnly bool) error { +func (s *storageDir) MigrationSink(live bool, container container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, containerOnly bool) error { return rsyncMigrationSink(live, container, snapshots, conn, srcIdmap, op, containerOnly) } diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go index ce0107c7b..ece80e331 100644 --- a/lxd/storage_lvm.go +++ b/lxd/storage_lvm.go @@ -11,6 +11,7 @@ import ( "github.com/lxc/lxd/lxd/db" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/logger" ) @@ -1651,7 +1652,7 @@ func (s *storageLvm) MigrationSource(container container, containerOnly bool) (M return rsyncMigrationSource(container, containerOnly) } -func (s *storageLvm) MigrationSink(live bool, container container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, containerOnly bool) error { +func (s *storageLvm) MigrationSink(live bool, container container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, containerOnly bool) error { return rsyncMigrationSink(live, container, snapshots, conn, srcIdmap, op, containerOnly) } diff --git a/lxd/storage_migration.go b/lxd/storage_migration.go index 80dfb2c14..faf7c4f02 100644 --- a/lxd/storage_migration.go +++ b/lxd/storage_migration.go @@ -8,6 +8,7 @@ import ( "github.com/lxc/lxd/lxd/db" "github.com/lxc/lxd/lxd/types" "github.com/lxc/lxd/shared" + "github.com/lxc/lxd/shared/idmap" ) // MigrationStorageSourceDriver defines the functions needed to implement a @@ -122,7 +123,7 @@ func snapshotProtobufToContainerArgs(containerName string, snap *Snapshot) db.Co } } -func rsyncMigrationSink(live bool, container container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, containerOnly bool) error { +func rsyncMigrationSink(live bool, container container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, containerOnly bool) error { ourStart, err := container.StorageStart() if err != nil { return err diff --git a/lxd/storage_mock.go b/lxd/storage_mock.go index b8b7e9656..03b390824 100644 --- a/lxd/storage_mock.go +++ b/lxd/storage_mock.go @@ -5,8 +5,8 @@ import ( "github.com/gorilla/websocket" - "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/logger" ) @@ -211,7 +211,7 @@ func (s *storageMock) PreservesInodes() bool { func (s *storageMock) MigrationSource(container container, containerOnly bool) (MigrationStorageSourceDriver, error) { return nil, fmt.Errorf("not implemented") } -func (s *storageMock) MigrationSink(live bool, container container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, containerOnly bool) error { +func (s *storageMock) MigrationSink(live bool, container container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, containerOnly bool) error { return nil } diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go index d2e85cb1e..594d0f2ad 100644 --- a/lxd/storage_zfs.go +++ b/lxd/storage_zfs.go @@ -17,6 +17,7 @@ import ( "github.com/lxc/lxd/lxd/util" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/logger" "github.com/pborman/uuid" @@ -2114,7 +2115,7 @@ func (s *storageZfs) MigrationSource(ct container, containerOnly bool) (Migratio return &driver, nil } -func (s *storageZfs) MigrationSink(live bool, container container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, containerOnly bool) error { +func (s *storageZfs) MigrationSink(live bool, container container, snapshots []*Snapshot, conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, containerOnly bool) error { poolName := s.getOnDiskPoolName() zfsRecv := func(zfsName string, writeWrapper func(io.WriteCloser) io.WriteCloser) error { zfsFsName := fmt.Sprintf("%s/%s", poolName, zfsName) diff --git a/lxd/sys/os.go b/lxd/sys/os.go index d699ad878..420b6e277 100644 --- a/lxd/sys/os.go +++ b/lxd/sys/os.go @@ -5,6 +5,7 @@ import ( "github.com/lxc/lxd/lxd/util" "github.com/lxc/lxd/shared" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/logger" ) @@ -16,7 +17,7 @@ type OS struct { Architectures []int // Cache of detected system architectures LxcPath string // Path to the $LXD_DIR/containers directory BackingFS string // Backing filesystem of $LXD_DIR/containers - IdmapSet *shared.IdmapSet + IdmapSet *idmap.IdmapSet MockMode bool // If true some APIs will be mocked (for testing) } diff --git a/lxd/util/sys.go b/lxd/util/sys.go index 005a8554a..fa46a5f2b 100644 --- a/lxd/util/sys.go +++ b/lxd/util/sys.go @@ -5,7 +5,7 @@ import ( log "gopkg.in/inconshreveable/log15.v2" - "github.com/lxc/lxd/shared" + "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/logger" "github.com/lxc/lxd/shared/osarch" ) @@ -36,14 +36,14 @@ func GetArchitectures() ([]int, error) { } // GetIdmapSet reads the uid/gid allocation. -func GetIdmapSet() *shared.IdmapSet { - idmapSet, err := shared.DefaultIdmapSet() +func GetIdmapSet() *idmap.IdmapSet { + idmapSet, err := idmap.DefaultIdmapSet() if err != nil { logger.Warn("Error reading default uid/gid map", log.Ctx{"err": err.Error()}) logger.Warnf("Only privileged containers will be able to run") idmapSet = nil } else { - kernelIdmapSet, err := shared.CurrentIdmapSet() + kernelIdmapSet, err := idmap.CurrentIdmapSet() if err == nil { logger.Infof("Kernel uid/gid map:") for _, lxcmap := range kernelIdmapSet.ToLxcString() { diff --git a/shared/idmapset_linux.go b/shared/idmap/idmapset_linux.go similarity index 97% rename from shared/idmapset_linux.go rename to shared/idmap/idmapset_linux.go index da1c59e7e..aa9241c1e 100644 --- a/shared/idmapset_linux.go +++ b/shared/idmap/idmapset_linux.go @@ -1,4 +1,4 @@ -package shared +package idmap import ( "bufio" @@ -11,6 +11,8 @@ import ( "sort" "strconv" "strings" + + "github.com/lxc/lxd/shared" ) type IdRange struct { @@ -307,7 +309,7 @@ func (m IdmapSet) ValidRanges() ([]*IdRange, error) { // Sort the map idmap := IdmapSet{} - err := DeepCopy(&m, &idmap) + err := shared.DeepCopy(&m, &idmap) if err != nil { return nil, err } @@ -397,7 +399,7 @@ func (m IdmapSet) ToLxcString() []string { var lines []string for _, e := range m.Idmap { for _, l := range e.ToLxcString() { - if !StringInSlice(l+"\n", lines) { + if !shared.StringInSlice(l+"\n", lines) { lines = append(lines, l+"\n") } } @@ -478,7 +480,7 @@ func (set *IdmapSet) doUidshiftIntoContainer(dir string, testmode bool, how stri return err } - intUid, intGid, _, _, _, _, err := GetFileStat(path) + intUid, intGid, _, _, _, _, err := shared.GetFileStat(path) if err != nil { return err } @@ -510,7 +512,7 @@ func (set *IdmapSet) doUidshiftIntoContainer(dir string, testmode bool, how stri return nil } - if !PathExists(dir) { + if !shared.PathExists(dir) { return fmt.Errorf("No such file or directory: %q", dir) } @@ -650,7 +652,7 @@ func DefaultIdmapSet() (*IdmapSet, error) { // Check if shadow's uidmap tools are installed newuidmap, _ := exec.LookPath("newuidmap") newgidmap, _ := exec.LookPath("newgidmap") - if newuidmap != "" && newgidmap != "" && PathExists("/etc/subuid") && PathExists("/etc/subgid") { + if newuidmap != "" && newgidmap != "" && shared.PathExists("/etc/subuid") && shared.PathExists("/etc/subgid") { // Parse the shadow uidmap entries, err := getFromShadow("/etc/subuid", "root") if err != nil { @@ -788,7 +790,7 @@ func DefaultIdmapSet() (*IdmapSet, error) { func CurrentIdmapSet() (*IdmapSet, error) { idmapset := new(IdmapSet) - if PathExists("/proc/self/uid_map") { + if shared.PathExists("/proc/self/uid_map") { // Parse the uidmap entries, err := getFromProc("/proc/self/uid_map") if err != nil { @@ -805,7 +807,7 @@ func CurrentIdmapSet() (*IdmapSet, error) { idmapset.Idmap = Extend(idmapset.Idmap, e) } - if PathExists("/proc/self/gid_map") { + if shared.PathExists("/proc/self/gid_map") { // Parse the gidmap entries, err := getFromProc("/proc/self/gid_map") if err != nil { diff --git a/shared/idmapset_linux_test.go b/shared/idmap/idmapset_linux_test.go similarity index 99% rename from shared/idmapset_linux_test.go rename to shared/idmap/idmapset_linux_test.go index d8582c8d9..9fe466caa 100644 --- a/shared/idmapset_linux_test.go +++ b/shared/idmap/idmapset_linux_test.go @@ -1,4 +1,4 @@ -package shared +package idmap import ( "fmt" diff --git a/shared/idmap/shift_linux.go b/shared/idmap/shift_linux.go new file mode 100644 index 000000000..b470da4fb --- /dev/null +++ b/shared/idmap/shift_linux.go @@ -0,0 +1,170 @@ +// +build linux +// +build cgo + +package idmap + +import ( + "fmt" + "os" + "unsafe" +) + +// #cgo LDFLAGS: -lacl +/* +#define _GNU_SOURCE +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/acl.h> + +int shiftowner(char *basepath, char *path, int uid, int gid) { + struct stat sb; + int fd, r; + char fdpath[PATH_MAX]; + char realpath[PATH_MAX]; + + fd = open(path, O_PATH|O_NOFOLLOW); + if (fd < 0 ) { + perror("Failed open"); + return 1; + } + + r = sprintf(fdpath, "/proc/self/fd/%d", fd); + if (r < 0) { + perror("Failed sprintf"); + close(fd); + return 1; + } + + r = readlink(fdpath, realpath, PATH_MAX); + if (r < 0) { + perror("Failed readlink"); + close(fd); + return 1; + } + + if (strlen(realpath) < strlen(basepath)) { + printf("Invalid path, source (%s) is outside of basepath (%s).\n", realpath, basepath); + close(fd); + return 1; + } + + if (strncmp(realpath, basepath, strlen(basepath))) { + printf("Invalid path, source (%s) is outside of basepath (%s).\n", realpath, basepath); + close(fd); + return 1; + } + + r = fstat(fd, &sb); + if (r < 0) { + perror("Failed fstat"); + close(fd); + return 1; + } + + r = fchownat(fd, "", uid, gid, AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW); + if (r < 0) { + perror("Failed chown"); + close(fd); + return 1; + } + + if (!S_ISLNK(sb.st_mode)) { + r = chmod(fdpath, sb.st_mode); + if (r < 0) { + perror("Failed chmod"); + close(fd); + return 1; + } + } + + close(fd); + return 0; +} +*/ +import "C" + +// ShiftOwner updates uid and gid for a file when entering/exiting a namespace +func ShiftOwner(basepath string, path string, uid int, gid int) error { + cbasepath := C.CString(basepath) + defer C.free(unsafe.Pointer(cbasepath)) + + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + + r := C.shiftowner(cbasepath, cpath, C.int(uid), C.int(gid)) + if r != 0 { + return fmt.Errorf("Failed to change ownership of: %s", path) + } + return nil +} + +// ShiftACL updates uid and gid for file ACLs when entering/exiting a namespace +func ShiftACL(path string, shiftIds func(uid int64, gid int64) (int64, int64)) error { + finfo, err := os.Lstat(path) + if err != nil { + return err + } + if finfo.Mode()&os.ModeSymlink != 0 { + return nil + } + + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + + acl := C.acl_get_file(cpath, C.ACL_TYPE_ACCESS) + if acl == nil { + return nil + } + defer C.acl_free(unsafe.Pointer(acl)) + + for entryId := C.ACL_FIRST_ENTRY; ; entryId = C.ACL_NEXT_ENTRY { + var ent C.acl_entry_t + var tag C.acl_tag_t + updateACL := false + + ret := C.acl_get_entry(acl, C.int(entryId), &ent) + if ret != 1 { + break + } + + ret = C.acl_get_tag_type(ent, &tag) + if ret == -1 { + return fmt.Errorf("Failed to change ACLs on %s", path) + } + + idp := (*C.id_t)(C.acl_get_qualifier(ent)) + if idp == nil { + continue + } + + var newId int64 + switch tag { + case C.ACL_USER: + newId, _ = shiftIds((int64)(*idp), -1) + updateACL = true + + case C.ACL_GROUP: + _, newId = shiftIds(-1, (int64)(*idp)) + updateACL = true + } + + if updateACL { + ret = C.acl_set_qualifier(ent, unsafe.Pointer(&newId)) + if ret == -1 { + return fmt.Errorf("Failed to change ACLs on %s", path) + } + ret = C.acl_set_file(cpath, C.ACL_TYPE_ACCESS, acl) + if ret == -1 { + return fmt.Errorf("Failed to change ACLs on %s", path) + } + } + } + return nil +} diff --git a/shared/util_linux.go b/shared/util_linux.go index 26389c7ee..77daf1051 100644 --- a/shared/util_linux.go +++ b/shared/util_linux.go @@ -19,7 +19,7 @@ import ( "github.com/lxc/lxd/shared/logger" ) -// #cgo LDFLAGS: -lutil -lpthread -lacl +// #cgo LDFLAGS: -lutil -lpthread /* #define _GNU_SOURCE #include <errno.h> @@ -36,7 +36,6 @@ import ( #include <sys/stat.h> #include <sys/types.h> #include <sys/un.h> -#include <sys/acl.h> #ifndef AT_SYMLINK_FOLLOW #define AT_SYMLINK_FOLLOW 0x400 @@ -129,71 +128,6 @@ void create_pipe(int *master, int *slave) { *slave = pipefd[1]; } -int shiftowner(char *basepath, char *path, int uid, int gid) { - struct stat sb; - int fd, r; - char fdpath[PATH_MAX]; - char realpath[PATH_MAX]; - - fd = open(path, O_PATH|O_NOFOLLOW); - if (fd < 0 ) { - perror("Failed open"); - return 1; - } - - r = sprintf(fdpath, "/proc/self/fd/%d", fd); - if (r < 0) { - perror("Failed sprintf"); - close(fd); - return 1; - } - - r = readlink(fdpath, realpath, PATH_MAX); - if (r < 0) { - perror("Failed readlink"); - close(fd); - return 1; - } - - if (strlen(realpath) < strlen(basepath)) { - printf("Invalid path, source (%s) is outside of basepath (%s).\n", realpath, basepath); - close(fd); - return 1; - } - - if (strncmp(realpath, basepath, strlen(basepath))) { - printf("Invalid path, source (%s) is outside of basepath (%s).\n", realpath, basepath); - close(fd); - return 1; - } - - r = fstat(fd, &sb); - if (r < 0) { - perror("Failed fstat"); - close(fd); - return 1; - } - - r = fchownat(fd, "", uid, gid, AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW); - if (r < 0) { - perror("Failed chown"); - close(fd); - return 1; - } - - if (!S_ISLNK(sb.st_mode)) { - r = chmod(fdpath, sb.st_mode); - if (r < 0) { - perror("Failed chmod"); - close(fd); - return 1; - } - } - - close(fd); - return 0; -} - int get_poll_revents(int lfd, int timeout, int flags, int *revents, int *saved_errno) { int ret; @@ -239,83 +173,6 @@ func GetPollRevents(fd int, timeout int, flags int) (int, int, error) { return int(ret), int(revents), err } -func ShiftOwner(basepath string, path string, uid int, gid int) error { - cbasepath := C.CString(basepath) - defer C.free(unsafe.Pointer(cbasepath)) - - cpath := C.CString(path) - defer C.free(unsafe.Pointer(cpath)) - - r := C.shiftowner(cbasepath, cpath, C.int(uid), C.int(gid)) - if r != 0 { - return fmt.Errorf("Failed to change ownership of: %s", path) - } - return nil -} - -func ShiftACL(path string, shiftIds func(uid int64, gid int64) (int64, int64)) error { - finfo, err := os.Lstat(path) - if err != nil { - return err - } - if finfo.Mode()&os.ModeSymlink != 0 { - return nil - } - - cpath := C.CString(path) - defer C.free(unsafe.Pointer(cpath)) - - acl := C.acl_get_file(cpath, C.ACL_TYPE_ACCESS) - if acl == nil { - return nil - } - defer C.acl_free(unsafe.Pointer(acl)) - - for entryId := C.ACL_FIRST_ENTRY; ; entryId = C.ACL_NEXT_ENTRY { - var ent C.acl_entry_t - var tag C.acl_tag_t - updateACL := false - - ret := C.acl_get_entry(acl, C.int(entryId), &ent) - if ret != 1 { - break - } - - ret = C.acl_get_tag_type(ent, &tag) - if ret == -1 { - return fmt.Errorf("Failed to change ACLs on %s", path) - } - - idp := (*C.id_t)(C.acl_get_qualifier(ent)) - if idp == nil { - continue - } - - var newId int64 - switch tag { - case C.ACL_USER: - newId, _ = shiftIds((int64)(*idp), -1) - updateACL = true - - case C.ACL_GROUP: - _, newId = shiftIds(-1, (int64)(*idp)) - updateACL = true - } - - if updateACL { - ret = C.acl_set_qualifier(ent, unsafe.Pointer(&newId)) - if ret == -1 { - return fmt.Errorf("Failed to change ACLs on %s", path) - } - ret = C.acl_set_file(cpath, C.ACL_TYPE_ACCESS, acl) - if ret == -1 { - return fmt.Errorf("Failed to change ACLs on %s", path) - } - } - } - return nil -} - func OpenPty(uid, gid int64) (master *os.File, slave *os.File, err error) { fd_master := C.int(-1) fd_slave := C.int(-1)
_______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
