Skip to content

Commit

Permalink
fix: randomize lxc container names
Browse files Browse the repository at this point in the history
In situations where concurrent stacker runs are happening on a system,
and they are building containers with the same name,
and they are being done inside a mount namespace,
and the path name given as the roots dir is the same,
but the actual mounted volume is different,

then both stackers will be able to acquire the file lock at
$rootdir/.lock, and will go ahead and start containers named $name,
which will then race to set up the lxc control socket, which is named
after the container name and the rootfs path, which are both the same
here.

The fix is to add some randomness to the lxc container name, which
ensures that the socket won't clash. This should not affect other uses
of the image name, which will still use the un-randomized name.

Signed-off-by: Michael McCracken <mikmccra@cisco.com>
  • Loading branch information
mikemccracken committed Nov 7, 2024
1 parent ad9a694 commit 74db868
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 2 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/cheggaaa/pb/v3 v3.1.2
github.com/containers/image/v5 v5.24.2
github.com/dustin/go-humanize v1.0.1
github.com/google/uuid v1.5.0
github.com/justincormack/go-memfd v0.0.0-20170219213707-6e4af0518993
github.com/klauspost/pgzip v1.2.6
github.com/lxc/go-lxc v0.0.0-20230926171149-ccae595aa49e
Expand Down Expand Up @@ -140,7 +141,6 @@ require (
github.com/google/licensecheck v0.3.1 // indirect
github.com/google/licenseclassifier/v2 v2.0.0 // indirect
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
github.com/gorilla/mux v1.8.1 // indirect
Expand Down
4 changes: 3 additions & 1 deletion pkg/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"syscall"

"github.com/google/uuid"
"github.com/lxc/go-lxc"
"github.com/pkg/errors"
embed_exec "stackerbuild.io/stacker/pkg/embed-exec"
Expand All @@ -36,7 +37,8 @@ func New(sc types.StackerConfig, name string) (*Container, error) {
return nil, errors.WithStack(err)
}

lxcC, err := lxc.NewContainer(name, sc.RootFSDir)
uniqname := fmt.Sprintf("%s-%s", name, uuid.NewString())
lxcC, err := lxc.NewContainer(uniqname, sc.RootFSDir)
if err != nil {
return nil, err
}
Expand Down
37 changes: 37 additions & 0 deletions test/concurrent.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
load helpers

function setup() {
stacker_setup
}

function teardown() {
cleanup
}

@test "concurrent w aliased rootdir" {
cat > stacker.yaml <<"EOF"
robertos:
from:
type: oci
url: ${{BUSYBOX_OCI}}
run: |
sleep ${{SNOOZ}} # make sure they have time to conflict
EOF

mkdir -p 1/roots 1/stacker 2/roots 2/stacker aliased-rootsdir
chmod -R 777 1 2

# simulate shared CI infra where name of sandbox dir is same despite backing store being different

mount --bind 1/roots aliased-rootsdir
${ROOT_DIR}/stacker --debug --roots-dir=aliased-rootsdir --stacker-dir=1/stacker --oci-dir=1/oci --log-file=1.log build --substitute BUSYBOX_OCI=${BUSYBOX_OCI} --substitute SNOOZ=15 &

sleep 5

unshare -m bash <<EOF
mount --bind 2/roots aliased-rootsdir
${ROOT_DIR}/stacker --debug --roots-dir=aliased-rootsdir --stacker-dir=2/stacker --oci-dir=2/oci --log-file=2.log \
build --substitute BUSYBOX_OCI=${BUSYBOX_OCI} --substitute SNOOZ=0
EOF

}

0 comments on commit 74db868

Please sign in to comment.