go.mod, cmd/tailscaled, ipn/localapi, util/osdiag, util/winutil, util/winutil/authenticode: add Windows module list to OS-specific logs that are written upon bugreport
* We update wingoes to pick up new version information functionality (See pe/version.go in the https://github.com/dblohm7/wingoes repo); * We move the existing LogSupportInfo code (including necessary syscall stubs) out of util/winutil into a new package, util/osdiag, and implement the public LogSupportInfo function may be implemented for other platforms as needed; * We add a new reason argument to LogSupportInfo and wire that into localapi's bugreport implementation; * We add module information to the Windows implementation of LogSupportInfo when reason indicates a bugreport. We enumerate all loaded modules in our process, and for each one we gather debug, authenticode signature, and version information. Fixes #7802 Signed-off-by: Aaron Klotz <aaron@tailscale.com>
This commit is contained in:
@ -4,13 +4,7 @@
|
||||
package winutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -34,117 +28,3 @@ func TestLookupPseudoUser(t *testing.T) {
|
||||
t.Errorf("LookupPseudoUser(%q) unexpectedly succeeded", networkSID)
|
||||
}
|
||||
}
|
||||
|
||||
func makeLongBinaryValue() []byte {
|
||||
buf := make([]byte, maxBinaryValueLen*2)
|
||||
for i, _ := range buf {
|
||||
buf[i] = byte(i % 0xFF)
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
var testData = map[string]any{
|
||||
"": "I am the default",
|
||||
"StringEmpty": "",
|
||||
"StringShort": "Hello",
|
||||
"StringLong": strings.Repeat("7", initialValueBufLen+1),
|
||||
"MultiStringEmpty": []string{},
|
||||
"MultiStringSingle": []string{"Foo"},
|
||||
"MultiStringSingleEmpty": []string{""},
|
||||
"MultiString": []string{"Foo", "Bar", "Baz"},
|
||||
"MultiStringWithEmptyBeginning": []string{"", "Foo", "Bar"},
|
||||
"MultiStringWithEmptyMiddle": []string{"Foo", "", "Bar"},
|
||||
"MultiStringWithEmptyEnd": []string{"Foo", "Bar", ""},
|
||||
"DWord": uint32(0x12345678),
|
||||
"QWord": uint64(0x123456789abcdef0),
|
||||
"BinaryEmpty": []byte{},
|
||||
"BinaryShort": []byte{0x01, 0x02, 0x03, 0x04},
|
||||
"BinaryLong": makeLongBinaryValue(),
|
||||
}
|
||||
|
||||
const (
|
||||
keyNameTest = `SOFTWARE\Tailscale Test`
|
||||
subKeyNameTest = "SubKey"
|
||||
)
|
||||
|
||||
func setValues(t *testing.T, k registry.Key) {
|
||||
for vk, v := range testData {
|
||||
var err error
|
||||
switch tv := v.(type) {
|
||||
case string:
|
||||
err = k.SetStringValue(vk, tv)
|
||||
case []string:
|
||||
err = k.SetStringsValue(vk, tv)
|
||||
case uint32:
|
||||
err = k.SetDWordValue(vk, tv)
|
||||
case uint64:
|
||||
err = k.SetQWordValue(vk, tv)
|
||||
case []byte:
|
||||
err = k.SetBinaryValue(vk, tv)
|
||||
default:
|
||||
t.Fatalf("Unknown type")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Error setting %q: %v", vk, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegistrySupportInfo(t *testing.T) {
|
||||
// Make sure the key doesn't exist yet
|
||||
k, err := registry.OpenKey(registry.CURRENT_USER, keyNameTest, registry.READ)
|
||||
switch {
|
||||
case err == nil:
|
||||
k.Close()
|
||||
t.Fatalf("Test key already exists")
|
||||
case !errors.Is(err, registry.ErrNotExist):
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
func() {
|
||||
k, _, err := registry.CreateKey(registry.CURRENT_USER, keyNameTest, registry.WRITE)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating test key: %v", err)
|
||||
}
|
||||
defer k.Close()
|
||||
|
||||
setValues(t, k)
|
||||
|
||||
sk, _, err := registry.CreateKey(k, subKeyNameTest, registry.WRITE)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating test subkey: %v", err)
|
||||
}
|
||||
defer sk.Close()
|
||||
|
||||
setValues(t, sk)
|
||||
}()
|
||||
|
||||
t.Cleanup(func() {
|
||||
registry.DeleteKey(registry.CURRENT_USER, keyNameTest+"\\"+subKeyNameTest)
|
||||
registry.DeleteKey(registry.CURRENT_USER, keyNameTest)
|
||||
})
|
||||
|
||||
wantValuesData := maps.Clone(testData)
|
||||
wantValuesData["BinaryLong"] = (wantValuesData["BinaryLong"].([]byte))[:maxBinaryValueLen]
|
||||
|
||||
wantKeyData := make(map[string]any)
|
||||
maps.Copy(wantKeyData, wantValuesData)
|
||||
wantSubKeyData := make(map[string]any)
|
||||
maps.Copy(wantSubKeyData, wantValuesData)
|
||||
wantKeyData[subKeyNameTest] = wantSubKeyData
|
||||
|
||||
wantData := map[string]any{
|
||||
"HKCU\\" + keyNameTest: wantKeyData,
|
||||
}
|
||||
|
||||
gotData, err := getRegistrySupportInfo(registry.CURRENT_USER, []string{keyNameTest})
|
||||
if err != nil {
|
||||
t.Errorf("getRegistrySupportInfo error: %v", err)
|
||||
}
|
||||
|
||||
want, got := fmt.Sprintf("%#v", wantData), fmt.Sprintf("%#v", gotData)
|
||||
if want != got {
|
||||
t.Errorf("Compare error: want\n%s,\ngot %s", want, got)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user