Visitar URL original
dotnet test fails on linux-arm64 since SDK 9.0.321: artifacts directory verification uses x64 open() flags (errno 22) · Issue #16657 · microsoft/vstest · GitHub
Skip to content

dotnet test fails on linux-arm64 since SDK 9.0.321: artifacts directory verification uses x64 open() flags (errno 22) #16657

Open

Description

@lioravr1

Description

Since .NET SDK 9.0.321 (released 2026-11-10, VSTest 17.14 17.1400.226.52835), dotnet test exits with code 1 on linux-arm64 even when every test passes. SDK 9.0.320 is not affected, and linux-x64 is not affected.

Passed!  - Failed: 0, Passed: 1006, Skipped: 3, Total: 1009, Duration: 1 s - MyTests.dll (net9.0)
The test session artifacts were not saved: Could not open '/tmp/<guid>/1_<guid>', errno: 22. Set VSTEST_DISABLE_ARTIFACTS_DIRECTORY_VERIFICATION=1 to skip this check.
The test session directory '/tmp/<guid>/1_<guid>' can be accessed by users other than its owner, it should allow the owner only. Set VSTEST_DISABLE_ARTIFACTS_DIRECTORY_VERIFICATION=1 to skip this check.

We hit it in CI on every multi-arch Docker build (mcr.microsoft.com/dotnet/sdk:9.0-alpine, arm64 agent, dotnet test --collect:"XPlat Code Coverage").

Root cause

ArtifactProcessingManager.VerifyDirectoryHasUserOnlyAccess opens the session directory with flags from GetOpenNoFollowDirectoryFlags(). Decompiled from Microsoft.TestPlatform.CrossPlatEngine.dll in SDK 9.0.321:

private static int GetOpenNoFollowDirectoryFlags()
{
    if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        return 196608;   // 0x30000
    return 1048832;
}

0x30000 is O_DIRECTORY | O_NOFOLLOW only on the asm-generic layout used by x86/x64 and others. On arm/arm64 (and powerpc) Linux uses different values:

Architecture O_DIRECTORY O_NOFOLLOW Meaning of 0x30000
x86_64 0x10000 0x20000 O_DIRECTORY | O_NOFOLLOW (intended)
aarch64 0x4000 0x8000 O_DIRECT | O_LARGEFILE

Opening a directory with O_DIRECT returns EINVAL (22), so the check always fails on arm64. Because fchmod is never reached, the directory keeps mode 0755, which then triggers the second message ("can be accessed by users other than its owner").

Minimal repro (no .NET needed)

import os, errno
d = "/tmp/probe"; os.makedirs(d, exist_ok=True)
for name, fl in [("vstest 0x30000", 0x30000), ("O_DIRECTORY|O_NOFOLLOW", os.O_DIRECTORY | os.O_NOFOLLOW)]:
    try: os.close(os.open(d, fl)); print(name, "OK")
    except OSError as e: print(name, "errno", e.errno, errno.errorcode[e.errno])
$ docker run --rm --platform linux/amd64 -v $PWD/p.py:/p.py python:3-alpine python /p.py
vstest 0x30000 OK
O_DIRECTORY|O_NOFOLLOW OK

$ docker run --rm --platform linux/arm64 -v $PWD/p.py:/p.py python:3-alpine python /p.py
vstest 0x30000 errno 22 EINVAL
O_DIRECTORY|O_NOFOLLOW OK

Suggested fix

Use architecture-specific Linux values:

private static int GetOpenNoFollowDirectoryFlags()
{
    if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
    {
        return 0x100000 | 0x100; // O_DIRECTORY | O_NOFOLLOW
    }

    // Linux: arm, arm64 and powerpc use different values than the asm-generic layout (x86, x64, riscv64, loongarch64, s390x).
    return RuntimeInformation.ProcessArchitecture switch
    {
        Architecture.Arm or Architecture.Arm64 or Architecture.Ppc64le => 0x4000 | 0x8000,
        _ => 0x10000 | 0x20000,
    };
}

A regression test that runs VerifyDirectoryHasUserOnlyAccess on a freshly created directory in the arm64 Linux CI leg would have caught this.

Workarounds

  • Set VSTEST_DISABLE_ARTIFACTS_DIRECTORY_VERIFICATION=1.
  • Pin the SDK to 9.0.320.

Environment

  • .NET SDK 9.0.321 (mcr.microsoft.com/dotnet/sdk:9.0-alpine, digest sha256:7bfcc502abdb2483b9b8d0ada3ac2b77fb888aa1824ffe0bb2ad400bc6a9b339)
  • VSTest 17.14.2 (17.1400.226.52835)
  • linux-arm64 (Alpine 3.24, Docker/BuildKit)

Activity

  1. github-actions commented on Nov 11, 2026

    @github-actions
    Contributor

    🤖 Automated triage: thanks for the detailed report. The analysis is consistent with the flags described: 0x30000 is O_DIRECTORY | O_NOFOLLOW only on the asm-generic layout, and means O_DIRECT | O_LARGEFILE on arm/arm64.

    GetOpenNoFollowDirectoryFlags isn't in main yet. The artifact-directory hardening appears to be in the open PRs #16656 and #16653, so a fix PR can't be built on main now. The architecture-specific flags suggested here should be applied in those PRs, or in a follow-up once one lands. A regression test on the arm64 Linux leg would also help.

    🔍 Triaged by Issue Repro Triage & Auto-Fix 🔍

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions