Skip to content

Commit 5f1937d

Browse files
author
William Li
authored
Merge pull request #20930 from wli3/fix-ignore-nugetconfig
Fix nuget config not being honored
2 parents c167a66 + 54f18e9 commit 5f1937d

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed

src/Cli/dotnet/StatInterop.cs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
using Microsoft.Win32.SafeHandles;
7+
8+
namespace Microsoft.DotNet.Cli
9+
{
10+
// https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Stat.cs
11+
12+
internal static class StatInterop
13+
{
14+
// Even though csc will by default use a sequential layout, a CS0649 warning as error
15+
// is produced for un-assigned fields when no StructLayout is specified.
16+
//
17+
// Explicitly saying Sequential disables that warning/error for consumers which only
18+
// use Stat in debug builds.
19+
[StructLayout(LayoutKind.Sequential)]
20+
internal struct FileStatus
21+
{
22+
internal FileStatusFlags Flags;
23+
internal int Mode;
24+
internal uint Uid;
25+
internal uint Gid;
26+
internal long Size;
27+
internal long ATime;
28+
internal long ATimeNsec;
29+
internal long MTime;
30+
internal long MTimeNsec;
31+
internal long CTime;
32+
internal long CTimeNsec;
33+
internal long BirthTime;
34+
internal long BirthTimeNsec;
35+
internal long Dev;
36+
internal long Ino;
37+
internal uint UserFlags;
38+
}
39+
40+
[Flags]
41+
internal enum Permissions
42+
{
43+
Mask = S_IRWXU | S_IRWXG | S_IRWXO,
44+
45+
S_IRWXU = S_IRUSR | S_IWUSR | S_IXUSR,
46+
S_IRUSR = 0x100,
47+
S_IWUSR = 0x80,
48+
S_IXUSR = 0x40,
49+
50+
S_IRWXG = S_IRGRP | S_IWGRP | S_IXGRP,
51+
S_IRGRP = 0x20,
52+
S_IWGRP = 0x10,
53+
S_IXGRP = 0x8,
54+
55+
S_IRWXO = S_IROTH | S_IWOTH | S_IXOTH,
56+
S_IROTH = 0x4,
57+
S_IWOTH = 0x2,
58+
S_IXOTH = 0x1,
59+
60+
S_IXUGO = S_IXUSR | S_IXGRP | S_IXOTH,
61+
}
62+
63+
[Flags]
64+
internal enum FileStatusFlags
65+
{
66+
None = 0,
67+
HasBirthTime = 1,
68+
}
69+
70+
[DllImport("libSystem.Native", EntryPoint = "SystemNative_LStat", SetLastError = true)]
71+
internal static extern int LStat(string path, out FileStatus output);
72+
}
73+
}

src/Cli/dotnet/SudoEnvironmentDirectoryOverride.cs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
using System;
55
using System.CommandLine.Parsing;
66
using System.IO;
7+
using System.Linq;
8+
using Microsoft.DotNet.Cli.Utils;
9+
using Microsoft.DotNet.Tools.Common;
10+
using NuGet.Common;
11+
using NuGet.Configuration;
712

813
namespace Microsoft.DotNet.Cli
914
{
@@ -32,12 +37,100 @@ public static void OverrideEnvironmentVariableToTmp(ParseResult parseResult)
3237
{
3338
if (!OperatingSystem.IsWindows() && IsRunningUnderSudo() && IsRunningWorkloadCommand(parseResult))
3439
{
40+
if (!TempHomeIsOnlyRootWritable(SudoHomeDirectory))
41+
{
42+
try
43+
{
44+
Directory.Delete(SudoHomeDirectory, recursive: true);
45+
}
46+
catch (DirectoryNotFoundException)
47+
{
48+
// Avoid read after write race condition
49+
}
50+
}
51+
3552
Directory.CreateDirectory(SudoHomeDirectory);
53+
54+
var homeBeforeOverride = Path.Combine(Environment.GetEnvironmentVariable("HOME"));
3655
Environment.SetEnvironmentVariable("HOME", SudoHomeDirectory);
56+
57+
CopyUserNuGetConfigToOverriddenHome(homeBeforeOverride);
58+
}
59+
}
60+
61+
/// <summary>
62+
/// To make NuGet honor the user's NuGet config file.
63+
/// Copying instead of using the file directoy to avoid existing file being set higher permission
64+
/// Try to delete the existing NuGet config file in "/tmp/dotnet_sudo_home/"
65+
/// to avoid different user's NuGet config getting mixed.
66+
/// </summary>
67+
private static void CopyUserNuGetConfigToOverriddenHome(string homeBeforeOverride)
68+
{
69+
// https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Common/PathUtil/NuGetEnvironment.cs#L139
70+
// home is cache in NuGet we cannot directly use the call
71+
var userSettingsDir = Path.Combine(homeBeforeOverride, ".nuget", "NuGet");
72+
73+
string userNuGetConfig = Settings.OrderedSettingsFileNames
74+
.Select(fileName => Path.Combine(userSettingsDir, fileName))
75+
.FirstOrDefault(f => File.Exists(f));
76+
77+
var overridenSettingsDir = NuGetEnvironment.GetFolderPath(NuGetFolderPath.UserSettingsDirectory);
78+
var overridenNugetConfig = Path.Combine(overridenSettingsDir, Settings.DefaultSettingsFileName);
79+
80+
if (File.Exists(overridenNugetConfig))
81+
{
82+
try
83+
{
84+
FileAccessRetrier.RetryOnIOException(
85+
() => File.Delete(overridenNugetConfig));
86+
}
87+
catch
88+
{
89+
// best effort to remove
90+
}
91+
}
92+
93+
if (userNuGetConfig != default)
94+
{
95+
try
96+
{
97+
FileAccessRetrier.RetryOnIOException(
98+
() => File.Copy(userNuGetConfig, overridenNugetConfig, overwrite: true));
99+
}
100+
catch
101+
{
102+
// best effort to copy
103+
}
37104
}
38105
}
39106

40107
private static bool IsRunningWorkloadCommand(ParseResult parseResult) =>
41108
parseResult.RootSubCommandResult() == (WorkloadCommandParser.GetCommand().Name);
109+
110+
private static bool TempHomeIsOnlyRootWritable(string path)
111+
{
112+
if (StatInterop.LStat(path, out StatInterop.FileStatus fileStat) != 0)
113+
{
114+
return false;
115+
}
116+
117+
return IsOwnedByRoot(fileStat) && GroupCannotWrite(fileStat) &&
118+
OtherUserCannotWrite(fileStat);
119+
}
120+
121+
private static bool OtherUserCannotWrite(StatInterop.FileStatus fileStat)
122+
{
123+
return (fileStat.Mode & (int) StatInterop.Permissions.S_IWOTH) == 0;
124+
}
125+
126+
private static bool GroupCannotWrite(StatInterop.FileStatus fileStat)
127+
{
128+
return (fileStat.Mode & (int) StatInterop.Permissions.S_IWGRP) == 0;
129+
}
130+
131+
private static bool IsOwnedByRoot(StatInterop.FileStatus fileStat)
132+
{
133+
return fileStat.Uid == 0;
134+
}
42135
}
43136
}

0 commit comments

Comments
 (0)