Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

os: executable FileMode bit is not set on Windows #41809

Open
gochist opened this issue Oct 6, 2020 · 7 comments
Open

os: executable FileMode bit is not set on Windows #41809

gochist opened this issue Oct 6, 2020 · 7 comments
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows
Milestone

Comments

@gochist
Copy link

gochist commented Oct 6, 2020

What version of Go are you using (go version)?

$ go version
go version go1.13.8 windows/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\june.yi\AppData\Local\go-build
set GOENV=C:\Users\june.yi\AppData\Roaming\go\env
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\june.yi\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\june.yi\Aset GOGCCFLAGS=-m64 -mthreads -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\june.yi\A
ppData\Local\Temp\go-build564788466=/tmp/go-build -gno-record-gcc-switches

What did you do?

I ran the code to check if a file is executable on Windows.

package main

import "os"

func main() {
	f, err := os.Stat("C:\\Users\\june.yi\\Downloads\\SopsSecretGenerator_1.3.1_windows_amd64.exe")

	if err == nil {
		println(f.Mode())
		println(f.Mode() & 0111 == 0000)
	}
}

What did you expect to see?

Bit operation was performed to implement a function that checks whether a file is executable. However, it seems that the executable bit is not set even though it is an executable file on Windows.

493
false

(493==0755)

What did you see instead?

438
true

(438==0644)

@ianlancetaylor ianlancetaylor changed the title Executable FileMode bit is not set on Windows os: executable FileMode bit is not set on Windows Oct 6, 2020
@ianlancetaylor ianlancetaylor added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows labels Oct 6, 2020
@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Oct 6, 2020
@ianlancetaylor
Copy link
Contributor

How do you suggest we decide whether a file is executable on Windows?

@gochist
Copy link
Author

gochist commented Oct 7, 2020

I'm sorry I don't have a solid idea. But wouldn't the following quote help?

Checking access is discouraged since it's race-prone, but if you have to do it in POSIX, you should use faccessat with X_OK and AT_EACCESS in order to evaluate the file's mode and ACL permissions against the effective user and group IDs and supplementary groups of the process. -- from https://stackoverflow.com/questions/63911706/how-to-check-if-a-file-is-executable-on-windows-with-golang#comment113020583_63911706

@davecheney
Copy link
Contributor

Can I ask, if go were changed to return the mode bits you propose, what problem would that allow you to solve?

Perhaps there is another way to accomplish what you need without wading into the depths of Unix file permissions on a platform that isn’t Unix. Do you think that is possible?

@networkimprov
Copy link

cc @alexbrainman @mattn @iwdgo

@gochist
Copy link
Author

gochist commented Oct 7, 2020

@davecheney

Can I ask, if go were changed to return the mode bits you propose, what problem would that allow you to solve?

There is a plugin system in a cli-based tool called kustomize, which supports exec type and go library type. FileMode is used to determine whether a plug-in is available when loading a plug-in and to classify the type, but in Windows, it is getting different results than the intended one. (related with kubernetes-sigs/kustomize#3027)

Perhaps there is another way to accomplish what you need without wading into the depths of Unix file permissions on a platform that isn’t Unix. Do you think that is possible?

I think it is possible. However, from the kustomize project's point of view(although I am not an active contributor), it also seems necessary to check whether the standard library will support this feature in the future in any way.

@mattn
Copy link
Member

mattn commented Oct 7, 2020

I do not agree with this. File permissions and ACLs need to be distinguished. Whereas the file's permissions indicate whether the file itself is executable or not, the ACL indicates whether the file is accessible or not for the user. Also, File permissions must be persistent when copied to another file system. Windows file system has no executable bits for executables. Also we can't determine file extension. For example, we can execute script files using PATHEXT enviroment variable.

One more thing I have to mention about this. Windows can execute without .exe, .bat, .com or file extensions contains in PATHEXT.

C:\temp>type test.go
package main

func main() {
        println("Hello!")
}

C:\temp>go build test.go

C:\temp>ren test.exe test.gopher

C:\temp>test.gopher
Hello!

Probably cmd.exe is looking magick-word MZ in the file. So we can't check the file extension for determine that the file is executable. i.e. we should not have a way to determine the file is executable, I think.

@jgrieger
Copy link

jgrieger commented Nov 8, 2023

What about the GetBinaryTypeW function?

I have a POC using the golang.org/x/sys/windows package, passing the path of an executable file with arbitrary file extension, receiving the value 6 (SCS_64BIT_BINARY) = "A 64-bit Windows-based application.".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows
Projects
None yet
Development

No branches or pull requests

6 participants