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

linux access command giving the wrong answer for X_OK for a non-executable file in a shared volume #5029

Open
2 of 3 tasks
r-owen opened this issue Oct 29, 2020 · 25 comments
Open
2 of 3 tasks

Comments

@r-owen
Copy link

r-owen commented Oct 29, 2020

  • This is a bug report
  • This is a feature request
  • I searched existing issues before opening this one

This may be the same as issue #5007
I can't quite tell. I expected False and in that ticket the user expected "access denied".

Expected behavior

The linux command access(path, F_OK) should return False for a file that is not executable.

Actual behavior

When the file is in a shared volume the access command above returns True for a file that is not executable. This despite ls -l showing that the file is not executable.

Steps to reproduce the behavior

  1. On macOS (I have 10.14.6): create a directory containing at least one file that is not executable.

  2. Run a Docker image that runs CentOS Linux release 7.7.1908 (Core), mounting that directory into the image.
    It simplifies the test if the Docker image includes Python (I have 3.7.8 but it should not matter), but it suffices to have gcc.

  3. Run the following code inside the image:

python -c "import os; print(os.access(<path-to-non-exe-file>, os.X_OK))"

I see True if the file is not executable and is on my shared volume, which is incorrect.
I see the correct result of False if the file is not executable and is internal to the Docker image.

If you would rather not use Python then compile and run the following C++ code.
I get the same results with it as I do with the Python test above.

#include <errno.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    if (argc < 2) {
        printf("one argument required: the path\n");
        return 1;
    }

    char* path = argv[1];
    int rval;

    /* Check file existence. */
    rval = access(path, F_OK);
    if (rval == 0)
        printf("%s exists\n", path);
    else {
        if (errno == ENOENT) {
            printf("%s does not exist\n", path);
        } else if (errno == EACCES) {
            printf("%s is not accessible\n", path);
            return 0;
        }
    }

    /* Check executable access. */
    rval = access(path, X_OK);
    if (rval == 0) {
        printf("%s is executable\n", path);
    } else {
        printf("%s is not executable\n", path);
    }
}

Output of docker version:

Client: Docker Engine - Community
 Cloud integration  0.1.18
 Version:           19.03.13
 API version:       1.40
 Go version:        go1.13.15
 Git commit:        4484c46d9d
 Built:             Wed Sep 16 16:58:31 2020
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.13
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       4484c46d9d
  Built:            Wed Sep 16 17:07:04 2020
  OS/Arch:          linux/amd64
  Experimental:     true
 containerd:
  Version:          v1.3.7
  GitCommit:        8fba4e9a7d01810a393d5d25a3621dc101981175
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

Output of docker info:

$ docker info
Client:
 Debug Mode: false

Server:
 Containers: 3
  Running: 2
  Paused: 0
  Stopped: 1
 Images: 10
 Server Version: 19.03.13
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 8fba4e9a7d01810a393d5d25a3621dc101981175
 runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd
 init version: fec3683
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 4.19.76-linuxkit
 Operating System: Docker Desktop
 OSType: linux
 Architecture: x86_64
 CPUs: 4
 Total Memory: 9.737GiB
 Name: docker-desktop
 ID: VRRF:OCAS:J3SQ:5HIW:GK3Z:JA4A:VDKW:JHSQ:ET6Y:GTJ7:MONZ:7VK7
 Docker Root Dir: /var/lib/docker
 Debug Mode: true
  File Descriptors: 55
  Goroutines: 68
  System Time: 2020-10-23T22:29:19.9940502Z
  EventsListeners: 3
 HTTP Proxy: gateway.docker.internal:3128
 HTTPS Proxy: gateway.docker.internal:3129
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: true
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false
 Product License: Community Engine

Additional environment details (AWS, VirtualBox, physical, etc.)

macOS 10.14.6
And in the Docker image:

  • CentOS Linux release 7.7.1908 (Core)
  • gcc (crosstool-NG 1.24.0.123_1667d2b) 7.5.0
  • Python 3.7.8
@neben
Copy link

neben commented Nov 4, 2020

This can also be easily reproduced with the alpine postgres image and bash, where bash falsely reports the non-executable file on a grpcfuse volume to be executable:

# docker run -v `pwd`/data:/data postgres bash -c 'FILE=data/foo.sh; touch $FILE; chmod -x $FILE; ls -l $FILE; if [ -x "$FILE" ]; then echo file is executable; fi'
-rw-r--r--    1 root     root             0 Nov  4 19:15 data/foo.sh
file is executable

Interestingly enough, sh behaves correctly:

docker run -v `pwd`/data:/data postgres sh -c 'FILE=data/foo.sh; touch $FILE; chmod -x $FILE; ls -l $FILE; if [ -x "$FILE" ]; then echo file is executable; fi'
-rw-r--r--    1 root     root             0 Nov  4 19:17 data/foo.sh

@mryan1539
Copy link

The issue seems to affect access() and faccessat(), but not stat(). /bin/sh on alpine and /bin/ash both use stat(), while bash uses faccessat().

So (with Docker Desktop 2.5.0 on MacOS 10.15):

mkdir mount
touch mount/foo
# The following will output nothing (stat() is used):
docker run -it --mount source=`pwd`/mount,dst=/mount,type=bind alpine sh -c 'test -x /mount/foo && echo exectuable'
# The following will output "executable" (faccessat() is used):
docker run -it --mount source=`pwd`/mount,dst=/mount,type=bind alpine sh -c 'apk add bash > /dev/null; /bin/bash -c "test -x /mount/foo && echo exectuable"'

@mryan1539
Copy link

I've found that this also seems to affect Docker Desktop 2.4.0 as well; 2.3.0.5 functions as expected.

@stephen-turner
Copy link
Contributor

@djs55 PTAL

@docker-robott
Copy link
Collaborator

Issues go stale after 90 days of inactivity.
Mark the issue as fresh with /remove-lifecycle stale comment.
Stale issues will be closed after an additional 30 days of inactivity.

Prevent issues from auto-closing with an /lifecycle frozen comment.

If this issue is safe to close now please do so.

Send feedback to Docker Community Slack channels #docker-for-mac or #docker-for-windows.
/lifecycle stale

@r-owen
Copy link
Author

r-owen commented Feb 8, 2021

/remove-lifecycle stale

@stephen-turner
Copy link
Contributor

/lifecycle frozen

@mryan1539
Copy link

mryan1539 commented Mar 28, 2021

I've found that this can be worked around by disabling gRPC FUSE. Is there some way to detect from the command-line whether gRPC FUSE is enabled or not? Failing that, is it possible to detect over the API?

@stephen-turner
Copy link
Contributor

Not exactly from the command line, but you can find it in the settings.json file.

@vitaly
Copy link

vitaly commented Jul 10, 2021

so.. is there any solution to this? The legacy sharing (when you disable gRPC FUSE) has 1 second file timestamps resolution. which breaks my build process. and gRPC has broken 'test -x' in bash. which also breaks build process ;)

any ideas?

@posita
Copy link

posita commented Mar 16, 2022

Is this a Docker issue or FUSE issue? Is there some way we can at least identify where a fix might exist?

This comes into play when doing VSCode Remote Container development for build/make processes that check for executable permissions.

@mryan1539
Copy link

The new "Enable VirtioFS accelerated directory sharing" feature seems to have the same issue; I assume it forces gRPC FUSE back on.

@josedaniel-escribano-clarity

any news on this?

@noorul
Copy link

noorul commented Jan 26, 2023

I am not sure why is issue not getting any attention.

@akamaryan
Copy link

It seems that both gRPC FUSE and VirtioFS in the very latest version (4.16.2) still suffer from this bug.

Worse, it seems that the legacy osxfs driver is now hanging on access to bind-mounted volumes (at least on MacOS 12.6.3 ARM), breaking the workaround of using it instead, completely breaking my use case for Docker Desktop.

@BenjaminYde
Copy link

got the same issue here

@Cito
Copy link

Cito commented May 5, 2023

Still the same with Docker Desktop 4.19.0.

@walzph
Copy link

walzph commented Jul 27, 2023

And still the same for Docker Desktop 4.21.1

@noorul
Copy link

noorul commented Jul 27, 2023

Not sure why is this not getting the deserving love.

@quiminbano
Copy link

February of 2024 and I have the same issue.

@hjerpe
Copy link

hjerpe commented Apr 21, 2024

I have the same error as of April 2024.

@ashwin153
Copy link

I have the same issue.

@6XGate
Copy link

6XGate commented Aug 9, 2024

This seems to effect the stock official node containers if you give it a CMD to a file that is within a bind mount to your local directory.

@dhruvkb
Copy link

dhruvkb commented Aug 10, 2024

For what its worth, several of my colleagues and I switched to OrbStack instead of Docker Desktop and it does not have this problem. If it is a viable option for you, do consider giving it a try.

@hash0b
Copy link

hash0b commented Nov 17, 2024

I came here while analysing check-executables-have-shebangs pre-commit check failing, in a VS Code Dev Container. I tried using the new Docker VMM (beta) today and the pre-commit check is no longer failing. Just thought to leave a note.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests