Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create fails when custom dir is specified; possible use-after-free? #161

Open
sblinch opened this issue Apr 6, 2022 · 0 comments
Open

Comments

@sblinch
Copy link

sblinch commented Apr 6, 2022

Create exhibits unexpected behavior if you specify a custom options.BackendSpecs.Dir. I've made this simple modification to examples/create/create.go:

--- create.go.orig      2022-04-06 14:34:24.287690956 -0700
+++ create.go   2022-04-06 14:35:20.088339284 -0700
@@ -8,6 +8,7 @@

 import (
        "flag"
+       "fmt"
        "log"

        "github.com/lxc/go-lxc"
@@ -71,6 +72,7 @@
                }
        }

+       dir := fmt.Sprintf("%s/%s/rootfs",lxcpath,name)
        options := lxc.TemplateOptions{
                Template:             template,
                Distro:               distro,
@@ -81,6 +83,7 @@
                Backend:              backend,
                BackendSpecs: &lxc.BackendStoreSpecs{
                        FSSize: uint64(bdevSize),
+                       Dir: &dir,
                },
        }

This results in:

root@lxc:~# ./create -validation -verbose -distro centos -release 8-Stream -name testy
2022/04/06 14:40:25 Creating container...
Using image from local cache
Unpacking the rootfs
tar: /usr/share/lxc/templates/lxc-download: Cannot open: Not a directory
tar: Error is not recoverable: exiting now
2022/04/06 14:40:25 ERROR: creating the container failed

The created config file then contains:

lxc.log.file = log
lxc.log.level = DEBUG
lxc.rootfs.path = dir:/usr/share/lxc/templates/lxc-download

It seems that the list of arguments internally passed to liblxc somehow gets out-of-sync with what liblxc is expecting.

I haven't had a chance to track down the definitive cause, but I did see something that piqued my interest in container.go:2316 in buildBdevSpecs():

	if o.Dir != nil {
		dir := C.CString(*o.Dir)
		specs.dir = dir
		defer C.free(unsafe.Pointer(dir))
	}

I don't have much experience with cgo so forgive me if I'm misreading this, but if we allocate a C.CString and assign it to specs.dir, isn't it incorrect to then free it on return? Wouldn't this cause the dir field in the returned C.struct_bdev_specs to point to freed memory?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant