haskell / cabal

Official upstream development repository for Cabal and cabal-install
https://haskell.org/cabal
Other
1.62k stars 691 forks source link

file permissions of installed files on windows #447

Closed bos closed 11 years ago

bos commented 12 years ago

(Imported from Trac #454, reported by @toxaris on 2009-01-13)

When installing a binary on Windows Vista using ghc 6.10.1 and Cabal 1.6.0.1, it is not accessible for ordinary users. Old binaries installed with ghc 6.8.2 and Cabal 1.4 had "read" and "execute" permissions set for "all users", while new binaries have only permissions set for "administrators".

Cabal should set "read" and "execute" permissions for "all users" for binaries.

A workaround is to manually set these permissions using the executable's properties dialog.

bos commented 12 years ago

(Imported comment by @dcoutts on 2009-01-13)

The problem occurs since we changed the way in which we copy file permissions. We used to do it incorrectly using the generic portable code. The problem before was that it lost permissions because the generic permissions representation is lossy for unix and windows. We now copy them all using some FFI magic. Unfortunately for Vista it looks like the original .exe gets created such that it cannot be used by anyone other than the admin user. So faithfully copying the file permissions means it is unusable.

The right thing to do seems to be to ignore the original permissions and install the files with explicitly the right permissions. This means distinguishing executable files from non-executable files during install. The code to set the permissions will probably have to be OS-specific. Basically it should do the equivalent of the traditional unix install program.

bos commented 12 years ago

(Imported comment by @dcoutts on 2009-01-13)

See #93.

bos commented 12 years ago

(Imported comment by @dcoutts on 2009-01-19)

http://haskell.org/pipermail/libraries/2009-January/011202.html

Looks like it can affect all files. In copyFile uses the copyPermissions too. It's not yet clear why this affects ghc-6.10 but does not appear to affect 6.8.

bos commented 12 years ago

(Imported comment by @dcoutts on 2009-01-21)

Unfortunately I'm completely stuck here. I cannot reproduce any of these issues because I've only go access as non-admin to a win2k3 machine.

We need to get clear what is really going on and in what environments. The important factors seem to be if the user is using ghc-6.8 or 6.10, Cabal-1.2 or 1.6, XP or Vista and if they're installing as admin or not. Whether they are global installs or not is also relevant.

In the email thread above Dominic notes:

When I rebuild the package _without_ having cleaned out haskell_packages
then I get the access error. I think this is because cabal (copyFile)
doesn't want to overwrite a read only file even though the directory
permissions should allow it to do so.
This should not be the case, but we should confirm it. The copyFile function creates a temporary file in the target directory, copies the data into it, then atomically renames over the target file. That should not fail even if the target file is read only. In my tests that works fine. I think what is clear however is that we should not be copying the original file permissions. We should set them explicitly. However what we should set them to is not clear. For a global install it would be customary to make the files read only while for a per-user install that is not necessary. How do ordinary unix installers manage this? Is it just via the umask? So perhaps all we have to do is set files to be readable (and executable files to be executable).
bos commented 12 years ago

(Imported comment by guest on 2009-01-26)

I can report that when using Windows 2008, cabal 1.6.0.1, ghc-6.10.1, I have installed the Encode package using cabal-install as Administrator, then:

looking at the properties on encode.exe under the Security Tab, for Users - Permissions are set to allow "Read & Execute" and "Read". I created a test user account, did runas /user:test "cmd" and successfully ran encode.exe

bos commented 12 years ago

(Imported comment by @dcoutts on 2009-01-26)

For unix I think it's clear we should do the same as install -m644 for data files and whatever the normal thing is for executables. That's what everone else does.

For Windows, I've no idea. The notion of permissions is so completely different. I'm not even sure that copying permissions makes any sense since it goes via a C struct stat which cannot represent Windows ACLs. Can we get away with not setting any permissions at all and just inherit all defaults? The only time we currently set permissions is when creating the temporary file when we open with mode 0o600. On Windows this appears to do precisely nothing. It is no different to creating a file with default permissions.

So here's the concrete proposal:

bos commented 12 years ago

(Imported comment by @dcoutts on 2009-01-26)

Replying to Toxaris:

When installing a binary on Windows Vista using ghc 6.10.1 and Cabal 1.6.0.1, it is not accessible for ordinary users. Old binaries installed with ghc 6.8.2 and Cabal 1.4 had "read" and "execute" permissions set for "all users", while new binaries have only permissions set for "administrators".

Having looked into how permissions are copied I cannot explain this behavior. The way System.Directory.copyFile copies permissions is in fact not to copy any permissions at all (it only copies the read-only attribute). I've tested this on Win2k3. Perhaps the behavior of msvcrt has changed in Windows Vista.

Could you give us more details on how you performed the test and how we can reproduce it. Were you doing global or user installs? Were you running the build and install as administrator? Where were you installing the files?

bos commented 12 years ago

(Imported comment by @toxaris on 2009-01-27)

Replying to @dcoutts:

Could you give us more details on how you performed the test and how we can reproduce it. Were you doing global or user installs? Were you running the build and install as administrator? Where were you installing the files?

I'm running a preinstalled Vista. I use a user account in the local administrator group. I have used a administrator console to run the following tests (see #320).

I performed a first test by running "cabal install hoogle".

Later, I performed a second test by downloading, unpacking, configuring, building and installing the hoogle package manually, without cabal-install involvement. I used the following commands: "runhaskell Setup configure", "runhaskell Setup build", "runhaskell Setup install".

I repeated both tests with some other package which contains a binary, but I'm not sure which one.

All tests yielded identical results, namely:

"c:\program files\Haskell\bin\hoogle.exe" was replaced by a file with no permissions set for "all users", but permissions set for "administrators". The file does not inherit the permissions set for "c:\program files\Haskell\bin" (read and execute allowed for "all users").

While the only user account I use is part of the "administrators" group, it cannot use the rights associated with this group in normal use. Therefore, I can execute the new hoogle.exe from a administrator console, but not from a normal console.

Does that help? I would be happy to look for more information or run tests if that helps. I can be contacted in #haskell (or here).

bos commented 12 years ago

(Imported comment by @dcoutts on 2009-01-27)

Replying to @toxaris:

Thanks for the details.

I use a user account in the local administrator group. I have used a administrator console to run the following tests (see #320). [...] All tests yielded identical results, namely: "c:\program files\Haskell\bin\hoogle.exe" was replaced by a file with no permissions set for "all users", but permissions set for "administrators". The file does not inherit the permissions set for "c:\program files\Haskell\bin" (read and execute allowed for "all users").

So the interesting thing is why copying an .exe into c:\program files\Haskell\bin does not create a file that inherits the permissions of that directory. I think that is what I would have expected, or at least hoped.

It is not surprising or problematic that when running cabal as administrator that the .exe files generated are executable only by administrator, however I was under the impression that when copying files, the ACLs are not copied and the new file gets default permissions based on the directory it is created in.

It turns out that the Haskell copyFile function does not copy permissions (though it does try to, this turns out not to be effective on Windows, which actually is what we want).

I'm interested in what happens when one creates an ordinary file in c:\program files\Haskell\bin when running as the administrator user. For example if one creates a simple foo.txt file, does that inherit the permission read and execute allowed for "all users"? If so, is the same true if we rename or copy foo.txt

bos commented 12 years ago

(Imported comment by @toxaris on 2009-01-28)

I did some more tests, all of them from an Administrator console (to access c:\Program Files\Haskell\bin at all). I compared ghc -e "System.Directory.copyFile \"from\" \"to\"", ghc -e "System.Directory.renameFile \"from\" \"to\"", copy from to and move from to. Results:

copy and copyFile create or overwrite a file, last changed now, with default permissions for the target directory.

move and renameFile create or overwrite a file, last changed whenever the source file was, with the source file permissions set and the target directory permissions not inherited.

While testing, I realized that this problem affects not only executables, but packages too. I cannot use newly installed packages without Administrator privileges enabled.

C:\ghc\ghc-6.10.1\gcc-lib\ld.exe: cannot find -lHSuniplate-1.2.0.3
collect2: ld returned 1 exit status
Indeed, the files in C:\Program Files\Haskell\uniplate-1.2.0.3\ghc-6.10.1 have the same restrictive permissions set as the executables, while the folders have the correct, inherited permissions. As a manual workaround, I figured out that the following command can be used to reset all permissions to folder defaults: icacls "C:\Program Files\Haskell" /reset /T. With folder defaults, I have no access problems so far.
bos commented 12 years ago

(Imported comment by @dcoutts on 2009-01-28)

I don't think we have a good enough understanding of the problem at the moment so I'm punting this to the next milestone.

It is clear that when copying files we do not copy permissions. That is good. What is not clear is if the files we copy into the target directory get created with non-default permissions for the directory or if it is the default permissions for the directory which are wrong.

In the former case something weird is going on and in the latter case we should work out if it's Cabal that creates the Haskell directory and if so, if the inherited permissions are appropriate. That is, if (as admin) one makes a directory under Program Files then are the default/inherited permissions such that files created in that new dir are readable by everyone or members of the users group.

tibbe commented 11 years ago

Since there has been no activity for over 3 years I'm closing this. If this bug still affects you, please speak up.

dmjio commented 10 years ago

@tibbe, if it wouldn't be too much trouble to reopen, I believe my error might be related.

I have an executable on Windows 2008R2 (compiled w/ GHC 7.8.2) that receives a permission error on copyFile from the directory package. Thinking it was an issue w/ my code I tried the following example and was able to reproduce it.

module Main where

import System.Directory ( copyFile )

main :: IO ()
main = copyFile file path
  where file = "C:/Users/vagrant/SolidTranslate.exe"
        path = "C:/Users/vagrant/Desktop"
vagrant@vagrant-2008R2 /cygdrive/c/Users/vagrant/Desktop/Test
$ ./Main.exe
Main.exe: C:/Users/vagrant\.copyFile600.tmp: copyFile: permission denied (Access is denied.)

The above occurs even after I check run the program as an Adminstrator under the compatibility tab after pressing the Change settings for all users button.

Still occurs after giving Everyone the Full Control permissions settings (under the Security tab).

The strange thing is that ghci doesn't give the same error. It copies the file.

*UPDATE:

When ghci is used to load the file :l Main.hs and then main is called. It does give a permission error. But, when ghci is run, System.Directory is imported and the command to copyFile is run, no error is given and the copy occurs.

dmjio commented 10 years ago

Actually, using System.Process.system :: String -> IO ExitCode I'm able to workaround this for now.

bawa-v commented 1 year ago

Hi,

I run stack build --allow-different-user :duckling-regen-exe && stack exec duckling-regen-exe && stack test for building a service from https://github.com/facebook/duckling

and get the following error from Cabal :

/mnt/c/Users/<user>/<working directory>/.stack-work/dist/x86_64-linux-tinfo6/Cabal-3.0.1.0/.stack-cabal-mod26078-0.tmp: withBinaryFile: permission denied (Operation not permitted)

I changed the permissions of the above folder using sudo chmod -R 1777 /mnt/c/Users/<user>/<working directory>/.stack-work/dist/x86_64-linux-tinfo6/Cabal-3.0.1.0/

But that does not change the error. Any ideas?