Skip to content

Cred type finalization can cause SIGSEGV #553

Closed
@mstergianis

Description

@mstergianis

Hi there,

In using the library I was able to cause a panic in the go runtime. It appears as though a Cred is being freed twice. It appears as though when you use a cred for ssh, libgit2 cleans up the cred that it creates, for example see https://github.com/libgit2/libgit2/blob/172239021f7ba04fe7327647b213799853a9eb89/src/transports/ssh.c#L684-L685. However, git.Cred structs have a finalizer attached to them by default

git2go/credentials.go

Lines 28 to 32 in a32375a

func newCred() *Cred {
cred := &Cred{}
runtime.SetFinalizer(cred, (*Cred).Free)
return cred
}
.

package main

import (
	"errors"
	"io/ioutil"
	"log"
	"runtime"

	git "github.com/libgit2/git2go/v29"
)

func main() {
	cloneOptions := &git.CloneOptions{
		FetchOptions: &git.FetchOptions{
			RemoteCallbacks: git.RemoteCallbacks{
				CredentialsCallback:      credCallbackGenerator(false), // change the bool to true to prevent panic
				CertificateCheckCallback: certificateCheckCallback,
			},
		},
	}

	tempDir, err := ioutil.TempDir("./", "cloned-repo-")
	must(err)

	repo, err := git.Clone("git@github.com:githubtraining/hellogitworld.git", tempDir, cloneOptions)
	must(err)

	runtime.GC()
	log.Println(repo)
}

func must(err error) {
	if err != nil {
		panic(err)
	}
}

func credCallbackGenerator(shouldUnsetFinalize bool) func(url string, username string, allowedTypes git.CredType) (*git.Cred, error) {
	return func(url string, username string, allowedTypes git.CredType) (cred *git.Cred, err error) {
		if (allowedTypes & git.CredTypeSshKey) == git.CredTypeSshKey {
			cred, err = git.NewCredSshKeyFromAgent(username)
		} else {
			cred, err = nil, errors.New("only unsupported allowed types")
		}

		if shouldUnsetFinalize && cred != nil {
			runtime.SetFinalizer(cred, nil)
		}

		return cred, err
	}
}

func certificateCheckCallback(cert *git.Certificate, valid bool, hostname string) git.ErrorCode {
	return 0
}

On my machine, this exhibits the behaviour I am describing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions