Skip to content

Commit ed08d2a

Browse files
neildgopherbot
authored andcommitted
os: don't follow symlinks on Windows when O_CREATE|O_EXCL and read-only
Fix a bug in CL 672396, where we add FILE_FLAG_OPEN_REPARSE_POINT to the attributes passed to CreateFile, but then overwrite the attributes with FILE_ATTRIBUTE_READONLY when opening a file with a read-only permissions mode. For #73702 Change-Id: I6c10bf470054592bafa031732585fc3155c61341 Reviewed-on: https://go-review.googlesource.com/c/go/+/676655 Auto-Submit: Damien Neil <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Alan Donovan <[email protected]>
1 parent fce9d45 commit ed08d2a

File tree

2 files changed

+17
-17
lines changed

2 files changed

+17
-17
lines changed

src/os/os_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2309,9 +2309,9 @@ func TestOpenFileCreateExclDanglingSymlink(t *testing.T) {
23092309
var f *File
23102310
var err error
23112311
if r == nil {
2312-
f, err = OpenFile(link, O_WRONLY|O_CREATE|O_EXCL, 0o666)
2312+
f, err = OpenFile(link, O_WRONLY|O_CREATE|O_EXCL, 0o444)
23132313
} else {
2314-
f, err = r.OpenFile(link, O_WRONLY|O_CREATE|O_EXCL, 0o666)
2314+
f, err = r.OpenFile(link, O_WRONLY|O_CREATE|O_EXCL, 0o444)
23152315
}
23162316
if err == nil {
23172317
f.Close()

src/syscall/syscall_windows.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -398,22 +398,7 @@ func Open(name string, flag int, perm uint32) (fd Handle, err error) {
398398
if flag&O_CLOEXEC == 0 {
399399
sa = makeInheritSa()
400400
}
401-
// We don't use CREATE_ALWAYS, because when opening a file with
402-
// FILE_ATTRIBUTE_READONLY these will replace an existing file
403-
// with a new, read-only one. See https://go.dev/issue/38225.
404-
//
405-
// Instead, we ftruncate the file after opening when O_TRUNC is set.
406-
var createmode uint32
407401
var attrs uint32 = FILE_ATTRIBUTE_NORMAL
408-
switch {
409-
case flag&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
410-
createmode = CREATE_NEW
411-
attrs |= FILE_FLAG_OPEN_REPARSE_POINT // don't follow symlinks
412-
case flag&O_CREAT == O_CREAT:
413-
createmode = OPEN_ALWAYS
414-
default:
415-
createmode = OPEN_EXISTING
416-
}
417402
if perm&S_IWRITE == 0 {
418403
attrs = FILE_ATTRIBUTE_READONLY
419404
}
@@ -433,6 +418,21 @@ func Open(name string, flag int, perm uint32) (fd Handle, err error) {
433418
const _FILE_FLAG_WRITE_THROUGH = 0x80000000
434419
attrs |= _FILE_FLAG_WRITE_THROUGH
435420
}
421+
// We don't use CREATE_ALWAYS, because when opening a file with
422+
// FILE_ATTRIBUTE_READONLY these will replace an existing file
423+
// with a new, read-only one. See https://go.dev/issue/38225.
424+
//
425+
// Instead, we ftruncate the file after opening when O_TRUNC is set.
426+
var createmode uint32
427+
switch {
428+
case flag&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
429+
createmode = CREATE_NEW
430+
attrs |= FILE_FLAG_OPEN_REPARSE_POINT // don't follow symlinks
431+
case flag&O_CREAT == O_CREAT:
432+
createmode = OPEN_ALWAYS
433+
default:
434+
createmode = OPEN_EXISTING
435+
}
436436
h, err := createFile(namep, access, sharemode, sa, createmode, attrs, 0)
437437
if h == InvalidHandle {
438438
if err == ERROR_ACCESS_DENIED && (attrs&FILE_FLAG_BACKUP_SEMANTICS == 0) {

0 commit comments

Comments
 (0)