]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: respect umask when creating executables
authorRuss Cox <rsc@golang.org>
Thu, 17 Dec 2015 06:38:14 +0000 (01:38 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 17 Dec 2015 19:24:06 +0000 (19:24 +0000)
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>
src/cmd/go/build.go
src/cmd/go/go_unix_test.go [new file with mode: 0644]

index 82fd9833c00ea59389be87c11241d17ef1322c0b..b7cfc87dc7dec654a67d6e2a372e8ce1bb5307cc 100644 (file)
@@ -1476,17 +1476,17 @@ func (b *builder) build(a *action) (err error) {
                switch {
                case strings.HasSuffix(name, _goos_goarch):
                        targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext
-                       if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644, true); err != nil {
+                       if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666, true); err != nil {
                                return err
                        }
                case strings.HasSuffix(name, _goarch):
                        targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext
-                       if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644, true); err != nil {
+                       if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666, true); err != nil {
                                return err
                        }
                case strings.HasSuffix(name, _goos):
                        targ := file[:len(name)-len(_goos)] + "_GOOS." + ext
-                       if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644, true); err != nil {
+                       if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666, true); err != nil {
                                return err
                        }
                }
@@ -1575,7 +1575,7 @@ func (b *builder) getPkgConfigFlags(p *Package) (cflags, ldflags []string, err e
 
 func (b *builder) installShlibname(a *action) error {
        a1 := a.deps[0]
-       err := ioutil.WriteFile(a.target, []byte(filepath.Base(a1.target)+"\n"), 0644)
+       err := ioutil.WriteFile(a.target, []byte(filepath.Base(a1.target)+"\n"), 0666)
        if err != nil {
                return err
        }
@@ -1599,12 +1599,12 @@ func (b *builder) install(a *action) (err error) {
                }
        }()
        a1 := a.deps[0]
-       perm := os.FileMode(0644)
+       perm := os.FileMode(0666)
        if a1.link {
                switch buildBuildmode {
                case "c-archive", "c-shared":
                default:
-                       perm = 0755
+                       perm = 0777
                }
        }
 
@@ -1678,7 +1678,25 @@ func (b *builder) moveOrCopyFile(a *action, dst, src string, perm os.FileMode, f
 
        // If we can update the mode and rename to the dst, do it.
        // Otherwise fall back to standard copy.
-       if err := os.Chmod(src, perm); err == nil {
+
+       // The perm argument is meant to be adjusted according to umask,
+       // but we don't know what the umask is.
+       // Create a dummy file to find out.
+       // This avoids build tags and works even on systems like Plan 9
+       // where the file mask computation incorporates other information.
+       mode := perm
+       f, err := os.OpenFile(filepath.Clean(dst)+"-go-tmp-umask", os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
+       if err == nil {
+               fi, err := f.Stat()
+               if err == nil {
+                       mode = fi.Mode() & 0777
+               }
+               name := f.Name()
+               f.Close()
+               os.Remove(name)
+       }
+
+       if err := os.Chmod(src, mode); err == nil {
                if err := os.Rename(src, dst); err == nil {
                        if buildX {
                                b.showcmd("", "mv %s %s", src, dst)
@@ -1765,7 +1783,7 @@ func (b *builder) installHeader(a *action) error {
                }
        }
 
-       return b.moveOrCopyFile(a, a.target, src, 0644, true)
+       return b.moveOrCopyFile(a, a.target, src, 0666, true)
 }
 
 // cover runs, in effect,
@@ -3258,7 +3276,7 @@ func (b *builder) swigIntSize(obj string) (intsize string, err error) {
                return "$INTBITS", nil
        }
        src := filepath.Join(b.work, "swig_intsize.go")
-       if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0644); err != nil {
+       if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0666); err != nil {
                return
        }
        srcs := []string{src}
diff --git a/src/cmd/go/go_unix_test.go b/src/cmd/go/go_unix_test.go
new file mode 100644 (file)
index 0000000..0d85859
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2015 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package main_test
+
+import (
+       "os"
+       "syscall"
+       "testing"
+)
+
+func TestGoBuildUmask(t *testing.T) {
+       // Do not use tg.parallel; avoid other tests seeing umask manipulation.
+       mask := syscall.Umask(0077) // prohibit low bits
+       defer syscall.Umask(mask)
+       tg := testgo(t)
+       defer tg.cleanup()
+       tg.tempFile("x.go", `package main; func main() {}`)
+       tg.creatingTemp("x")
+       tg.run("build", tg.path("x.go"))
+       fi, err := os.Stat("x")
+       if err != nil {
+               t.Fatal(err)
+       }
+       if mode := fi.Mode(); mode&0077 != 0 {
+               t.Fatalf("wrote x with mode=%v, wanted no 0077 bits", mode)
+       }
+}