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

_build/default/bin/dune.exe: Permission denied (ecryptfs, Mint) #8210

Closed
alan-j-hu opened this issue Jul 13, 2023 · 8 comments · Fixed by #8234 or ocaml/opam-repository#24158
Closed
Assignees
Labels

Comments

@alan-j-hu
Copy link
Contributor

alan-j-hu commented Jul 13, 2023

Expected Behavior

I can upgrade Dune.

Actual Behavior

I get a permission denied error.

Reproduction

I currently have Dune 3.7.1 installed. When I ran opam upgrade, Dune 3.9.1 cannot build due to a permission error.

[ERROR] The compilation of dune.3.9.1 failed at "./_boot/dune.exe build dune.install --release --profile dune-bootstrap -j 15".

#=== ERROR while compiling dune.3.9.1 =========================================#
# context     2.1.4 | linux/x86_64 | ocaml-base-compiler.5.0.0 | https://opam.ocaml.org#7109cb08
# path        ~/.opam/5.0.0/.opam-switch/build/dune.3.9.1
# command     ~/.opam/opam-init/hooks/sandbox.sh build ./_boot/dune.exe build dune.install --release --profile dune-bootstrap -j 15
# exit-code   1
# env-file    ~/.opam/log/dune-208893-44c9eb.env
# output-file ~/.opam/log/dune-208893-44c9eb.out
### output ###
# Error: _build/default/bin/dune.exe: Permission denied
# -> required by _build/default/bin/dune.exe
# -> required by _build/install/default/bin/dune
# -> required by _build/default/dune.install

When I try to upgrade to 3.8.0, 3.8.1, or 3.8.2, I get the error #8041. When I try to upgrade to 3.8.3, 3.9.0, or 3.9.1, I get this current error. #8049, which fixes the sendfile error and was included in 3.8.3, is probably the cause of the current error.

My Linux kernel version is 5.15.0-76-generic, I am running Linux Mint 21.1.

@emillon
Copy link
Collaborator

emillon commented Jul 18, 2023

Thanks. Looks like this is the followup to the same issue, indeed.
Can you help me by answering these questions:

  • is your HOME directory (or the place where you're running opam) a network mount like NFS?
    • if so, can you post the relevant output of the mount command
  • can you install packages that do not use dune, for example you can try opam install fmt?
    Thanks

@alan-j-hu
Copy link
Contributor Author

No, my home directory (where my .opam directory is) is not a network mount. I am using ecryptfs.

I already have fmt installed, so I tried with kcas. This one apparently uses Dune, but I have Dune 3.7.1 installed already.

@emillon
Copy link
Collaborator

emillon commented Jul 18, 2023

Ok, that's interesting. It might be mounted noexec or something like it but I don't understand why it would only be an issue on new dune.

  • Can you post the output of the mount command relevant to the home directory (feel free to redact stuff, I'm only interested to see the options used there, in particular whether user or noexec is there).
  • Can you try to copy your ls binary in your home directory and execute it from there? (cp /usr/bin/ls . then ./ls - the ./ is important)

@emillon emillon changed the title I cannot upgrade Dune to 3.9.1 because of permission denied error. _build/default/bin/dune.exe: Permission denied (ecryptfs, Mint) Jul 18, 2023
@emillon emillon self-assigned this Jul 18, 2023
@emillon emillon added the bug label Jul 18, 2023
@alan-j-hu
Copy link
Contributor Author

This is the output of mount that I think is relevant:

/home/.ecryptfs/alan/.Private on /home/alan type ecryptfs (rw,nosuid,nodev,relatime,<redacted>)

Is there any other information you need?

I can execute a copy of the ls binary in my home directory.

@emillon
Copy link
Collaborator

emillon commented Jul 19, 2023

Thanks, that's helpful. I'll try to repro locally with ecryptfs.
My new working hypothesis is that the error code returned by sendfile depends on the actual FS used and can be at least EINVAL or ENOSYS and that we only support one of these. I'll try to confirm that by tracing; if I can't repro I'll ask you again.

@emillon emillon mentioned this issue Jul 19, 2023
10 tasks
@emillon
Copy link
Collaborator

emillon commented Jul 19, 2023

Ok, I can reproduce this.
For some reason, the output file can't be reopened in the fallback case. Thanks again for the info.

openat(AT_FDCWD, "_build/default/_boot/dune.exe", O_RDONLY) = 7
newfstatat(7, "", {st_mode=S_IFREG|0555, st_size=24871240, ...}, AT_EMPTY_PATH) = 0
openat(AT_FDCWD, "_build/default/bin/dune.exe", O_WRONLY|O_CREAT|O_TRUNC, 0555) = 8
sendfile(8, 7, NULL, 24871240)          = -1 EINVAL (Invalid argument)
close(7)                                = 0
close(8)                                = 0
openat(AT_FDCWD, "_build/default/_boot/dune.exe", O_RDONLY|O_CLOEXEC) = 7
lseek(7, 0, SEEK_CUR)                   = 0
newfstatat(7, "", {st_mode=S_IFREG|0555, st_size=24871240, ...}, AT_EMPTY_PATH) = 0
openat(AT_FDCWD, "_build/default/bin/dune.exe", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0555) = -1 EACCES (Permission denied)

@emillon
Copy link
Collaborator

emillon commented Jul 19, 2023

What's happening is that the output file has been created, but not removed, so open(... O_WRONLY|O_CREAT) fails if the file is not writable.
FTR, it's possible to repro this without ecryptfs by just running strace -f -o strace.out -e inject=sendfile:error=EINVAL make test.

emillon added a commit to emillon/dune that referenced this issue Jul 19, 2023
What's happening here is:

- input and output files are open
- sendfile is attempted and fails
- both files are closed
- input file is opened again
- output file is opened again (but already exists)

This throws an error if the output file is not writable.

Signed-off-by: Etienne Millon <me@emillon.org>
emillon added a commit to emillon/dune that referenced this issue Jul 19, 2023
Fixes ocaml#8210

If the `sendfile` branch failed, it left an empty target file. This file
needs to be removed, otherwise the next `open` call can fail if the file
is not writeable.

Signed-off-by: Etienne Millon <me@emillon.org>
@emillon
Copy link
Collaborator

emillon commented Jul 19, 2023

I pushed a fix in #8234.

emillon added a commit to emillon/dune that referenced this issue Jul 19, 2023
Fixes ocaml#8210

If the `sendfile` branch failed, it left an empty target file. This file
needs to be removed, otherwise the next `open` call can fail if the file
is not writeable.

Signed-off-by: Etienne Millon <me@emillon.org>
emillon added a commit that referenced this issue Jul 19, 2023
What's happening here is:

- input and output files are open
- sendfile is attempted and fails
- both files are closed
- input file is opened again
- output file is opened again (but already exists)

This throws an error if the output file is not writable.

Signed-off-by: Etienne Millon <me@emillon.org>
emillon added a commit to emillon/dune that referenced this issue Jul 19, 2023
Fixes ocaml#8210

If the `sendfile` branch failed, it left an empty target file. This file
needs to be removed, otherwise the next `open` call can fail if the file
is not writeable.

Signed-off-by: Etienne Millon <me@emillon.org>
gridbugs pushed a commit to gridbugs/dune that referenced this issue Jul 20, 2023
What's happening here is:

- input and output files are open
- sendfile is attempted and fails
- both files are closed
- input file is opened again
- output file is opened again (but already exists)

This throws an error if the output file is not writable.

Signed-off-by: Etienne Millon <me@emillon.org>
emillon added a commit to emillon/dune that referenced this issue Jul 24, 2023
Fixes ocaml#8210

If the `sendfile` branch failed, it left an empty target file. This file
needs to be removed, otherwise the next `open` call can fail if the file
is not writeable.

Signed-off-by: Etienne Millon <me@emillon.org>
emillon added a commit to emillon/dune that referenced this issue Jul 24, 2023
Fixes ocaml#8210

If the `sendfile` branch failed, it leaves an empty target file, so
retrying will fail. Instead we reuse the fd directly.

Signed-off-by: Etienne Millon <me@emillon.org>
emillon added a commit that referenced this issue Jul 24, 2023
Fixes #8210

If the `sendfile` branch failed, it leaves an empty target file, so
retrying will fail. Instead we reuse the fd directly.

Signed-off-by: Etienne Millon <me@emillon.org>
emillon added a commit to emillon/dune that referenced this issue Jul 25, 2023
What's happening here is:

- input and output files are open
- sendfile is attempted and fails
- both files are closed
- input file is opened again
- output file is opened again (but already exists)

This throws an error if the output file is not writable.

Signed-off-by: Etienne Millon <me@emillon.org>
emillon added a commit to emillon/dune that referenced this issue Jul 25, 2023
Fixes ocaml#8210

If the `sendfile` branch failed, it leaves an empty target file, so
retrying will fail. Instead we reuse the fd directly.

Signed-off-by: Etienne Millon <me@emillon.org>
emillon added a commit to emillon/dune that referenced this issue Jul 25, 2023
What's happening here is:

- input and output files are open
- sendfile is attempted and fails
- both files are closed
- input file is opened again
- output file is opened again (but already exists)

This throws an error if the output file is not writable.

Signed-off-by: Etienne Millon <me@emillon.org>
emillon added a commit to emillon/dune that referenced this issue Jul 25, 2023
Fixes ocaml#8210

If the `sendfile` branch failed, it leaves an empty target file, so
retrying will fail. Instead we reuse the fd directly.

Signed-off-by: Etienne Millon <me@emillon.org>
emillon added a commit that referenced this issue Jul 25, 2023
* test: repro for #8210 (EACCESS if sendfile fails)

What's happening here is:

- input and output files are open
- sendfile is attempted and fails
- both files are closed
- input file is opened again
- output file is opened again (but already exists)

This throws an error if the output file is not writable.

Signed-off-by: Etienne Millon <me@emillon.org>

* refactor: use Exn.protect instead of protectx (#8235)

This adds a layer of rebinding that obscures what is going on.

Signed-off-by: Etienne Millon <me@emillon.org>

* fix(sendfile): unlink dst before fallback (#8234)

Fixes #8210

If the `sendfile` branch failed, it leaves an empty target file, so
retrying will fail. Instead we reuse the fd directly.

Signed-off-by: Etienne Millon <me@emillon.org>

---------

Signed-off-by: Etienne Millon <me@emillon.org>
pmwhite pushed a commit to pmwhite/dune that referenced this issue Aug 10, 2023
Fixes ocaml#8210

If the `sendfile` branch failed, it leaves an empty target file, so
retrying will fail. Instead we reuse the fd directly.

Signed-off-by: Etienne Millon <me@emillon.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants