Skip to content

Commit 96105dd

Browse files
committed
Add go:notinheap annotations to all the WFP API types.
This should prevent us from accidentally passing Go memory to Windows. Also fix up a couple cases where we were, in fact, passing Go memory to Windows. Signed-off-by: David Anderson <[email protected]>
1 parent 3c2c0fd commit 96105dd

File tree

6 files changed

+68
-36
lines changed

6 files changed

+68
-36
lines changed

compose.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,27 @@ import (
88
"golang.org/x/sys/windows"
99
)
1010

11+
func toSession0(a *arena, opts *SessionOptions) *fwpmSession0 {
12+
ret := (*fwpmSession0)(a.alloc(unsafe.Sizeof(fwpmSession0{})))
13+
*ret = fwpmSession0{
14+
DisplayData: fwpmDisplayData0{
15+
Name: toUint16(a, opts.Name),
16+
Description: toUint16(a, opts.Description),
17+
},
18+
TxnWaitTimeoutMillis: uint32(opts.TransactionStartTimeout.Milliseconds()),
19+
}
20+
if opts.Dynamic {
21+
ret.Flags = fwpmSession0FlagDynamic
22+
}
23+
return ret
24+
}
25+
26+
func toSublayerEnumTemplate0(a *arena, provider *windows.GUID) *fwpmSublayerEnumTemplate0 {
27+
ret := (*fwpmSublayerEnumTemplate0)(a.alloc(unsafe.Sizeof(fwpmSublayerEnumTemplate0{})))
28+
ret.ProviderKey = toGUID(a, provider)
29+
return ret
30+
}
31+
1132
func toSublayer0(a *arena, sl *Sublayer) *fwpmSublayer0 {
1233
ret := (*fwpmSublayer0)(a.alloc(unsafe.Sizeof(fwpmSublayer0{})))
1334
*ret = fwpmSublayer0{

firewall.go

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,13 @@ func New(opts *SessionOptions) (*Session, error) {
5656
opts = &SessionOptions{}
5757
}
5858

59-
session := fwpmSession0{
60-
DisplayData: fwpmDisplayData0{
61-
Name: windows.StringToUTF16Ptr(opts.Name),
62-
Description: windows.StringToUTF16Ptr(opts.Description),
63-
},
64-
TxnWaitTimeoutMillis: uint32(opts.TransactionStartTimeout.Milliseconds()),
65-
}
66-
if opts.Dynamic {
67-
session.Flags = fwpmSession0FlagDynamic
68-
}
59+
var a arena
60+
defer a.dispose()
6961

70-
var handle windows.Handle
62+
s0 := toSession0(&a, opts)
7163

72-
err := fwpmEngineOpen0(nil, authnServiceWinNT, nil, &session, &handle)
64+
var handle windows.Handle
65+
err := fwpmEngineOpen0(nil, authnServiceWinNT, nil, s0, &handle)
7366
if err != nil {
7467
return nil, err
7568
}
@@ -232,12 +225,13 @@ type Sublayer struct {
232225
// Sublayers returns available Sublayers. If provider is non-nil, only
233226
// Sublayers registered to that Provider are returned.
234227
func (s *Session) Sublayers(provider *windows.GUID) ([]*Sublayer, error) {
235-
tpl := fwpmSublayerEnumTemplate0{
236-
ProviderKey: provider,
237-
}
228+
var a arena
229+
defer a.dispose()
230+
231+
tpl := toSublayerEnumTemplate0(&a, provider)
238232

239233
var enum windows.Handle
240-
if err := fwpmSubLayerCreateEnumHandle0(s.handle, &tpl, &enum); err != nil {
234+
if err := fwpmSubLayerCreateEnumHandle0(s.handle, tpl, &enum); err != nil {
241235
return nil, err
242236
}
243237
defer fwpmSubLayerDestroyEnumHandle0(s.handle, enum)

parse.go

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,9 @@ func fromLayer0(array **fwpmLayer0, num uint32) ([]*Layer, error) {
9191
sh.Len = int(layer.NumFields)
9292
sh.Data = uintptr(unsafe.Pointer(layer.Fields))
9393

94-
for _, field := range fields {
95-
typ, err := fieldType(&field)
94+
for i := range fields {
95+
field := &fields[i]
96+
typ, err := fieldType(field)
9697
if err != nil {
9798
return nil, fmt.Errorf("finding type of field %s: %w", GUIDName(*field.FieldKey), err)
9899
}
@@ -124,7 +125,7 @@ func fromSublayer0(array **fwpmSublayer0, num uint32) []*Sublayer {
124125
Name: windows.UTF16PtrToString(sublayer.DisplayData.Name),
125126
Description: windows.UTF16PtrToString(sublayer.DisplayData.Description),
126127
Persistent: (sublayer.Flags & fwpmSublayerFlagsPersistent) != 0,
127-
ProviderData: fromByteBlob(sublayer.ProviderData),
128+
ProviderData: fromByteBlob(&sublayer.ProviderData),
128129
Weight: sublayer.Weight,
129130
}
130131
if sublayer.ProviderKey != nil {
@@ -157,7 +158,7 @@ func fromProvider0(array **fwpmProvider0, num uint32) []*Provider {
157158
Description: windows.UTF16PtrToString(provider.DisplayData.Description),
158159
Persistent: (provider.Flags & fwpmProviderFlagsPersistent) != 0,
159160
Disabled: (provider.Flags & fwpmProviderFlagsDisabled) != 0,
160-
Data: fromByteBlob(provider.ProviderData),
161+
Data: fromByteBlob(&provider.ProviderData),
161162
ServiceName: windows.UTF16PtrToString(provider.ServiceName),
162163
}
163164
ret = append(ret, p)
@@ -186,7 +187,7 @@ func fromFilter0(array **fwpmFilter0, num uint32, layerTypes layerTypes) ([]*Rul
186187
Persistent: (rule.Flags & fwpmFilterFlagsPersistent) != 0,
187188
BootTime: (rule.Flags & fwpmFilterFlagsBootTime) != 0,
188189
Provider: rule.ProviderKey,
189-
ProviderData: fromByteBlob(rule.ProviderData),
190+
ProviderData: fromByteBlob(&rule.ProviderData),
190191
Disabled: (rule.Flags & fwpmFilterFlagsDisabled) != 0,
191192
}
192193
if rule.EffectiveWeight.Type == dataTypeUint64 {
@@ -226,13 +227,14 @@ func fromCondition0(condArray *fwpmFilterCondition0, num uint32, fieldTypes fiel
226227

227228
var ret []*Match
228229

229-
for _, cond := range conditions {
230+
for i := range conditions {
231+
cond := &conditions[i]
230232
fieldType, ok := fieldTypes[cond.FieldKey]
231233
if !ok {
232234
return nil, fmt.Errorf("unknown field %s", cond.FieldKey)
233235
}
234236

235-
v, err := fromValue0(fwpValue0(cond.Value), fieldType)
237+
v, err := fromValue0((*fwpValue0)(unsafe.Pointer(&cond.Value)), fieldType)
236238
if err != nil {
237239
return nil, fmt.Errorf("getting value for match [%s %s]: %w", GUIDName(cond.FieldKey), cond.MatchType, err)
238240
}
@@ -249,7 +251,7 @@ func fromCondition0(condArray *fwpmFilterCondition0, num uint32, fieldTypes fiel
249251
}
250252

251253
// fromValue converts a fwpValue0 to the corresponding Go value.
252-
func fromValue0(v fwpValue0, ftype reflect.Type) (interface{}, error) {
254+
func fromValue0(v *fwpValue0, ftype reflect.Type) (interface{}, error) {
253255
// For most types, the field type and raw data type match up. But
254256
// for some, the raw type can vary from the field type
255257
// (e.g. comparing an IP to a prefix). Get the complex matchups
@@ -316,7 +318,7 @@ func fromValue0(v fwpValue0, ftype reflect.Type) (interface{}, error) {
316318
copy(ret[:], fromBytes(v.Value, 16))
317319
return ret, nil
318320
case dataTypeByteBlob:
319-
return fromByteBlob(**(**fwpByteBlob)(unsafe.Pointer(&v.Value))), nil
321+
return fromByteBlob(*(**fwpByteBlob)(unsafe.Pointer(&v.Value))), nil
320322
case dataTypeSID:
321323
return parseSID(&v.Value)
322324
// case dataTypeSecurityDescriptor:
@@ -373,18 +375,18 @@ func parseSID(v *uintptr) (*windows.SID, error) {
373375
func parseSecurityDescriptor(v *uintptr) (*windows.SECURITY_DESCRIPTOR, error) {
374376
// The security descriptor is embedded in the API response as
375377
// a byte slice.
376-
bb := fromByteBlob(**(**fwpByteBlob)(unsafe.Pointer(v)))
378+
bb := fromByteBlob(*(**fwpByteBlob)(unsafe.Pointer(v)))
377379
relSD := (*windows.SECURITY_DESCRIPTOR)(unsafe.Pointer(&bb[0]))
378380
return relSD, nil
379381
}
380382

381383
func parseRange0(v *uintptr, ftype reflect.Type) (interface{}, error) {
382384
r := *(**fwpRange0)(unsafe.Pointer(v))
383-
from, err := fromValue0(r.From, ftype)
385+
from, err := fromValue0(&r.From, ftype)
384386
if err != nil {
385387
return nil, err
386388
}
387-
to, err := fromValue0(r.To, ftype)
389+
to, err := fromValue0(&r.To, ftype)
388390
if err != nil {
389391
return nil, err
390392
}
@@ -421,8 +423,8 @@ func fromBytes(bb uintptr, length int) []byte {
421423

422424
// fromByteBlob extracts the bytes from bb and returns them as a
423425
// []byte that doesn't alias C memory.
424-
func fromByteBlob(bb fwpByteBlob) []byte {
425-
if bb.Size == 0 {
426+
func fromByteBlob(bb *fwpByteBlob) []byte {
427+
if bb == nil || bb.Size == 0 {
426428
return nil
427429
}
428430

syscall.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ package wf
2222

2323
//sys fwpmSubLayerDeleteByKey0(engineHandle windows.Handle, guid *windows.GUID) (err error) [failretval!=0] = fwpuclnt.FwpmSubLayerDeleteByKey0
2424

25-
//sys fwpmProviderCreateEnumHandle0(engineHandle windows.Handle, enumTemplate *fwpmProviderEnumTemplate0, handle *windows.Handle) (err error) [failretval!=0] = fwpuclnt.FwpmProviderCreateEnumHandle0
25+
//sys fwpmProviderCreateEnumHandle0(engineHandle windows.Handle, enumTemplate *struct{}, handle *windows.Handle) (err error) [failretval!=0] = fwpuclnt.FwpmProviderCreateEnumHandle0
2626

2727
//sys fwpmProviderDestroyEnumHandle0(engineHandle windows.Handle, enumHandle windows.Handle) (err error) [failretval!=0] = fwpuclnt.FwpmProviderDestroyEnumHandle0
2828

types.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"golang.org/x/sys/windows"
55
)
66

7+
//go:notinheap
78
type fwpmDisplayData0 struct {
89
Name *uint16
910
Description *uint16
@@ -13,6 +14,7 @@ type fwpmSession0Flags uint32
1314

1415
const fwpmSession0FlagDynamic = 1
1516

17+
//go:notinheap
1618
type fwpmSession0 struct {
1719
SessionKey windows.GUID
1820
DisplayData fwpmDisplayData0
@@ -31,6 +33,7 @@ const (
3133
authnServiceDefault authnService = 0xffffffff
3234
)
3335

36+
//go:notinheap
3437
type fwpmLayerEnumTemplate0 struct {
3538
reserved uint64
3639
}
@@ -44,6 +47,7 @@ const (
4447
fwpmLayerFlagsBuffered
4548
)
4649

50+
//go:notinheap
4751
type fwpmLayer0 struct {
4852
LayerKey windows.GUID
4953
DisplayData fwpmDisplayData0
@@ -93,16 +97,19 @@ const (
9397
// dataTypeUnicodeString dataType = 17
9498
// dataTypeBitmapArray64 dataType = 20
9599

100+
//go:notinheap
96101
type fwpmField0 struct {
97102
FieldKey *windows.GUID
98103
Type fwpmFieldType
99104
DataType dataType
100105
}
101106

107+
//go:notinheap
102108
type fwpmSublayerEnumTemplate0 struct {
103109
ProviderKey *windows.GUID
104110
}
105111

112+
//go:notinheap
106113
type fwpByteBlob struct {
107114
Size uint32
108115
Data *uint8
@@ -112,6 +119,7 @@ type fwpmSublayerFlags uint32
112119

113120
const fwpmSublayerFlagsPersistent fwpmSublayerFlags = 1
114121

122+
//go:notinheap
115123
type fwpmSublayer0 struct {
116124
SublayerKey windows.GUID
117125
DisplayData fwpmDisplayData0
@@ -121,17 +129,14 @@ type fwpmSublayer0 struct {
121129
Weight uint16
122130
}
123131

124-
type fwpmProviderEnumTemplate0 struct {
125-
Reserved uint64
126-
}
127-
128132
type fwpmProviderFlags uint32
129133

130134
const (
131135
fwpmProviderFlagsPersistent fwpmProviderFlags = 0x01
132136
fwpmProviderFlagsDisabled fwpmProviderFlags = 0x10
133137
)
134138

139+
//go:notinheap
135140
type fwpmProvider0 struct {
136141
ProviderKey windows.GUID
137142
DisplayData fwpmDisplayData0
@@ -140,6 +145,7 @@ type fwpmProvider0 struct {
140145
ServiceName *uint16
141146
}
142147

148+
//go:notinheap
143149
type fwpValue0 struct {
144150
Type dataType
145151
Value uintptr // unioned value
@@ -157,11 +163,13 @@ const (
157163
fwpmFilterFlagsIndexed
158164
)
159165

166+
//go:notinheap
160167
type fwpmAction0 struct {
161168
Type Action
162169
GUID windows.GUID
163170
}
164171

172+
//go:notinheap
165173
type fwpmFilter0 struct {
166174
FilterKey windows.GUID
167175
DisplayData fwpmDisplayData0
@@ -180,31 +188,37 @@ type fwpmFilter0 struct {
180188
EffectiveWeight fwpValue0
181189
}
182190

191+
//go:notinheap
183192
type fwpConditionValue0 struct {
184193
Type dataType
185194
Value uintptr
186195
}
187196

197+
//go:notinheap
188198
type fwpmFilterCondition0 struct {
189199
FieldKey windows.GUID
190200
MatchType MatchType
191201
Value fwpConditionValue0
192202
}
193203

204+
//go:notinheap
194205
type fwpV4AddrAndMask struct {
195206
Addr, Mask uint32
196207
}
197208

209+
//go:notinheap
198210
type fwpV6AddrAndMask struct {
199211
Addr [16]byte
200212
PrefixLength uint8
201213
}
202214

215+
//go:notinheap
203216
type fwpmProviderContextEnumTemplate0 struct {
204217
ProviderKey *windows.GUID
205218
ProviderContextType uint32
206219
}
207220

221+
//go:notinheap
208222
type fwpmFilterEnumTemplate0 struct {
209223
ProviderKey *windows.GUID
210224
LayerKey windows.GUID
@@ -217,6 +231,7 @@ type fwpmFilterEnumTemplate0 struct {
217231
CalloutKey *windows.GUID
218232
}
219233

234+
//go:notinheap
220235
type fwpRange0 struct {
221236
From, To fwpValue0
222237
}

zsyscall_windows.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)