-
Notifications
You must be signed in to change notification settings - Fork 373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace unsafe.Slice with memory copying to avoid potential fault memory issue #6664
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -368,7 +368,16 @@ func (n *netIO) ListIPForwardRows(family uint16) ([]MibIPForwardRow, error) { | |
if err != nil { | ||
return nil, os.NewSyscallError("iphlpapi.GetIpForwardTable", err) | ||
} | ||
return unsafe.Slice(&table.Table[0], table.NumEntries), nil | ||
rows := make([]MibIPForwardRow, table.NumEntries, table.NumEntries) | ||
|
||
pFirstRow := uintptr(unsafe.Pointer(&table.Table[0])) | ||
rowSize := unsafe.Sizeof(table.Table[0]) | ||
|
||
for i := uint32(0); i < table.NumEntries; i++ { | ||
row := *(*MibIPForwardRow)(unsafe.Pointer(pFirstRow + rowSize*uintptr(i))) | ||
rows[i] = row | ||
} | ||
return rows, nil | ||
Comment on lines
-371
to
+380
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does this fix a specific issue? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We received a report indicating that when host memory is less than 8GB, using unsafe.Slice can lead to memory faults. It’s possible that this function didn’t perform a deep copy, so after calling |
||
} | ||
|
||
func NewIPForwardRow() *MibIPForwardRow { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I know the only issue with the previous code is that we were not making a copy of the slice prior to returning, while at the same time freeing the underlying memory by calling
n.freeMibTable(unsafe.Pointer(table))
.The Wireguard Windows code has a simpler implementation of this, which still uses
unsafe.Slice
. It achieves correctness by making a proper copy of the slice: https://github.com/WireGuard/wireguard-windows/blob/e70799b1440690e7d4140bffc7c73baf903c7b54/tunnel/winipcfg/winipcfg.go#L151That being said, if this new version has already been tested thoroughly, there is probably no string reason to change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@antoninbas , we used to think about the solution as what Wiregurad is taking, a concern is some fields in MibIPForwardRow are using type
[]byte
, which still exists the risk with a shadow copy if the memory resource is limited (e.g., Windows OS re-allocate the memory to other objects after theMibIPForwardTable
is free). So we finally choose the solution to deep copy the objects before free the memory. The latest code is verified on the problematic cluster.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean
[N]byte
types like the[26]byte
field inRawSockAddrInet
([]byte
would not be possible here AFAIK)? These should be no different than integer types, they should be inlined in the struct with no indirection.The code before this change was wrong for obvious reasons. I don't think the Wireguard code is wrong. But if you feel like manual copy is the best approach and this has been well-tested, as I wrote before we can merge it as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fields in MibIPForwardRow is array not slice. It will be deepcopied automatically.
And the current code is inconsistent: it makes a manual deepcopy for RawSockAddrInet but not AddressPrefix which also has a RawSockAddrInet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An example: https://play.golang.com/p/z6Gc0YhEQSV