Skip to content

Commit 0cb68ac

Browse files
committed
cmd/go: respect umask when creating executables
Also update many call sites where I forgot that the permission argument is going to be masked by umask. Fixes #12692. Change-Id: I52b315b06236122ca020950447863fa396b68abd Reviewed-on: https://go-review.googlesource.com/17950 Reviewed-by: Ian Lance Taylor <iant@golang.org>
1 parent 807c6c5 commit 0cb68ac

File tree

2 files changed

+58
-9
lines changed

2 files changed

+58
-9
lines changed

Diff for: src/cmd/go/build.go

+27-9
Original file line numberDiff line numberDiff line change
@@ -1476,17 +1476,17 @@ func (b *builder) build(a *action) (err error) {
14761476
switch {
14771477
case strings.HasSuffix(name, _goos_goarch):
14781478
targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext
1479-
if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644, true); err != nil {
1479+
if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666, true); err != nil {
14801480
return err
14811481
}
14821482
case strings.HasSuffix(name, _goarch):
14831483
targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext
1484-
if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644, true); err != nil {
1484+
if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666, true); err != nil {
14851485
return err
14861486
}
14871487
case strings.HasSuffix(name, _goos):
14881488
targ := file[:len(name)-len(_goos)] + "_GOOS." + ext
1489-
if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644, true); err != nil {
1489+
if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666, true); err != nil {
14901490
return err
14911491
}
14921492
}
@@ -1575,7 +1575,7 @@ func (b *builder) getPkgConfigFlags(p *Package) (cflags, ldflags []string, err e
15751575

15761576
func (b *builder) installShlibname(a *action) error {
15771577
a1 := a.deps[0]
1578-
err := ioutil.WriteFile(a.target, []byte(filepath.Base(a1.target)+"\n"), 0644)
1578+
err := ioutil.WriteFile(a.target, []byte(filepath.Base(a1.target)+"\n"), 0666)
15791579
if err != nil {
15801580
return err
15811581
}
@@ -1599,12 +1599,12 @@ func (b *builder) install(a *action) (err error) {
15991599
}
16001600
}()
16011601
a1 := a.deps[0]
1602-
perm := os.FileMode(0644)
1602+
perm := os.FileMode(0666)
16031603
if a1.link {
16041604
switch buildBuildmode {
16051605
case "c-archive", "c-shared":
16061606
default:
1607-
perm = 0755
1607+
perm = 0777
16081608
}
16091609
}
16101610

@@ -1678,7 +1678,25 @@ func (b *builder) moveOrCopyFile(a *action, dst, src string, perm os.FileMode, f
16781678

16791679
// If we can update the mode and rename to the dst, do it.
16801680
// Otherwise fall back to standard copy.
1681-
if err := os.Chmod(src, perm); err == nil {
1681+
1682+
// The perm argument is meant to be adjusted according to umask,
1683+
// but we don't know what the umask is.
1684+
// Create a dummy file to find out.
1685+
// This avoids build tags and works even on systems like Plan 9
1686+
// where the file mask computation incorporates other information.
1687+
mode := perm
1688+
f, err := os.OpenFile(filepath.Clean(dst)+"-go-tmp-umask", os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
1689+
if err == nil {
1690+
fi, err := f.Stat()
1691+
if err == nil {
1692+
mode = fi.Mode() & 0777
1693+
}
1694+
name := f.Name()
1695+
f.Close()
1696+
os.Remove(name)
1697+
}
1698+
1699+
if err := os.Chmod(src, mode); err == nil {
16821700
if err := os.Rename(src, dst); err == nil {
16831701
if buildX {
16841702
b.showcmd("", "mv %s %s", src, dst)
@@ -1765,7 +1783,7 @@ func (b *builder) installHeader(a *action) error {
17651783
}
17661784
}
17671785

1768-
return b.moveOrCopyFile(a, a.target, src, 0644, true)
1786+
return b.moveOrCopyFile(a, a.target, src, 0666, true)
17691787
}
17701788

17711789
// cover runs, in effect,
@@ -3258,7 +3276,7 @@ func (b *builder) swigIntSize(obj string) (intsize string, err error) {
32583276
return "$INTBITS", nil
32593277
}
32603278
src := filepath.Join(b.work, "swig_intsize.go")
3261-
if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0644); err != nil {
3279+
if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0666); err != nil {
32623280
return
32633281
}
32643282
srcs := []string{src}

Diff for: src/cmd/go/go_unix_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2015 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
6+
7+
package main_test
8+
9+
import (
10+
"os"
11+
"syscall"
12+
"testing"
13+
)
14+
15+
func TestGoBuildUmask(t *testing.T) {
16+
// Do not use tg.parallel; avoid other tests seeing umask manipulation.
17+
mask := syscall.Umask(0077) // prohibit low bits
18+
defer syscall.Umask(mask)
19+
tg := testgo(t)
20+
defer tg.cleanup()
21+
tg.tempFile("x.go", `package main; func main() {}`)
22+
tg.creatingTemp("x")
23+
tg.run("build", tg.path("x.go"))
24+
fi, err := os.Stat("x")
25+
if err != nil {
26+
t.Fatal(err)
27+
}
28+
if mode := fi.Mode(); mode&0077 != 0 {
29+
t.Fatalf("wrote x with mode=%v, wanted no 0077 bits", mode)
30+
}
31+
}

0 commit comments

Comments
 (0)