haskell / ghcup-hs

https://www.haskell.org/ghcup/
GNU Lesser General Public License v3.0
290 stars 90 forks source link

Running custom bindist's shim requires elevated permissions on Windows #1149

Open jasagredo opened 2 weeks ago

jasagredo commented 2 weeks ago

I have a GHC 9.6.6 with some patches on top that I use daily, named 9.6.6-patched in GHCup.

image

This GHC was installed via hadrian binary-dist, then ghcup install ghc -u file:///<path-to-bindist> 9.6.6-patched.

I can run it from the ghc.exe shim:

➜ /c/ghcup/bin/ghc.exe
ghc-9.6.6.exe: no input files
Usage: For basic information, try the `--help' option.

The shim file for this one and ghc-9.6.6-patched.exe are the same, and the executables are the same (via diff):

➜ cat /c/ghcup/bin/ghc.shim
path = C:\ghcup\ghc\9.6.6-patched\bin\ghc.exe%

➜ cat /c/ghcup/bin/ghc-9.6.6-patched.shim
path = C:\ghcup\ghc\9.6.6-patched\bin\ghc.exe%

➜ diff ghc.exe ghc-9.6.6-patched.exe; echo $?
0

➜ ls -lah ghc.exe ghc-9.6.6-patched.exe
-rwxr-xr-x 1 Javier Javier 113K May  6  2024 ghc.exe
-rwxr-xr-x 1 Javier Javier 113K May  6  2024 ghc-9.6.6-patched.exe

However, running the ghc-9.6.6-patched.exe executable results in a permission error unless we are in an elevated shell:

# normal shell
~
➜ /c/ghcup/bin/ghc-9.6.6-patched.exe
zsh: permission denied: /c/ghcup/bin/ghc-9.6.6-patched.exe

# elevated shell
Administrator in ~
➜ /c/ghcup/bin/ghc-9.6.6-patched.exe
ghc-9.6.6.exe: no input files
Usage: For basic information, try the `--help' option.

I found this out via the following error when compiling HLS for this GHC: image

[ Info  ] Building HLS 2.9.0.1 for GHC version 9.6.6-patched
Searching for curl in path.
Found curl at C:\WINDOWS\SYSTEM32\curl.exe
Searching for powershell in path.
Found powershell at C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Searching for wget in path.
Found wget at C:\msys64\usr\bin\wget.exe
Selected http transport implementation: curl
File monitor 'config' changed: first run
Project settings changed, reconfiguring...
creating
C:\ghcup\tmp\ghcup-9822830f4a81c589\haskell-language-server-2.9.0.1\dist-newstyle\cache
creating
C:\ghcup\tmp\ghcup-9822830f4a81c589\haskell-language-server-2.9.0.1\dist-newstyle
creating
C:\ghcup\tmp\ghcup-9822830f4a81c589\haskell-language-server-2.9.0.1\dist-newstyle\cache
Warning: cannot determine version of C:\ghcup\bin\ghc-9.6.6-patched.exe :
""
Error: [Cabal-1008]
The program 'ghc' version >=7.0.1 is required but the version of C:\ghcup\bin\ghc-9.6.6-patched.exe could not be determined.
CallStack (from HasCallStack):
  dieWithException, called at src\Distribution\Simple\Program\Db.hs:520:13 in Cabal-3.12.1.0-inplace:Distribution.Simple.Program.Db

File monitor 'compiler' changed: first run
Compiler settings changed, reconfiguring...
Searching for ghc-9.6.6-patched in path.
Found ghc-9.6.6-patched at C:\ghcup\bin\ghc-9.6.6-patched.exe
Running: "C:\ghcup\bin\ghc-9.6.6-patched.exe" "--numeric-version"
Error: [GHCup-08841] BuildFailed failed in dir C:\ghcup\tmp\ghcup-9822830f4a81c589\haskell-language-server-2.9.0.1: Process "cabal" with arguments ["v2-install",
                                                                                                                               "-w",
                                                                                                                               "ghc-9.6.6-patched",
                                                                                                                               "--install-method=copy",
                                                                                                                               "--overwrite-policy=always",
                                                                                                                               "--disable-profiling",
                                                                                                                               "--disable-tests",
                                                                                                                               "--installdir=C:\\ghcup\\tmp\\ghcup-9822830f4a81c589\\haskell-language-server-2.9.0.1\\out\\9.6.6-patched",
                                                                                                                               "--project-file=cabal.project",
                                                                                                                               "-v3",
                                                                                                                               "exe:haskell-language-server",
                                                                                                                               "exe:haskell-language-server-wrapper"] failed with exit code 1.
Press enter to continue

Note this succeeds in an elevated shell:


Administrator in ~
❯ ghcup tui
[ Info  ] verifying digest of: gs.exe
[ Info  ] Updating cabal DB
Downloading the latest package lists from:
- hackage.haskell.org
- cardano-haskell-packages
Package list of cardano-haskell-packages is up to date.
The index-state is set to 2024-11-05T09:09:23Z.
Package list of hackage.haskell.org is up to date.
The index-state is set to 2024-11-11T04:00:37Z.
[ Info  ] downloading: https://downloads.haskell.org/~ghcup/unofficial-bindists/haskell-language-server/2.9.0.1/haskell-language-server-2.9.0.1-src.tar.gz as file C:\ghcup\tmp\ghcup-bf169583f4abc607\haskell-language-server-2.9.0.1-src.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 7058k  100 7058k    0     0  18.4M      0 --:--:-- --:--:-- --:--:-- 18.5M
[ Info  ] verifying digest of: haskell-language-server-2.9.0.1-src.tar.gz
[ Info  ] Unpacking: haskell-language-server-2.9.0.1-src.tar.gz to C:\ghcup\tmp\ghcup-2e4270a6ac1940a3
[ Info  ] Building HLS 2.9.0.1 for GHC version 9.6.6-patched
Wrote tarball sdist to
C:\ghcup\tmp\ghcup-2e4270a6ac1940a3\haskell-language-server-2.9.0.1\dist-newstyle\sdist\haskell-language-server-2.9.0.1.tar.gz
Wrote tarball sdist to
C:\ghcup\tmp\ghcup-2e4270a6ac1940a3\haskell-language-server-2.9.0.1\dist-newstyle\sdist\hie-compat-0.3.1.2.tar.gz
Wrote tarball sdist to
C:\ghcup\tmp\ghcup-2e4270a6ac1940a3\haskell-language-server-2.9.0.1\dist-newstyle\sdist\shake-bench-0.2.0.0.tar.gz
Wrote tarball sdist to
C:\ghcup\tmp\ghcup-2e4270a6ac1940a3\haskell-language-server-2.9.0.1\dist-newstyle\sdist\hls-graph-2.9.0.1.tar.gz
Wrote tarball sdist to
C:\ghcup\tmp\ghcup-2e4270a6ac1940a3\haskell-language-server-2.9.0.1\dist-newstyle\sdist\ghcide-2.9.0.1.tar.gz
Wrote tarball sdist to
C:\ghcup\tmp\ghcup-2e4270a6ac1940a3\haskell-language-server-2.9.0.1\dist-newstyle\sdist\hls-plugin-api-2.9.0.1.tar.gz
Wrote tarball sdist to
C:\ghcup\tmp\ghcup-2e4270a6ac1940a3\haskell-language-server-2.9.0.1\dist-newstyle\sdist\hls-test-utils-2.9.0.1.tar.gz
Resolving dependencies...
Build profile: -w ghc-9.6.6 -O1
In order, the following will be built (use -v for more details):
...
hasufell commented 2 weeks ago

This is not proof that there's something wrong with the shim.

Can you run C:\ghcup\ghc\9.6.6-patched\bin\ghc.exe without elevated privileges?

jasagredo commented 2 weeks ago

Yes I can:

~
➜ /c/ghcup/ghc/9.6.6-patched/bin/ghc.exe
ghc-9.6.6.exe: no input files
Usage: For basic information, try the `--help' option.
hasufell commented 2 weeks ago

Is antivirus off?

jasagredo commented 2 weeks ago

Yes, it is off.

dfordivam commented 2 weeks ago

I could not reproduce the issue, I tried with zsh too.

I installed the official https://downloads.haskell.org/~ghc/9.6.6/ghc-9.6.6-x86_64-unknown-mingw32.tar.xz with the name "ghc-9.6.6-patched" for testing

jasagredo commented 2 weeks ago

Surprisingly that works for me too.

➜ ghcup install ghc -u https://downloads.haskell.org/\~ghc/9.6.6/ghc-9.6.6-x86_64-unknown-mingw32.tar.xz 9.6.6-upstream
[ Info  ] downloading: https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-0.0.8.yaml as file C:\ghcup\cache\ghcup-0.0.8.yaml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0
[ Warn  ] New ghc version available. If you want to install this latest version, run 'ghcup install ghc 9.10.1'
[ Info  ] verifying digest of: gs.exe
[ Info  ] downloading: https://downloads.haskell.org/~ghc/9.6.6/ghc-9.6.6-x86_64-unknown-mingw32.tar.xz as file C:\ghcup\tmp\ghcup-e2889c71bc9d3c01\ghc-9.6.6-x86_64-unknown-mingw32.tar.xz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  309M  100  309M    0     0  35.7M      0  0:00:08  0:00:08 --:--:-- 38.9M
[ Info  ] Unpacking: ghc-9.6.6-x86_64-unknown-mingw32.tar.xz to C:\ghcup\tmp\ghcup-ed464af51a8403e2
[ Info  ] Installing GHC (this may take a while)
[ Info  ] Merging file tree from "C:\ghcup\tmp\ghcup-ed464af51a8403e2\ghc-9.6.6-x86_64-unknown-mingw32" to "C:\ghcup\ghc\9.6.6-upstream"
[ Info  ] GHC installation successful

~ took 8m29s
➜ /c/ghcup/bin/ghc-9.6.6-upstream.exe
ghc-9.6.6.exe: no input files
Usage: For basic information, try the `--help' option.

Now I'm quite puzzled on what is going on with the 9.6.6-patched shim. I don't really understand what is going on here, check this:

➜ /c/ghcup/bin/ghc-9.6.6-upstream.exe
ghc-9.6.6.exe: no input files
Usage: For basic information, try the `--help' option.

~
❯ mv /c/ghcup/bin/ghc-9.6.6-patched.exe /c/ghcup/bin/ghc-9.6.6-back.exe

~
➜ cp /c/ghcup/bin/ghc-9.6.6-upstream.exe /c/ghcup/bin/ghc-9.6.6-patched.exe

~
➜ /c/ghcup/bin/ghc-9.6.6-patched.exe
zsh: permission denied: /c/ghcup/bin/ghc-9.6.6-patched.exe
jasagredo commented 2 weeks ago

Ok this is something I would not expect. If I get into PowerShell, I can try to execute both ghc-9.6.6-patched.exe and ghc-9.6.6-upstream.exe which are the same file as per the above sequence of commands. And I get this:

C:\ghcup\bin
➜ .\ghc-9.6.6-upstream.exe
ghc-9.6.6.exe: no input files
Usage: For basic information, try the `--help' option.

C:\ghcup\bin
➜ .\ghc-9.6.6-patched.exe

And the second one prompts a UAC dialog: image Which even if I click Yes, still has no output:

C:\ghcup\bin 
➜ .\ghc-9.6.6-patched.exe

C:\ghcup\bin
➜
jasagredo commented 2 weeks ago

Ok I think I have an answer and it is not what I was expecting: https://stackoverflow.com/questions/20096706/how-does-windows-decide-whether-to-display-the-uac-prompt

Before a 32 bit process is created, the following attributes are checked to determine whether it is an installer:

  • Filename includes keywords like "install," "setup," "update," etc.

And my ghc has patched on its name. If I change it to ptched:

C:\ghcup\bin took 22s
➜ mv .\ghc-9.6.6-patched.exe .\ghc-9.6.6-ptched.exe

C:\ghcup\bin
❯ mv .\ghc-9.6.6-patched.shim .\ghc-9.6.6-ptched.shim

C:\ghcup\bin
➜ .\ghc-9.6.6-ptched.exe
ghc-9.6.6.exe: no input files
Usage: For basic information, try the `--help' option.

I guess this can close the issue as mystery solved. The issue is with the name of the file making it being considered an installer.

hasufell commented 1 week ago

If we have a more or less comprehensive list of these suffixes/filenames, I think it does make sense on windows to emit a post-install warning (or even pre-install with a 10s sleep timer) about this issue.

jasagredo commented 1 week ago

This only mentions "install", "setup" and "update", now we know also about "patch".

https://learn.microsoft.com/en-us/windows/security/application-security/application-control/user-account-control/how-it-works#installer-detection-technology