Skip to content

win: Set correct folder permissions after folder creation #38942

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

Merged
merged 1 commit into from
Dec 27, 2020

Conversation

musm
Copy link
Contributor

@musm musm commented Dec 18, 2020

libuv's uv_fs_mkdir does not implement the mode argument on Windows, as a
result the folder mode is never passed on the Windows platform.

This PR:
Forcibly change the folder permissions to agree with the mode passed into mkdir.

Fixes: #38411

TODO: remove when libuv properly sets the mode argument in uv_fs_mkdir

libuv's mkdir does not implement the mode argument on Windows, as a
result the folder mode is never passed on the Windows platform.

Forcibly change the folder permissions to agree with the mode passed
into `mkdir`.
@musm musm added backport 1.5 backport 1.6 Change should be backported to release-1.6 filesystem Underlying file system and functions that use it system:windows Affects only Windows labels Dec 18, 2020
@thofma
Copy link
Contributor

thofma commented Dec 19, 2020

Is it possible to test this?

@musm
Copy link
Contributor Author

musm commented Dec 19, 2020

I don't know, stat reports the same permissions across 1.5.2 1.5.3 and this PR despite there being differences, which is perhaps not surprising, but makes testing difficult. I don't think we have a robust way to set and check ACL permissions on Windows.

@KristofferC KristofferC mentioned this pull request Dec 19, 2020
26 tasks
@@ -179,6 +179,8 @@ function mkdir(path::AbstractString; mode::Integer = 0o777)
uv_error("mkdir($(repr(path)); mode=0o$(string(mode,base=8)))", ret)
end
ccall(:uv_fs_req_cleanup, Cvoid, (Ptr{Cvoid},), req)
# mode is not implemented in mkdir in libuv yet, so do it here
Sys.iswindows() && chmod(path, mode)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per documentation, this mode argument should be restricted by the umask, but there's no good way to get the current umask (libuv uses umask(current_umask = umask(0)), though that's racy and thus a bad idea) :/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what to do about this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vtjnash: do you have a suggestion of what should be done here aside from leaving a comment in case we ever have a umask function that is able to get the umask?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I built Julia with the "offending" libuv commit reverted and the issue persists.

If you want to try it out add the following to your Make.user

override XC_HOST = x86_64-w64-mingw32
override JULIA_CPU_TARGET=generic;sandybridge,-xsaveopt,clone_all;haswell,-rdrnd,base(1)

override USE_BINARYBUILDER_LIBUV=0
override LIBUV_GIT_URL=git://github.com/musm/libuv.git
override LIBUV_BRANCH=julia-uv2-1.39.0
override LIBUV_SHA1=b17d437a171a9cd58459b4736b89298bd19e0c7e

Then run > $env:JULIA_DEPOT_PATH="C:\.julia-dev" in PowerShell and run Julia and add any package. Unless something was built incorrectly (and I don't think it was), the linked issue persists.

So clearly it shouldn't be libuv commit that caused this issue in the 1.5.3 upgrade: #38122, right?

I was almost sure it was the offending libuv commit, but now I don't think so. For one, I checked that child folders created in the parent C:\\ through mkdir in Julia 1.5.2 and Julia 1.5.3 and both had identical permissions. Surprisingly, neither had write permissions, but that doesn't affect things it looks like.

Ok so then I kept digging.

Looking at:
v1.5.2...v1.5.3

And doing some more digging, it looks like a Pkg bump might have caused the permissions changes. In particular, my hunch was that this change could have caused this https://github.com/JuliaLang/Pkg.jl/pull/2150/files#diff-9a6a909fb1a0128f652bc4ca79a4df77d5dbb6bafeac08d5cc2e6e9be9bc07fbR230

So let's test and revert that line.....and once again, unlink permission errors. I also tried reverting 0305b7c and again the same issue.

So I'm at wits end on what's actually causing the linked issue.

Copy link
Contributor Author

@musm musm Dec 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a careful git bisect I'm lead to the following commits triggering this issue on 1.5.3
JuliaLang/libuv@794bfdf
JuliaLang/libuv@1dcf324
julia-master has some additional changes that cause further bugs that mask this, but on 1.5.3, those are the offending commits.

@KristofferC
Copy link
Member

KristofferC commented Dec 27, 2020

Merging this since it feels pretty important to have #38411 fixed for the 1.6 beta. @staticfloat it would be good if you could look at JuliaLang/libuv@794bfdf, JuliaLang/libuv@1dcf324 that seems to have caused Julia to be broken on some Windows installation and comment on if everything is ok with this PR or there is something that has to be fixed / tweaked in our libuv changes.

@KristofferC KristofferC merged commit 556cee7 into JuliaLang:master Dec 27, 2020
KristofferC pushed a commit that referenced this pull request Dec 27, 2020
libuv's mkdir does not implement the mode argument on Windows, as a
result the folder mode is never passed on the Windows platform.

Forcibly change the folder permissions to agree with the mode passed
into `mkdir`.

(cherry picked from commit 556cee7)
@staticfloat
Copy link
Member

The best thing is if someone who encounters a problem could give the output of icacls <file> and maybe icacls <containing folder> or whatever is giving trouble. Without that, I'd just be guessing as to what is going wrong.

@KristofferC
Copy link
Member

@musm, since you could reproduce, perhaps you could show the output of those commands?

@olejorik
Copy link

Here you are: fresh installation of julia1.5.3, with removed folder .julia/compiled/v1.5 :

This is how get the precompilation error

(@v1.5) pkg> add OhMyREPL

 julia> using OhMyREPL
 
[ Info: Precompiling OhMyREPL [5fb14364-9ced-5910-84b2-373655c76a03]
ERROR: LoadError: IOError: unlink: permission denied (EACCES)
Stacktrace:
 [1] uv_error at .\libuv.jl:97 [inlined]
 [2] unlink(::String) at .\file.jl:918
 [3] rm(::String; force::Bool, recursive::Bool) at .\file.jl:268
 [4] compilecache(::Base.PkgId, ::String) at .\loading.jl:1300
 [5] _require(::Base.PkgId) at .\loading.jl:1030
 [6] require(::Base.PkgId) at .\loading.jl:928
 [7] require(::Module, ::Symbol) at .\loading.jl:923
 [8] include(::Function, ::Module, ::String) at .\Base.jl:380
 [9] include(::Module, ::String) at .\Base.jl:368
 [10] top-level scope at none:2
 [11] eval at .\boot.jl:331 [inlined]
 [12] eval(::Expr) at .\client.jl:467
 [13] top-level scope at .\none:3
in expression starting at D:\julia\.julia\packages\OhMyREPL\07uNa\src\OhMyREPL.jl:9
caused by [exception 1]
IOError: unlink: permission denied (EACCES)
Stacktrace:
 [1] uv_error at .\libuv.jl:97 [inlined]
 [2] unlink(::String) at .\file.jl:918
 [3] rm(::String; force::Bool, recursive::Bool) at .\file.jl:268
 [4] rename(::String, ::String; force::Bool) at .\file.jl:928
 [5] compilecache(::Base.PkgId, ::String) at .\loading.jl:1296
 [6] _require(::Base.PkgId) at .\loading.jl:1030
 [7] require(::Base.PkgId) at .\loading.jl:928
 [8] require(::Module, ::Symbol) at .\loading.jl:923
 [9] include(::Function, ::Module, ::String) at .\Base.jl:380
 [10] include(::Module, ::String) at .\Base.jl:368
 [11] top-level scope at none:2
 [12] eval at .\boot.jl:331 [inlined]
 [13] eval(::Expr) at .\client.jl:467
 [14] top-level scope at .\none:3
┌ Warning: temp cleanup
│   exception =
│    IOError: unlink: permission denied (EACCES)
│    Stacktrace:
│     [1] uv_error at .\libuv.jl:97 [inlined]
│     [2] unlink(::String) at .\file.jl:918
│     [3] rm(::String; force::Bool, recursive::Bool) at .\file.jl:268
│     [4] temp_cleanup_purge(::Bool) at .\file.jl:514
│     [5] temp_cleanup_purge() at .\file.jl:507
│     [6] _atexit() at .\initdefs.jl:316
│     [7] exit at .\initdefs.jl:28 [inlined]
│     [8] _start() at .\client.jl:509
└ @ Base.Filesystem file.jl:518
ERROR: Failed to precompile OhMyREPL [5fb14364-9ced-5910-84b2-373655c76a03] to D:\julia\.julia\compiled\v1.5\OhMyREPL\08e1i_ORVRH.ji.
Stacktrace:
 [1] error(::String) at .\error.jl:33
 [2] compilecache(::Base.PkgId, ::String) at .\loading.jl:1305
 [3] _require(::Base.PkgId) at .\loading.jl:1030
 [4] require(::Base.PkgId) at .\loading.jl:928
 [5] require(::Module, ::Symbol) at .\loading.jl:923

And here is the output of icacls command

PS D:\julia1.5.3> icacls D:\julia\.julia\compiled\v1.5\OhMyREPL
D:\julia\.julia\compiled\v1.5\OhMyREPL BUILTIN\Administrators:(I)(F)
                                       BUILTIN\Administrators:(I)(OI)(CI)(IO)(F)
                                       NT AUTHORITY\SYSTEM:(I)(F)
                                       NT AUTHORITY\SYSTEM:(I)(OI)(CI)(IO)(F)
                                       NT AUTHORITY\Authenticated Users:(I)(M)
                                       NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(IO)(M)
                                       BUILTIN\Users:(I)(RX)
                                       BUILTIN\Users:(I)(OI)(CI)(IO)(GR,GE)

Successfully processed 1 files; Failed processing 0 files

The folder D:\julia\.julia\compiled\v1.5\OhMyREPL is empty.

@musm
Copy link
Contributor Author

musm commented Dec 27, 2020

I personally think we should probably revert this when we have the actual fix, because I'm slightly uncomfortable chmod'ing the folder.

Here is the comparison of icalcs (see below)

On 1.5.3 there's the failing to precompile jl_XXX.tmp file and I think the crux of the issue is this file. Take a look at jl_2E8.tmp below. It has different permissions than wLPFy_s6eFQ.ji So somewhere in Pkg.jl I assume this file needs to be merged or overwrite wLPFy_s6eFQ.ji ? Perhaps the libuv bump exposed some issue in the Pkg.jl where this copy or overwrite doesn't have correct permissions on Windows? I'm not sure, this is my guess.

# v1.5.3

> icacls .\.julia-1.5.3\
.\.julia-1.5.3\ BUILTIN\Administrators:(I)(OI)(CI)(F)
                NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
                BUILTIN\Users:(I)(OI)(CI)(RX)
                NT AUTHORITY\Authenticated Users:(I)(M)
                NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(IO)(M)

Successfully processed 1 files; Failed processing 0 files

> icacls .\.julia-1.5.3\compiled\
.\.julia-1.5.3\compiled\ BUILTIN\Administrators:(I)(OI)(CI)(F)
                         NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
                         BUILTIN\Users:(I)(OI)(CI)(RX)
                         NT AUTHORITY\Authenticated Users:(I)(M)
                         NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(IO)(M)

Successfully processed 1 files; Failed processing 0 files

> icacls .\.julia-1.5.3\compiled\v1.5\WinTypes\
.\.julia-1.5.3\compiled\v1.5\WinTypes\ BUILTIN\Administrators:(I)(OI)(CI)(F)
                                       NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
                                       BUILTIN\Users:(I)(OI)(CI)(RX)
                                       NT AUTHORITY\Authenticated Users:(I)(M)
                                       NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(IO)(M)

Successfully processed 1 files; Failed processing 0 files

> icacls .\.julia-1.5.3\compiled\v1.5\WinTypes\wLPFy_s6eFQ.ji
.\.julia-1.5.3\compiled\v1.5\WinTypes\wLPFy_s6eFQ.ji BUILTIN\Administrators:(I)(F)
                                                     NT AUTHORITY\SYSTEM:(I)(F)
                                                     BUILTIN\Users:(I)(RX)
                                                     NT AUTHORITY\Authenticated Users:(I)(M)

Successfully processed 1 files; Failed processing 0 files

> icacls .\.julia-1.5.3\compiled\v1.5\WinTypes\jl_2E8.tmp
.\.julia-1.5.3\compiled\v1.5\WinTypes\jl_2E8.tmp RUSTLER9\Mus:(RX,W,DC)
                                                 Everyone:(RX,W,DC)
                                                 BUILTIN\Users:(RX,W,DC)
                                                 NT AUTHORITY\Authenticated Users:(RX,W,DC)
                                                 BUILTIN\Administrators:(F)
                                                 NT AUTHORITY\SYSTEM:(F)

# v1.5.2

> icacls .\.julia-1.5.2\
.\.julia-1.5.2\ BUILTIN\Administrators:(I)(OI)(CI)(F)
                NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
                BUILTIN\Users:(I)(OI)(CI)(RX)
                NT AUTHORITY\Authenticated Users:(I)(M)
                NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(IO)(M)

Successfully processed 1 files; Failed processing 0 files
> icacls .\.julia-1.5.2\compiled\
.\.julia-1.5.2\compiled\ BUILTIN\Administrators:(I)(OI)(CI)(F)
                         NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
                         BUILTIN\Users:(I)(OI)(CI)(RX)
                         NT AUTHORITY\Authenticated Users:(I)(M)
                         NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(IO)(M)

Successfully processed 1 files; Failed processing 0 files
> icacls .\.julia-1.5.2\compiled\v1.5\WinTypes\
.\.julia-1.5.2\compiled\v1.5\WinTypes\ BUILTIN\Administrators:(I)(OI)(CI)(F)
                                       NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
                                       BUILTIN\Users:(I)(OI)(CI)(RX)
                                       NT AUTHORITY\Authenticated Users:(I)(M)
                                       NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(IO)(M)

Successfully processed 1 files; Failed processing 0 files
> icacls .\.julia-1.5.2\compiled\v1.5\WinTypes\wLPFy_LHVP9.ji
.\.julia-1.5.2\compiled\v1.5\WinTypes\wLPFy_LHVP9.ji BUILTIN\Administrators:(I)(F)
                                                     NT AUTHORITY\SYSTEM:(I)(F)
                                                     BUILTIN\Users:(I)(RX)
                                                     NT AUTHORITY\Authenticated Users:(I)(M)

Successfully processed 1 files; Failed processing 0 files

@yilmazdurmaz
Copy link

@musm
I just noticed this issue's header is about "folder" permissions, but as my tests suggests the problem is "file" permissions.

as I cannot delve into code (at least until I understand some more Julia) to find when and how they are created, all I can direct my fingers is the creation of packages's files, and those of "tmp" files created during compilation, is where to look first.

Also "copy" process is not affected and "jl_2E8.tmp" seems to be first copied into "wLPFy_s6eFQ.ji" then tried to be deleted.

Is this merge covered the file creation or folder creation?

@musm
Copy link
Contributor Author

musm commented Dec 28, 2020

Yes, that's right, I didn't realize the exact failure point until looking at things again today and after several unsuccessful attempts earlier this week. I have made some progress in nailing down what exactly is happening and the failure point, but will still need to investigate a fix.

@staticfloat
Ok so the issue is this:

The temporary cache file has the following differences in permissions

v1.5.2

C:\test-dev-1.5\compiled\v1.5\jl_10B0.tmp BUILTIN\Administrators:(I)(F)
NT AUTHORITY\SYSTEM:(I)(F)
BUILTIN\Users:(I)(RX)
NT AUTHORITY\Authenticated Users:(I)(M)

>v1.5.2 (where we made libuv ACL changes)

icacls.exe C:\test-dev\compiled\v1.7\jl_5A2A.tmp
C:\test-dev\compiled\v1.7\jl_5A2A.tmp RUSTLER9\Mus:(R,W,DC)
Everyone:(R,W,DC)
BUILTIN\Users:(R,W,DC)
NT AUTHORITY\Authenticated Users:(R,W,DC)
BUILTIN\Administrators:(F)
NT AUTHORITY\SYSTEM:(F)

This is a problem because when we go to rename the jl_5A2A.tmp file to the Foo.ji cache file these operations fail with Permission Access.

Do you think this is related to an ACL ordering issue?

musm added a commit to musm/julia that referenced this pull request Dec 28, 2020
@KristofferC KristofferC removed backport 1.5 backport 1.6 Change should be backported to release-1.6 labels Dec 28, 2020
KristofferC added a commit that referenced this pull request Dec 28, 2020
musm added a commit that referenced this pull request Dec 28, 2020
@yilmazdurmaz
Copy link

@musm ,

do you know if libuv is used only when adding packages or for all file/folder related operations in Julia?

if it is used all the time, then I can say I narrowed the problem to ]add PackageName and using PackageName procedure. instead of cheking whole library, it would be better to check how do these two methods create files.

steps to produce to check:

  • remove/rename .julia folder
  • run julia . new .julia folder and Logs in it containing repl_history.jl are created. they have no read/write problem.
  • use only ]registry add to download known registries into registries folder. none of registry folders/files have read/write problem.
  • use ]add DataAPI to add a single package (it needs no additional package and have few files inside). two new folders created with file in it. environment folder and its files have no problem. packages folder seem to have no problem with any subfolder but has the problem for all the files inside package's folder (meaning only files are affected)
  • try using DataAPI. it will create compiled folder structure. compiled .ji file has no problem but compiled *.tmp has the problem.

@musm
Copy link
Contributor Author

musm commented Dec 28, 2020

@yilmazdurmaz Libuv is used almost everywhere we need IO.

Thanks for tracking this down initially. At this point we have a good understanding of what is going on.

We will likely eventually need to un-revert this, but it looks like we will first need to patch up our libuv fork.

The issue is that the xxx.tmp file created in the compiled folder doesn't have permissions to be renamed because the root folder the file resides in compiled doesn't have the required permissions. I think this was working previously since we didn't mess around with ACL privileges, but with those changes we need to be more careful our API meshes together with these new privileges (i.e. missing the chmod call here)

staticfloat pushed a commit that referenced this pull request Jan 15, 2021
libuv's mkdir does not implement the mode argument on Windows, as a
result the folder mode is never passed on the Windows platform.

Forcibly change the folder permissions to agree with the mode passed
into `mkdir`.

(cherry picked from commit 556cee7)
staticfloat pushed a commit that referenced this pull request Jan 15, 2021
ElOceanografo pushed a commit to ElOceanografo/julia that referenced this pull request May 4, 2021
…38942)

libuv's mkdir does not implement the mode argument on Windows, as a
result the folder mode is never passed on the Windows platform.

Forcibly change the folder permissions to agree with the mode passed
into `mkdir`.
ElOceanografo pushed a commit to ElOceanografo/julia that referenced this pull request May 4, 2021
staticfloat pushed a commit that referenced this pull request Dec 23, 2022
libuv's mkdir does not implement the mode argument on Windows, as a
result the folder mode is never passed on the Windows platform.

Forcibly change the folder permissions to agree with the mode passed
into `mkdir`.

(cherry picked from commit 556cee7)
staticfloat pushed a commit that referenced this pull request Dec 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
filesystem Underlying file system and functions that use it system:windows Affects only Windows
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Permission errors for precompilation on Windows
8 participants