Skip to content

Commit 3aa668c

Browse files
committed
chore: update patch file for goissue77975
1 parent fcf780a commit 3aa668c

2 files changed

Lines changed: 219 additions & 21 deletions

File tree

.github/patch/issue77975.patch

Lines changed: 218 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,22 @@
1-
Subject: [PATCH] move lpFromlen to heap for WSARecvFrom syscall
1+
Subject: [PATCH] internal/poll: move rsan to heap on windows
2+
3+
According to https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsarecvfrom,
4+
the memory pointed to by lpFromlen must remain available during the
5+
overlapped I/O, and therefore cannot be allocated on the stack.
6+
7+
CL 685417 moved the rsan field out of the operation struct and placed
8+
it on stack, which violates the above requirement and causes stack
9+
corruption.
10+
11+
Unfortunately, it is no longer possible to cleanly revert CL 685417.
12+
Instead of attempting to revert it, this CL bundles rsan together
13+
with rsa in the same sync.Pool. The new wsaRsa struct is still in the
14+
same size class, so no additional overhead is introduced by this
15+
change.
16+
17+
Fixes #77975.
18+
19+
Change-Id: I5ffbccb332515116ddc03fb7c40ffc9293cad2ab
220
---
321
Index: src/internal/poll/fd_windows.go
422
IDEA additional info:
@@ -7,49 +25,229 @@ Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
725
===================================================================
826
diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go
927
--- a/src/internal/poll/fd_windows.go (revision 8149d992682ce76c6af804b507878e19fc966f7b)
10-
+++ b/src/internal/poll/fd_windows.go (revision 25efab96145f416bbae4024e9c110429770b22d1)
11-
@@ -76,6 +76,8 @@
12-
// fields used by runtime.netpoll
13-
runtimeCtx uintptr
14-
mode int32
28+
+++ b/src/internal/poll/fd_windows.go (date 1773058735706)
29+
@@ -149,7 +149,7 @@
30+
31+
// newWSAMsg creates a new WSAMsg with the provided parameters.
32+
// Use [freeWSAMsg] to free it.
33+
-func newWSAMsg(p []byte, oob []byte, flags int, unconnected bool) *windows.WSAMsg {
34+
+func newWSAMsg(p []byte, oob []byte, flags int, rsa *wsaRsa) *windows.WSAMsg {
35+
// The returned object can't be allocated in the stack because it is accessed asynchronously
36+
// by Windows in between several system calls. If the stack frame is moved while that happens,
37+
// then Windows may access invalid memory.
38+
@@ -164,33 +164,45 @@
39+
Buf: unsafe.SliceData(oob),
40+
}
41+
msg.Flags = uint32(flags)
42+
- if unconnected {
43+
- msg.Name = wsaRsaPool.Get().(*syscall.RawSockaddrAny)
44+
- msg.Namelen = int32(unsafe.Sizeof(syscall.RawSockaddrAny{}))
45+
+ if rsa != nil {
46+
+ msg.Name = &rsa.name
47+
+ msg.Namelen = rsa.namelen
48+
}
49+
return msg
50+
}
51+
52+
func freeWSAMsg(msg *windows.WSAMsg) {
53+
// Clear pointers to buffers so they can be released by garbage collector.
54+
+ msg.Name = nil
55+
+ msg.Namelen = 0
56+
msg.Buffers.Len = 0
57+
msg.Buffers.Buf = nil
58+
msg.Control.Len = 0
59+
msg.Control.Buf = nil
60+
- if msg.Name != nil {
61+
- *msg.Name = syscall.RawSockaddrAny{}
62+
- wsaRsaPool.Put(msg.Name)
63+
- msg.Name = nil
64+
- msg.Namelen = 0
65+
- }
66+
wsaMsgPool.Put(msg)
67+
}
68+
69+
+// wsaRsa bundles a [syscall.RawSockaddrAny] with its length for efficient caching.
70+
+//
71+
+// When used by WSARecvFrom, wsaRsa must be on the heap. See
72+
+// https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsarecvfrom.
73+
+type wsaRsa struct {
74+
+ name syscall.RawSockaddrAny
75+
+ namelen int32
76+
+}
1577
+
16-
+ rsan int32
78+
var wsaRsaPool = sync.Pool{
79+
New: func() any {
80+
- return new(syscall.RawSockaddrAny)
81+
+ return new(wsaRsa)
82+
},
1783
}
84+
+
85+
+func newWSARsa() *wsaRsa {
86+
+ rsa := wsaRsaPool.Get().(*wsaRsa)
87+
+ rsa.name = syscall.RawSockaddrAny{}
88+
+ rsa.namelen = int32(unsafe.Sizeof(syscall.RawSockaddrAny{}))
89+
+ return rsa
90+
+}
91+
92+
var operationPool = sync.Pool{
93+
New: func() any {
94+
@@ -737,19 +749,18 @@
1895

19-
func (fd *FD) overlapped(o *operation) *syscall.Overlapped {
20-
@@ -740,9 +742,9 @@
21-
rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
96+
fd.pin('r', &buf[0])
97+
98+
- rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
99+
+ rsa := newWSARsa()
22100
defer wsaRsaPool.Put(rsa)
23101
n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
24102
- rsan := int32(unsafe.Sizeof(*rsa))
25-
+ o.rsan = int32(unsafe.Sizeof(*rsa))
26103
var flags uint32
27104
- err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &rsan, &o.o, nil)
28-
+ err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &o.rsan, &o.o, nil)
105+
+ err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, &rsa.name, &rsa.namelen, &o.o, nil)
29106
return qty, err
30107
})
31108
err = fd.eofError(n, err)
32-
@@ -771,9 +773,9 @@
33-
rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
109+
if err != nil {
110+
return n, nil, err
111+
}
112+
- sa, _ := rsa.Sockaddr()
113+
+ sa, _ := rsa.name.Sockaddr()
114+
return n, sa, nil
115+
}
116+
117+
@@ -768,19 +779,18 @@
118+
119+
fd.pin('r', &buf[0])
120+
121+
- rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
122+
+ rsa := newWSARsa()
34123
defer wsaRsaPool.Put(rsa)
35124
n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
36125
- rsan := int32(unsafe.Sizeof(*rsa))
37-
+ o.rsan = int32(unsafe.Sizeof(*rsa))
38126
var flags uint32
39127
- err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &rsan, &o.o, nil)
40-
+ err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &o.rsan, &o.o, nil)
128+
+ err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, &rsa.name, &rsa.namelen, &o.o, nil)
41129
return qty, err
42130
})
43131
err = fd.eofError(n, err)
44-
@@ -802,9 +804,9 @@
45-
rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
132+
if err != nil {
133+
return n, err
134+
}
135+
- rawToSockaddrInet4(rsa, sa4)
136+
+ rawToSockaddrInet4(&rsa.name, sa4)
137+
return n, err
138+
}
139+
140+
@@ -799,19 +809,18 @@
141+
142+
fd.pin('r', &buf[0])
143+
144+
- rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
145+
+ rsa := newWSARsa()
46146
defer wsaRsaPool.Put(rsa)
47147
n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
48148
- rsan := int32(unsafe.Sizeof(*rsa))
49-
+ o.rsan = int32(unsafe.Sizeof(*rsa))
50149
var flags uint32
51150
- err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &rsan, &o.o, nil)
52-
+ err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &o.rsan, &o.o, nil)
151+
+ err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, &rsa.name, &rsa.namelen, &o.o, nil)
53152
return qty, err
54153
})
55154
err = fd.eofError(n, err)
155+
if err != nil {
156+
return n, err
157+
}
158+
- rawToSockaddrInet6(rsa, sa6)
159+
+ rawToSockaddrInet6(&rsa.name, sa6)
160+
return n, err
161+
}
162+
163+
@@ -1371,7 +1380,9 @@
164+
p = p[:maxRW]
165+
}
166+
167+
- msg := newWSAMsg(p, oob, flags, true)
168+
+ rsa := newWSARsa()
169+
+ defer wsaRsaPool.Put(rsa)
170+
+ msg := newWSAMsg(p, oob, flags, rsa)
171+
defer freeWSAMsg(msg)
172+
n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
173+
err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
174+
@@ -1396,7 +1407,9 @@
175+
p = p[:maxRW]
176+
}
177+
178+
- msg := newWSAMsg(p, oob, flags, true)
179+
+ rsa := newWSARsa()
180+
+ defer wsaRsaPool.Put(rsa)
181+
+ msg := newWSAMsg(p, oob, flags, rsa)
182+
defer freeWSAMsg(msg)
183+
n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
184+
err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
185+
@@ -1420,7 +1433,9 @@
186+
p = p[:maxRW]
187+
}
188+
189+
- msg := newWSAMsg(p, oob, flags, true)
190+
+ rsa := newWSARsa()
191+
+ defer wsaRsaPool.Put(rsa)
192+
+ msg := newWSAMsg(p, oob, flags, rsa)
193+
defer freeWSAMsg(msg)
194+
n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
195+
err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
196+
@@ -1444,15 +1459,18 @@
197+
}
198+
defer fd.writeUnlock()
199+
200+
- msg := newWSAMsg(p, oob, 0, sa != nil)
201+
- defer freeWSAMsg(msg)
202+
+ var rsa *wsaRsa
203+
if sa != nil {
204+
+ rsa = newWSARsa()
205+
+ defer wsaRsaPool.Put(rsa)
206+
var err error
207+
- msg.Namelen, err = sockaddrToRaw(msg.Name, sa)
208+
+ rsa.namelen, err = sockaddrToRaw(&rsa.name, sa)
209+
if err != nil {
210+
return 0, 0, err
211+
}
212+
}
213+
+ msg := newWSAMsg(p, oob, 0, rsa)
214+
+ defer freeWSAMsg(msg)
215+
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
216+
err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
217+
return qty, err
218+
@@ -1471,11 +1489,14 @@
219+
}
220+
defer fd.writeUnlock()
221+
222+
- msg := newWSAMsg(p, oob, 0, sa != nil)
223+
- defer freeWSAMsg(msg)
224+
+ var rsa *wsaRsa
225+
if sa != nil {
226+
- msg.Namelen = sockaddrInet4ToRaw(msg.Name, sa)
227+
+ rsa = newWSARsa()
228+
+ defer wsaRsaPool.Put(rsa)
229+
+ rsa.namelen = sockaddrInet4ToRaw(&rsa.name, sa)
230+
}
231+
+ msg := newWSAMsg(p, oob, 0, rsa)
232+
+ defer freeWSAMsg(msg)
233+
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
234+
err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
235+
return qty, err
236+
@@ -1494,11 +1515,14 @@
237+
}
238+
defer fd.writeUnlock()
239+
240+
- msg := newWSAMsg(p, oob, 0, sa != nil)
241+
- defer freeWSAMsg(msg)
242+
+ var rsa *wsaRsa
243+
if sa != nil {
244+
- msg.Namelen = sockaddrInet6ToRaw(msg.Name, sa)
245+
+ rsa = newWSARsa()
246+
+ defer wsaRsaPool.Put(rsa)
247+
+ rsa.namelen = sockaddrInet6ToRaw(&rsa.name, sa)
248+
}
249+
+ msg := newWSAMsg(p, oob, 0, rsa)
250+
+ defer freeWSAMsg(msg)
251+
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
252+
err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
253+
return qty, err

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252

5353
# TODO: remove after issue77975 fixed, see: https://github.com/golang/go/issues/77975
5454
- name: Fix issue77975 for Golang1.26
55-
if: ${{ matrix.jobs.goversion == '1.26' }}
55+
if: ${{ matrix.go-version == '1.26' }}
5656
run: |
5757
cd $(go env GOROOT)
5858
patch --verbose -p 1 < $GITHUB_WORKSPACE/.github/patch/issue77975.patch

0 commit comments

Comments
 (0)