agent/checkvirt/checkvirt_windows.go (164 lines of code) (raw):

package checkvirt import ( "errors" "fmt" "path" "strconv" "syscall" "unsafe" "github.com/aliyun/aliyun_assist_client/agent/log" "github.com/aliyun/aliyun_assist_client/agent/metrics" "github.com/aliyun/aliyun_assist_client/agent/taskengine/timermanager" "golang.org/x/sys/windows" ) const ( // DefaultCheckIntervalSeconds is the default interval for report virtio driver version DefaultCheckIntervalSeconds = 3600 * 24 ) const ( IOCTL_STORAGE_QUERY_PROPERTY = 0x002d1400 StorageDeviceUniqueIdProperty = 3 PropertyStandardQuery = 0 StorageIdCodeSetAscii = 2 StorageIdCodeSetBinary = 1 StorageIdTypeEUI64 = 2 ) type STORAGE_DEVICE_UNIQUE_IDENTIFIER struct { Version uint32 Size uint32 StorageDeviceIdOffset uint32 StorageDeviceOffset uint32 DriveLayoutSignatureOffset uint32 raw [512]byte } type STORAGE_PROPERTY_QUERY struct { PropertyId uint32 QueryType uint32 AdditionalParameters byte } type STORAGE_DEVICE_ID_DESCRIPTOR struct { Version uint32 Size uint32 NumberOfIdentifiers uint32 Identifiers [1]STORAGE_IDENTIFIER } type STORAGE_IDENTIFIER struct { CodeSet uint32 Type uint32 IdentifierSize uint16 NextOffset uint16 Association uint32 Identifier [1]byte } func GetDiskPropertyDUID(path string, diskProperty []byte) error { utfPath, err := syscall.UTF16PtrFromString(path) if err != nil { return err } hFile, err := syscall.CreateFile(utfPath, syscall.GENERIC_READ, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, nil, syscall.OPEN_EXISTING, 0, 0) if err != nil { return err } defer syscall.CloseHandle(hFile) var diskdiskPropertySize uint32 query := &STORAGE_PROPERTY_QUERY{ AdditionalParameters: 0, PropertyId: StorageDeviceUniqueIdProperty, QueryType: PropertyStandardQuery, } return syscall.DeviceIoControl(hFile, IOCTL_STORAGE_QUERY_PROPERTY, (*byte)(unsafe.Pointer(query)), uint32(unsafe.Sizeof(*query)), (*byte)(unsafe.Pointer(&diskProperty[0])), uint32(len(diskProperty)), &diskdiskPropertySize, nil) } func CheckVirtIoVersion(Index int) (error, bool) { diskDuidInfo := make([]byte, 1024, 1024) err := GetDiskPropertyDUID("\\\\.\\PhysicalDrive"+strconv.Itoa(Index), diskDuidInfo) if err != nil { return err, false } diskData := (*STORAGE_DEVICE_UNIQUE_IDENTIFIER)(unsafe.Pointer(&diskDuidInfo[0])) if diskData.StorageDeviceIdOffset >= 1024 { return errors.New("Invalid diskData.StorageDeviceIdOffset"), false } pIdentifiers := (*STORAGE_DEVICE_ID_DESCRIPTOR)(unsafe.Pointer(uintptr(unsafe.Pointer(diskData)) + uintptr(diskData.StorageDeviceIdOffset))) if pIdentifiers.NumberOfIdentifiers < 1 { return errors.New("Invalid pIdentifiers.NumberOfIdentifiers"), false } blockStart := uintptr(unsafe.Pointer(&pIdentifiers.Identifiers[0].Identifier[0])) - uintptr(unsafe.Pointer(&diskDuidInfo[0])) idSize := pIdentifiers.Identifiers[0].IdentifierSize codeSet := pIdentifiers.Identifiers[0].CodeSet Type := pIdentifiers.Identifiers[0].Type if blockStart+uintptr(idSize) >= 1024 { return errors.New("Invalid idSize"), false } dst := diskDuidInfo[blockStart : blockStart+uintptr(idSize)] //老版本驱动uniqueid生成逻辑 // IdentificationDescr->CodeSet = VpdCodeSetBinary; // IdentificationDescr->IdentifierType = VpdIdentifierTypeEUI64; // IdentificationDescr->IdentifierLength = 8; // IdentificationDescr->Identifier[0] = '1'; // IdentificationDescr->Identifier[1] = 'A'; // IdentificationDescr->Identifier[2] = 'F'; // IdentificationDescr->Identifier[3] = '4'; // IdentificationDescr->Identifier[4] = '1'; // IdentificationDescr->Identifier[5] = '0'; // IdentificationDescr->Identifier[6] = '0'; // IdentificationDescr->Identifier[7] = '1'; if Type == StorageIdTypeEUI64 && codeSet == StorageIdCodeSetBinary && idSize == 8 && string(dst[:]) == "1AF41001" { log.GetLogger().Println("find dangerous uniqueid:" + string(dst[:])) return nil, true } return nil, false } func doCheck() { system32, err := windows.GetSystemDirectory() if err != nil { system32 = "C:\\Windows\\System32" } driversDir := path.Join(system32, "drivers") driversVersionMap := map[string]WinVersion{ "viostor.sys": WinVersion{}, "netkvm.sys": WinVersion{}, "vioser.sys": WinVersion{}, "AliNVMe.sys": WinVersion{}, "AliWinUtilDrv.sys": WinVersion{}, } for key, _ := range driversVersionMap { ver, err := GetFileVersion(path.Join(driversDir, key)) if err != nil { log.GetLogger().Infof("get %s version failed,err=%s", key, err.Error()) } else { driversVersionMap[key] = ver } } viostor := driversVersionMap["viostor.sys"] netkvm := driversVersionMap["netkvm.sys"] vioser := driversVersionMap["vioser.sys"] AliNVMe := driversVersionMap["AliNVMe.sys"] AliWinUtilDrv := driversVersionMap["AliWinUtilDrv.sys"] vminit, err := GetFileVersion("C:\\ProgramData\\aliyun\\vminit\\vminit.exe") if err != nil { log.GetLogger().Infof("get vminit.exe version failed,err=%s", err.Error()) } metrics.GetVirtioVersionEvent( "viostor", fmt.Sprintf("%d.%d.%d.%d", viostor.Major, viostor.Minor, viostor.Patch, viostor.Build), "netkvm", fmt.Sprintf("%d.%d.%d.%d", netkvm.Major, netkvm.Minor, netkvm.Patch, netkvm.Build), "vioser", fmt.Sprintf("%d.%d.%d.%d", vioser.Major, vioser.Minor, vioser.Patch, vioser.Build), "AliNVMe", fmt.Sprintf("%d.%d.%d.%d", AliNVMe.Major, AliNVMe.Minor, AliNVMe.Patch, AliNVMe.Build), "AliWinUtilDrv", fmt.Sprintf("%d.%d.%d.%d", AliWinUtilDrv.Major, AliWinUtilDrv.Minor, AliWinUtilDrv.Patch, AliWinUtilDrv.Build), "vminit", fmt.Sprintf("%d.%d.%d.%d", vminit.Major, vminit.Minor, vminit.Patch, vminit.Build), ).ReportEvent() } func StartVirtIoVersionReport() error { timerManager := timermanager.GetTimerManager() timer, err := timerManager.CreateTimerInSeconds(doCheck, DefaultCheckIntervalSeconds) if err != nil { return err } _, err = timer.Run() if err != nil { return err } return nil }