Skip to content

Commit

Permalink
Merge pull request #6308 from mook-as/win32/certs/copy-unsafe
Browse files Browse the repository at this point in the history
WSL-Helper: Certs: Make a copy of foreign memory
  • Loading branch information
jandubois authored Jan 11, 2024
2 parents de85021 + 765822c commit ae3b6f2
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 1 deletion.
1 change: 1 addition & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ fav
fcb
fdx
featurename
FEEEFEEE
femto
ffi
ficlone
Expand Down
8 changes: 7 additions & 1 deletion src/go/wsl-helper/pkg/certificates/certificates_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,13 @@ func GetSystemCertificates(storeName string) (<-chan Entry, error) {
}
break
}
cert, err := x509.ParseCertificate(unsafe.Slice(certCtx.EncodedCert, certCtx.Length))
// Make a copy of the encoded cert, because the parsed cert may have
// references to the memory (that isn't owned by the GC) and we'll return
// it in a channel, so HeapFree() might get called on it before it's used.
// See #6295 / #6307.
certData := make([]byte, certCtx.Length)
copy(certData, unsafe.Slice(certCtx.EncodedCert, certCtx.Length))
cert, err := x509.ParseCertificate(certData)
if err != nil {
// Skip invalid certs
logrus.Tracef("Skipping invalid certificate %q in %q: %s", getCertName(certCtx), storeName, err)
Expand Down
47 changes: 47 additions & 0 deletions src/go/wsl-helper/pkg/certificates/certificates_windows_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package certificates_test

import (
"bytes"
"crypto/x509"
"encoding/pem"
"testing"

"github.com/rancher-sandbox/rancher-desktop/src/go/wsl-helper/pkg/certificates"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// Test that we don't use memory that we don't own
func TestGetSystemCertificates_UseAfterFree(t *testing.T) {
var certs []*x509.Certificate
ch, err := certificates.GetSystemCertificates("CA")
require.NoError(t, err, "failed to get CA certificates")
for entry := range ch {
if assert.NoError(t, err, entry.Err) {
certs = append(certs, entry.Cert)
}
}
ch, err = certificates.GetSystemCertificates("ROOT")
require.NoError(t, err, "failed to get ROOT certificates")
for entry := range ch {
if assert.NoError(t, err, entry.Err) {
certs = append(certs, entry.Cert)
}
}

// By this point, both channels have been closed, which also means we have
// closed both cert stores.
for _, cert := range certs {
buf := bytes.Buffer{}
block := &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}
err = pem.Encode(&buf, block)
if assert.NoError(t, err, "Failed to encode certificate") {
// Look for invalid certificates:
// - A line of all A (nulls)
// - A line with 0xFEEEFEEE (HeapAlloc freed marker)
output := buf.String()
assert.NotContains(t, output, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "encoded cert contains nulls")
assert.NotContains(t, output, "7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+", "encoded cert contains FEEEFEEE")
}
}
}

0 comments on commit ae3b6f2

Please sign in to comment.