Skip to content

Commit ddd1cda

Browse files
committed
windows: fix race when allocating buffer for some windows syscalls
From main repo: https://go-review.googlesource.com/#/c/4940 Change-Id: I56fe7f6aedc0fd350abb94299ad500fcb80c049a Reviewed-on: https://go-review.googlesource.com/8604 Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent ea75526 commit ddd1cda

File tree

3 files changed

+59
-77
lines changed

3 files changed

+59
-77
lines changed

windows/env_windows.go

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,17 @@ func Getenv(key string) (value string, found bool) {
1616
if err != nil {
1717
return "", false
1818
}
19-
b := make([]uint16, 100)
20-
n, e := GetEnvironmentVariable(keyp, &b[0], uint32(len(b)))
21-
if n == 0 && e == ERROR_ENVVAR_NOT_FOUND {
22-
return "", false
23-
}
24-
if n > uint32(len(b)) {
25-
b = make([]uint16, n)
26-
n, e = GetEnvironmentVariable(keyp, &b[0], uint32(len(b)))
27-
if n > uint32(len(b)) {
28-
n = 0
19+
n := uint32(100)
20+
for {
21+
b := make([]uint16, n)
22+
n, err = GetEnvironmentVariable(keyp, &b[0], uint32(len(b)))
23+
if n == 0 && err == ERROR_ENVVAR_NOT_FOUND {
24+
return "", false
25+
}
26+
if n <= uint32(len(b)) {
27+
return string(utf16.Decode(b[:n])), true
2928
}
3029
}
31-
return string(utf16.Decode(b[0:n])), true
3230
}
3331

3432
func Setenv(key, value string) error {

windows/exec_windows.go

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66

77
package windows
88

9-
import "syscall"
10-
119
// EscapeArg rewrites command line argument s as prescribed
1210
// in http://msdn.microsoft.com/en-us/library/ms880421.
1311
// This function returns "" (2 double quotes) if s is empty.
@@ -85,21 +83,15 @@ func FullPath(name string) (path string, err error) {
8583
if err != nil {
8684
return "", err
8785
}
88-
buf := make([]uint16, 100)
89-
n, err := GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
90-
if err != nil {
91-
return "", err
92-
}
93-
if n > uint32(len(buf)) {
94-
// Windows is asking for bigger buffer.
95-
buf = make([]uint16, n)
86+
n := uint32(100)
87+
for {
88+
buf := make([]uint16, n)
9689
n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
9790
if err != nil {
9891
return "", err
9992
}
100-
if n > uint32(len(buf)) {
101-
return "", syscall.EINVAL
93+
if n <= uint32(len(buf)) {
94+
return UTF16ToString(buf[:n]), nil
10295
}
10396
}
104-
return UTF16ToString(buf[:n]), nil
10597
}

windows/security_windows.go

Lines changed: 45 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,20 @@ func TranslateAccountName(username string, from, to uint32, initSize int) (strin
4242
if e != nil {
4343
return "", e
4444
}
45-
b := make([]uint16, 50)
46-
n := uint32(len(b))
47-
e = TranslateName(u, from, to, &b[0], &n)
48-
if e != nil {
45+
n := uint32(50)
46+
for {
47+
b := make([]uint16, n)
48+
e = TranslateName(u, from, to, &b[0], &n)
49+
if e == nil {
50+
return UTF16ToString(b[:n]), nil
51+
}
4952
if e != ERROR_INSUFFICIENT_BUFFER {
5053
return "", e
5154
}
52-
// make receive buffers of requested size and try again
53-
b = make([]uint16, n)
54-
e = TranslateName(u, from, to, &b[0], &n)
55-
if e != nil {
55+
if n <= uint32(len(b)) {
5656
return "", e
5757
}
5858
}
59-
return UTF16ToString(b), nil
6059
}
6160

6261
const (
@@ -137,26 +136,23 @@ func LookupSID(system, account string) (sid *SID, domain string, accType uint32,
137136
return nil, "", 0, e
138137
}
139138
}
140-
db := make([]uint16, 50)
141-
dn := uint32(len(db))
142-
b := make([]byte, 50)
143-
n := uint32(len(b))
144-
sid = (*SID)(unsafe.Pointer(&b[0]))
145-
e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
146-
if e != nil {
139+
n := uint32(50)
140+
dn := uint32(50)
141+
for {
142+
b := make([]byte, n)
143+
db := make([]uint16, dn)
144+
sid = (*SID)(unsafe.Pointer(&b[0]))
145+
e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
146+
if e == nil {
147+
return sid, UTF16ToString(db), accType, nil
148+
}
147149
if e != ERROR_INSUFFICIENT_BUFFER {
148150
return nil, "", 0, e
149151
}
150-
// make receive buffers of requested size and try again
151-
b = make([]byte, n)
152-
sid = (*SID)(unsafe.Pointer(&b[0]))
153-
db = make([]uint16, dn)
154-
e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
155-
if e != nil {
152+
if n <= uint32(len(b)) {
156153
return nil, "", 0, e
157154
}
158155
}
159-
return sid, UTF16ToString(db), accType, nil
160156
}
161157

162158
// String converts sid to a string format
@@ -198,24 +194,22 @@ func (sid *SID) LookupAccount(system string) (account, domain string, accType ui
198194
return "", "", 0, err
199195
}
200196
}
201-
b := make([]uint16, 50)
202-
n := uint32(len(b))
203-
db := make([]uint16, 50)
204-
dn := uint32(len(db))
205-
e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
206-
if e != nil {
197+
n := uint32(50)
198+
dn := uint32(50)
199+
for {
200+
b := make([]uint16, n)
201+
db := make([]uint16, dn)
202+
e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
203+
if e == nil {
204+
return UTF16ToString(b), UTF16ToString(db), accType, nil
205+
}
207206
if e != ERROR_INSUFFICIENT_BUFFER {
208207
return "", "", 0, e
209208
}
210-
// make receive buffers of requested size and try again
211-
b = make([]uint16, n)
212-
db = make([]uint16, dn)
213-
e = LookupAccountSid(nil, sid, &b[0], &n, &db[0], &dn, &accType)
214-
if e != nil {
209+
if n <= uint32(len(b)) {
215210
return "", "", 0, e
216211
}
217212
}
218-
return UTF16ToString(b), UTF16ToString(db), accType, nil
219213
}
220214

221215
const (
@@ -327,21 +321,20 @@ func (t Token) Close() error {
327321

328322
// getInfo retrieves a specified type of information about an access token.
329323
func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
330-
b := make([]byte, initSize)
331-
var n uint32
332-
e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
333-
if e != nil {
324+
n := uint32(initSize)
325+
for {
326+
b := make([]byte, n)
327+
e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
328+
if e == nil {
329+
return unsafe.Pointer(&b[0]), nil
330+
}
334331
if e != ERROR_INSUFFICIENT_BUFFER {
335332
return nil, e
336333
}
337-
// make receive buffers of requested size and try again
338-
b = make([]byte, n)
339-
e = GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
340-
if e != nil {
334+
if n <= uint32(len(b)) {
341335
return nil, e
342336
}
343337
}
344-
return unsafe.Pointer(&b[0]), nil
345338
}
346339

347340
// GetTokenUser retrieves access token t user account information.
@@ -367,19 +360,18 @@ func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
367360
// GetUserProfileDirectory retrieves path to the
368361
// root directory of the access token t user's profile.
369362
func (t Token) GetUserProfileDirectory() (string, error) {
370-
b := make([]uint16, 100)
371-
n := uint32(len(b))
372-
e := GetUserProfileDirectory(t, &b[0], &n)
373-
if e != nil {
363+
n := uint32(100)
364+
for {
365+
b := make([]uint16, n)
366+
e := GetUserProfileDirectory(t, &b[0], &n)
367+
if e == nil {
368+
return UTF16ToString(b), nil
369+
}
374370
if e != ERROR_INSUFFICIENT_BUFFER {
375371
return "", e
376372
}
377-
// make receive buffers of requested size and try again
378-
b = make([]uint16, n)
379-
e = GetUserProfileDirectory(t, &b[0], &n)
380-
if e != nil {
373+
if n <= uint32(len(b)) {
381374
return "", e
382375
}
383376
}
384-
return UTF16ToString(b), nil
385377
}

0 commit comments

Comments
 (0)