[service] Fix check for invalid kext handle (#1716)
* [service] Fix check for invalid kext handle * [windows_kext] Use BTreeMap as cache structure * [windows_kext] Fix synchronization bug * Update windows_kext/kextinterface/kext_file.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update windows_kext/kextinterface/kext_file.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update windows_kext/kextinterface/kext_file.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
@@ -38,7 +38,7 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
winInvalidHandleValue = windows.Handle(^uintptr(0)) // Max value
|
||||
winInvalidHandleValue = windows.InvalidHandle
|
||||
stopServiceTimeoutDuration = time.Duration(30 * time.Second)
|
||||
)
|
||||
|
||||
@@ -48,7 +48,7 @@ type KextService struct {
|
||||
}
|
||||
|
||||
func (s *KextService) isValid() bool {
|
||||
return s != nil && s.handle != winInvalidHandleValue && s.handle != 0
|
||||
return s != nil && s.handle != windows.InvalidHandle && s.handle != 0
|
||||
}
|
||||
|
||||
func (s *KextService) isRunning() (bool, error) {
|
||||
@@ -99,7 +99,7 @@ func (s *KextService) Start(wait bool) error {
|
||||
_ = windows.ControlService(s.handle, windows.SERVICE_CONTROL_STOP, &status)
|
||||
_ = windows.DeleteService(s.handle)
|
||||
_ = windows.CloseServiceHandle(s.handle)
|
||||
s.handle = winInvalidHandleValue
|
||||
s.handle = windows.InvalidHandle
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -158,7 +158,7 @@ func (s *KextService) Delete() error {
|
||||
return fmt.Errorf("failed to close service handle: %s", err)
|
||||
}
|
||||
|
||||
s.handle = winInvalidHandleValue
|
||||
s.handle = windows.InvalidHandle
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ func CreateKextService(driverName string, driverPath string) (*KextService, erro
|
||||
return nil, err
|
||||
}
|
||||
|
||||
service = winInvalidHandleValue
|
||||
service = windows.InvalidHandle
|
||||
log.Warning("kext: old driver service was deleted successfully")
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
package kextinterface
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
@@ -13,7 +15,16 @@ type KextFile struct {
|
||||
read_slice []byte
|
||||
}
|
||||
|
||||
// Read tries to read the supplied buffer length from the driver.
|
||||
// The data from the driver is read in chunks `len(f.buffer)` and the extra data is cached for the next call.
|
||||
// The performance penalty of calling the function with small buffers is very small.
|
||||
// The function will block until the next info packet is received from the kext.
|
||||
func (f *KextFile) Read(buffer []byte) (int, error) {
|
||||
if err := f.IsValid(); err != nil {
|
||||
return 0, fmt.Errorf("failed to read: %w", err)
|
||||
}
|
||||
|
||||
// If no data is available from previous calls, read from kext.
|
||||
if f.read_slice == nil || len(f.read_slice) == 0 {
|
||||
err := f.refill_read_buffer()
|
||||
if err != nil {
|
||||
@@ -22,14 +33,19 @@ func (f *KextFile) Read(buffer []byte) (int, error) {
|
||||
}
|
||||
|
||||
if len(f.read_slice) >= len(buffer) {
|
||||
// Write all requested bytes.
|
||||
// There is enough data to fill the requested buffer.
|
||||
copy(buffer, f.read_slice[0:len(buffer)])
|
||||
// Move the slice to contain the remaining data.
|
||||
f.read_slice = f.read_slice[len(buffer):]
|
||||
} else {
|
||||
// Write all available bytes and read again.
|
||||
// There is not enough data to fill the requested buffer.
|
||||
|
||||
// Write everything available.
|
||||
copy(buffer[0:len(f.read_slice)], f.read_slice)
|
||||
copiedBytes := len(f.read_slice)
|
||||
f.read_slice = nil
|
||||
|
||||
// Read again.
|
||||
_, err := f.Read(buffer[copiedBytes:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -51,20 +67,33 @@ func (f *KextFile) refill_read_buffer() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write sends the buffer bytes to the kext. The function will block until the whole buffer is written to the kext.
|
||||
func (f *KextFile) Write(buffer []byte) (int, error) {
|
||||
if err := f.IsValid(); err != nil {
|
||||
return 0, fmt.Errorf("failed to write: %w", err)
|
||||
}
|
||||
var count uint32 = 0
|
||||
overlapped := &windows.Overlapped{}
|
||||
err := windows.WriteFile(f.handle, buffer, &count, overlapped)
|
||||
return int(count), err
|
||||
}
|
||||
|
||||
// Close closes the handle to the kext. This will cancel all active Reads and Writes.
|
||||
func (f *KextFile) Close() error {
|
||||
if err := f.IsValid(); err != nil {
|
||||
return fmt.Errorf("failed to close: %w", err)
|
||||
}
|
||||
err := windows.CloseHandle(f.handle)
|
||||
f.handle = winInvalidHandleValue
|
||||
f.handle = windows.InvalidHandle
|
||||
return err
|
||||
}
|
||||
|
||||
// deviceIOControl exists for compatibility with the old kext.
|
||||
func (f *KextFile) deviceIOControl(code uint32, inData []byte, outData []byte) (*windows.Overlapped, error) {
|
||||
if err := f.IsValid(); err != nil {
|
||||
return nil, fmt.Errorf("failed to send io control: %w", err)
|
||||
}
|
||||
// Prepare the input data
|
||||
var inDataPtr *byte = nil
|
||||
var inDataSize uint32 = 0
|
||||
if inData != nil {
|
||||
@@ -72,6 +101,7 @@ func (f *KextFile) deviceIOControl(code uint32, inData []byte, outData []byte) (
|
||||
inDataSize = uint32(len(inData))
|
||||
}
|
||||
|
||||
// Prepare the output data
|
||||
var outDataPtr *byte = nil
|
||||
var outDataSize uint32 = 0
|
||||
if outData != nil {
|
||||
@@ -79,6 +109,7 @@ func (f *KextFile) deviceIOControl(code uint32, inData []byte, outData []byte) (
|
||||
outDataSize = uint32(len(outData))
|
||||
}
|
||||
|
||||
// Make the request to the kext.
|
||||
overlapped := &windows.Overlapped{}
|
||||
err := windows.DeviceIoControl(f.handle,
|
||||
code,
|
||||
@@ -92,6 +123,20 @@ func (f *KextFile) deviceIOControl(code uint32, inData []byte, outData []byte) (
|
||||
return overlapped, nil
|
||||
}
|
||||
|
||||
// GetHandle returns the handle of the kext.
|
||||
func (f *KextFile) GetHandle() windows.Handle {
|
||||
return f.handle
|
||||
}
|
||||
|
||||
// IsValid checks if kext file holds a valid handle to the kext driver.
|
||||
func (f *KextFile) IsValid() error {
|
||||
if f == nil {
|
||||
return fmt.Errorf("nil kext file")
|
||||
}
|
||||
|
||||
if f.handle == windows.Handle(0) || f.handle == windows.InvalidHandle {
|
||||
return fmt.Errorf("invalid handle")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user