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

Bug: GCM Misidentifies Docker Containers Running on WSL2 Due to /proc/version #1813

Open
vinitsiriya opened this issue Jan 27, 2025 · 3 comments

Comments

@vinitsiriya
Copy link

Description Git Credential Manager (GCM) incorrectly identifies Docker containers running on WSL2 as WSL distributions. This is caused by /proc/version in the container inheriting WSL-related strings (WSL2, microsoft) from the underlying WSL2 host kernel. As a result, GCM incorrectly applies WSL-specific logic and attempts to invoke Windows interop tools (e.g., powershell.exe), which are not available in Linux-native Docker containers.This results in failed Git operations inside the Docker container, even when the container is a full Linux environment.


Steps to Reproduce

Prerequisites:

  1. Docker Desktop is installed on Windows and configured to use WSL2 as the backend.

  2. GCM for Linux is installed inside the Docker container.

Steps:

  1. Start a Full Desktop Environment Docker Container :
    Run a desktop-enabled container like linuxserver/rdesktop:
docker run -it linuxserver/rdesktop
  1. Check Kernel Version Inside the Container :
    Inside the container, run:
cat /proc/version

Output :

Linux version 5.15.167.4-microsoft-standard-WSL2 (root@f9c826d3017f) (gcc (GCC) 11.2.0, GNU ld (GNU Binutils) 2.37) #1 SMP Tue Nov 5 00:21:55 UTC 2024

This indicates the container inherits the WSL2 kernel from the host.

  1. Install Git and GCM :
    Inside the container:
apt update && apt install -y git curl
curl -sSL https://github.com/GitCredentialManager/git-credential-manager/releases/download/v2.0.935/gcm-linux-x86_64.2.0.935.tar.gz | tar -xz
sudo ./install.sh
git config --global credential.helper /usr/local/bin/git-credential-manager
  1. Attempt to Clone a Repository :
    Run:
git clone https://<username>@dev.azure.com/<project>/<repo>

Observe the Error :

fatal: An error occurred trying to start process '/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe' with working directory '/root/'. No such file or directory

Current Behavior

  • Detection Logic : GCM incorrectly detects the Docker container as a WSL distribution because /proc/version contains WSL2-related strings (WSL2, microsoft).

  • Interop Issue : GCM tries to invoke Windows tools (e.g., powershell.exe), which do not exist in the container.

  • Result : Git operations relying on GCM fail inside the container.


Expected Behavior GCM should recognize the Docker container as a Linux-native environment and avoid invoking Windows interop tools. It should use Linux-native tools like pass or other credential helpers configured for Linux.


Root Cause The problem lies in the current WSL detection logic in the WslUtils.GetWslVersion method, which checks for WSL-related strings in /proc/version but does not account for Docker containers that inherit these strings from the WSL2 host.

Current Logic:

const string procVersionPath = "/proc/version";
if (fs.FileExists(procVersionPath))
{
    string procVersion = fs.ReadAllText(procVersionPath);
    if (!Regex.IsMatch(procVersion, "[Mm]icrosoft"))
    {
        return 0; // Not WSL
    }
    if (Regex.IsMatch(procVersion, "wsl2", RegexOptions.IgnoreCase))
    {
        return 2; // WSL2
    }
    return 1; // WSL1
}

This does not differentiate between actual WSL distributions and Docker containers running on WSL2.


Proposed Fix

  1. Improve WSL Detection Logic :
  • Add checks for container-specific environments using /proc/1/cgroup or /proc/self/cgroup. If the environment is containerized (e.g., docker, containerd), bypass WSL detection:
if (File.Exists("/proc/1/cgroup"))
{
    string cgroup = File.ReadAllText("/proc/1/cgroup");
    if (Regex.IsMatch(cgroup, "(docker|containerd|kubepods)"))
    {
        return 0; // Not WSL, it's a container
    }
}
  1. Introduce GCM_DISABLE_WSL_SUPPORT :
    Add an environment variable to explicitly disable WSL detection. This allows users to force Linux-native behavior in ambiguous environments. For example:
export GCM_DISABLE_WSL_SUPPORT=1
  1. Default to Linux-Native Tools for Containers :
    If /proc/version contains WSL2-related strings but the environment is containerized, GCM should default to Linux-native behavior instead of invoking Windows tools.

  2. Proposed New Logic :

private static int GetWslVersion(IEnvironment env, IFileSystem fs)
{
    // Check if WSL support is explicitly disabled
    if (env.Variables.TryGetValue("GCM_DISABLE_WSL_SUPPORT", out _))
    {
        return 0; // Treat as non-WSL
    }

    // Detect containers and avoid misclassification as WSL
    if (File.Exists("/proc/1/cgroup"))
    {
        string cgroup = File.ReadAllText("/proc/1/cgroup");
        if (Regex.IsMatch(cgroup, "(docker|containerd|kubepods)"))
        {
            return 0; // Treat as non-WSL
        }
    }

    // Standard WSL detection
    const string procVersionPath = "/proc/version";
    if (fs.FileExists(procVersionPath))
    {
        string procVersion = fs.ReadAllText(procVersionPath);
        if (!Regex.IsMatch(procVersion, "[Mm]icrosoft"))
        {
            return 0; // Not WSL
        }
        if (Regex.IsMatch(procVersion, "wsl2", RegexOptions.IgnoreCase))
        {
            return 2; // WSL2
        }
        return 1; // WSL1
    }

    return 0;
}

Additional Context
This issue primarily affects:

  1. Docker Containers running on WSL2 backends (e.g., Docker Desktop with WSL2 integration).

  2. Linux-native workflows where users expect GCM to operate without invoking Windows interop tools.


@becm
Copy link

becm commented Feb 1, 2025

All attempts to start Windows executables from /mnt/c will still fail if automount or interop settingsare changed.

So the only reliable solution would be to:

  • check if required (entrypoint) binaries are present in (hardcoded?) expected locations
  • fall back to native if anything is amiss with interop scope (no /proc/sys/fs/binfmt_misc/WSLInterop).

@vinitsiriya
Copy link
Author

@becm
okay, but I am taking about a very different case, well if you turn off wsl automount or interop that some setting related to wsl but I am talking about ubuntu that is running as docker image, like this https://docs.linuxserver.io/images/docker-rdesktop/, while that docker is running over wsl as backend,
in this situation, GCM is not working now, there should be an at least a flag to turn off this misclassification that we that they put there as detection of wsl.

@becm
Copy link

becm commented Feb 5, 2025

@vinitsiriya let's assume the above error is triggered due to calling GetWebBrowserAvailable.
There are at least 4 issues in this method:

  1. Assume a WSL kernel provides interop (which it does not per se)
  2. It's possible to call powershell.exe to get the Windows Session ID (which we apparently can not)
  3. Assume not being in an OpenSSH session guarantees us to have an UI (it does not)
  4. We're likely doing this for OAUTH purposes,
    meaning we need the Browser to back-connect to a random port onlocalhost (not possible in docker)

So correctly catching the

  • impossibility to launch powershell.exe (needs mount path and binfmt support) or
  • not getting a SessionId > 0

should redirect to the native IsDesktopSession check instead of continuing any WSL interop path.

This would still not cover the issue that hoping we can launch a Windows-Bowser will get us anything from within a Docker runtime…
But to our advantage(?) it seems to be is really hard to get the WSL binfmt support to work inside a container.
So we fa[il]l back to the native path a lot earlier in the check stack. 😅

So as a summary, GetWslVersion is not the issue here, but the

  • reason for calling it and
  • the interpretation of its result.

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

No branches or pull requests

2 participants