Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 0 additions & 27 deletions src/System.Management.Automation/CoreCLR/CorePsPlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,32 +121,6 @@ public static bool IsIoT
}
}

/// <summary>
/// True if it is the inbox powershell for NanoServer or IoT.
/// </summary>
internal static bool IsInbox
{
get
{
#if UNIX
return false;
#else
if (_isInbox.HasValue) { return _isInbox.Value; }

_isInbox = false;
if (IsNanoServer || IsIoT)
{
_isInbox = string.Equals(
Utils.DefaultPowerShellAppBase,
Utils.GetApplicationBaseFromRegistry(Utils.DefaultPowerShellShellID),
StringComparison.OrdinalIgnoreCase);
}

return _isInbox.Value;
#endif
}
}

/// <summary>
/// True if underlying system is Windows Desktop.
/// </summary>
Expand All @@ -168,7 +142,6 @@ public static bool IsWindowsDesktop
#if !UNIX
private static bool? _isNanoServer = null;
private static bool? _isIoT = null;
private static bool? _isInbox = null;
private static bool? _isWindowsDesktop = null;
#endif

Expand Down
117 changes: 77 additions & 40 deletions src/System.Management.Automation/engine/InitialSessionState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2360,67 +2360,106 @@ private void Bind_LoadAssemblies(ExecutionContext context)

internal Exception BindRunspace(Runspace initializedRunspace, PSTraceSource runspaceInitTracer)
{
// Get initial list of public commands in session.
HashSet<CommandInfo> publicCommands = new HashSet<CommandInfo>();
foreach (CommandInfo sessionCommand in initializedRunspace.ExecutionContext.SessionState.InvokeCommand.GetCommands(
"*", CommandTypes.Alias | CommandTypes.Function | CommandTypes.Filter | CommandTypes.Cmdlet, true))
// Get the initial list of public commands from session in a lazy way, so that we can defer
// the work until it's actually needed.
//
// We could use Lazy<> with an initializer for the same purpose, but we can save allocations
// by using the local function. It avoids allocating the delegate, and it's more efficient on
// capturing variables from the enclosing scope by using a struct.
HashSet<CommandInfo> publicCommands = null;
HashSet<CommandInfo> GetPublicCommands()
{
if (sessionCommand.Visibility == SessionStateEntryVisibility.Public)
if (publicCommands != null)
{
publicCommands.Add(sessionCommand);
return publicCommands;
}

publicCommands = new HashSet<CommandInfo>();
foreach (CommandInfo sessionCommand in initializedRunspace.ExecutionContext.SessionState.InvokeCommand.GetCommands(
"*", CommandTypes.Alias | CommandTypes.Function | CommandTypes.Filter | CommandTypes.Cmdlet, nameIsPattern: true))
{
if (sessionCommand.Visibility == SessionStateEntryVisibility.Public)
{
publicCommands.Add(sessionCommand);
}
}
return publicCommands;
}

// If a user has any module with the same name as that of the core module( or nested module inside the core module)
// in his module path, then that will get loaded instead of the actual nested module (from the GAC - in our case)
// Hence, searching only from the system module path while loading the core modules
var unresolvedCmdsToExpose = new HashSet<string>(this.UnresolvedCommandsToExpose, StringComparer.OrdinalIgnoreCase);
ProcessImportModule(initializedRunspace, CoreModulesToImport, ModuleIntrinsics.GetPSHomeModulePath(), publicCommands, unresolvedCmdsToExpose);
if (CoreModulesToImport.Count > 0 || unresolvedCmdsToExpose.Count > 0)
{
// If a user has any module with the same name as that of the core module( or nested module inside the core module)
// in his module path, then that will get loaded instead of the actual nested module (from the GAC - in our case)
// Hence, searching only from the system module path while loading the core modules
ProcessModulesToImport(initializedRunspace, CoreModulesToImport, ModuleIntrinsics.GetPSHomeModulePath(), GetPublicCommands(), unresolvedCmdsToExpose);
}

// Win8:328748 - functions defined in global scope end up in a module
// Since we import the core modules, EngineSessionState's module is set to the last imported module. So, if a function is defined in global scope, it ends up in that module.
// Setting the module to null fixes that.
initializedRunspace.ExecutionContext.EngineSessionState.Module = null;

Exception moduleImportException = ProcessImportModule(initializedRunspace, ModuleSpecificationsToImport, string.Empty, publicCommands, unresolvedCmdsToExpose);
if (moduleImportException != null)
if (ModuleSpecificationsToImport.Count > 0 || unresolvedCmdsToExpose.Count > 0)
{
runspaceInitTracer.WriteLine(
"Runspace open failed while loading module: First error {1}", moduleImportException);
return moduleImportException;
Exception moduleImportException = ProcessModulesToImport(initializedRunspace, ModuleSpecificationsToImport, string.Empty, GetPublicCommands(), unresolvedCmdsToExpose);
if (moduleImportException != null)
{
runspaceInitTracer.WriteLine(
"Runspace open failed while loading module: First error {1}", moduleImportException);
return moduleImportException;
}
}

// If we still have unresolved commands after importing specified modules, then try finding associated module for
// each unresolved command and import that module.
string[] foundModuleList = GetModulesForUnResolvedCommands(unresolvedCmdsToExpose, initializedRunspace.ExecutionContext);
if (foundModuleList.Length > 0)
if (unresolvedCmdsToExpose.Count > 0)
{
ProcessImportModule(initializedRunspace, foundModuleList, string.Empty, publicCommands, unresolvedCmdsToExpose);
string[] foundModuleList = GetModulesForUnResolvedCommands(unresolvedCmdsToExpose, initializedRunspace.ExecutionContext);
if (foundModuleList.Length > 0)
{
ProcessModulesToImport(initializedRunspace, foundModuleList, string.Empty, GetPublicCommands(), unresolvedCmdsToExpose);
}
}

ProcessDynamicVariables(initializedRunspace);
ProcessCommandModifications(initializedRunspace);
// Process dynamic variables if any are defined.
if (DynamicVariablesToDefine.Count > 0)
{
ProcessDynamicVariables(initializedRunspace);
}

// Process User: drive
Exception userDriveException = ProcessUserDrive(initializedRunspace);
if (userDriveException != null)
// Process command modifications if any are defined.
if (CommandModifications.Count > 0)
{
runspaceInitTracer.WriteLine(
"Runspace open failed while processing user drive with error {1}", userDriveException);
ProcessCommandModifications(initializedRunspace);
}

Exception result = PSTraceSource.NewInvalidOperationException(userDriveException, RemotingErrorIdStrings.UserDriveProcessingThrewTerminatingError, userDriveException.Message);
return result;
// Process the 'User:' drive if 'UserDriveEnabled' is set.
if (UserDriveEnabled)
{
Exception userDriveException = ProcessUserDrive(initializedRunspace);
if (userDriveException != null)
{
runspaceInitTracer.WriteLine(
"Runspace open failed while processing user drive with error {1}", userDriveException);

Exception result = PSTraceSource.NewInvalidOperationException(userDriveException, RemotingErrorIdStrings.UserDriveProcessingThrewTerminatingError, userDriveException.Message);
return result;
}
}

// Process startup scripts
Exception startupScriptException = ProcessStartupScripts(initializedRunspace);
if (startupScriptException != null)
if (StartupScripts.Count > 0)
{
runspaceInitTracer.WriteLine(
"Runspace open failed while running startup script: First error {1}", startupScriptException);
Exception startupScriptException = ProcessStartupScripts(initializedRunspace);
if (startupScriptException != null)
{
runspaceInitTracer.WriteLine(
"Runspace open failed while running startup script: First error {1}", startupScriptException);

Exception result = PSTraceSource.NewInvalidOperationException(startupScriptException, RemotingErrorIdStrings.StartupScriptThrewTerminatingError, startupScriptException.Message);
return result;
Exception result = PSTraceSource.NewInvalidOperationException(startupScriptException, RemotingErrorIdStrings.StartupScriptThrewTerminatingError, startupScriptException.Message);
return result;
}
}

// Start transcribing
Expand Down Expand Up @@ -2639,8 +2678,6 @@ private Exception ProcessDynamicVariables(Runspace initializedRunspace)

private Exception ProcessUserDrive(Runspace initializedRunspace)
{
if (!UserDriveEnabled) { return null; }

Exception ex = null;
try
{
Expand Down Expand Up @@ -2805,7 +2842,7 @@ private Exception ProcessPowerShellCommand(PowerShell psToInvoke, Runspace initi
return null;
}

private RunspaceOpenModuleLoadException ProcessImportModule(
private RunspaceOpenModuleLoadException ProcessModulesToImport(
Runspace initializedRunspace,
IEnumerable moduleList,
string path,
Expand All @@ -2819,7 +2856,7 @@ private RunspaceOpenModuleLoadException ProcessImportModule(
string moduleName = module as string;
if (moduleName != null)
{
exceptionToReturn = ProcessImportModule(initializedRunspace, moduleName, null, path, publicCommands);
exceptionToReturn = ProcessOneModule(initializedRunspace, moduleName, null, path, publicCommands);
}
else
{
Expand All @@ -2830,15 +2867,15 @@ private RunspaceOpenModuleLoadException ProcessImportModule(
{
// if only name is specified in the module spec, just try import the module
// ie., don't take the performance overhead of calling GetModule.
exceptionToReturn = ProcessImportModule(initializedRunspace, moduleSpecification.Name, null, path, publicCommands);
exceptionToReturn = ProcessOneModule(initializedRunspace, moduleSpecification.Name, null, path, publicCommands);
}
else
{
Collection<PSModuleInfo> moduleInfos = ModuleCmdletBase.GetModuleIfAvailable(moduleSpecification, initializedRunspace);

if (moduleInfos != null && moduleInfos.Count > 0)
{
exceptionToReturn = ProcessImportModule(initializedRunspace, moduleSpecification.Name, moduleInfos[0], path, publicCommands);
exceptionToReturn = ProcessOneModule(initializedRunspace, moduleSpecification.Name, moduleInfos[0], path, publicCommands);
}
else
{
Expand Down Expand Up @@ -2979,7 +3016,7 @@ private IEnumerable<CommandInfo> LookupCommands(
/// if <paramref name="moduleInfoToLoad"/> is null, import module using <paramref name="name"/>. Otherwise,
/// import module using <paramref name="moduleInfoToLoad"/>
/// </summary>
private RunspaceOpenModuleLoadException ProcessImportModule(Runspace initializedRunspace, string name, PSModuleInfo moduleInfoToLoad, string path, HashSet<CommandInfo> publicCommands)
private RunspaceOpenModuleLoadException ProcessOneModule(Runspace initializedRunspace, string name, PSModuleInfo moduleInfoToLoad, string path, HashSet<CommandInfo> publicCommands)
{
using (PowerShell pse = PowerShell.Create())
{
Expand Down
2 changes: 1 addition & 1 deletion src/System.Management.Automation/engine/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ internal static bool IsValidPSEditionValue(string editionValue)
/// <summary>
/// This is used to construct the profile path.
/// </summary>
internal static string ProductNameForDirectory = Platform.IsInbox ? "WindowsPowerShell" : "PowerShell";
internal const string ProductNameForDirectory = "PowerShell";

/// <summary>
/// The subdirectory of module paths
Expand Down
24 changes: 16 additions & 8 deletions src/System.Management.Automation/engine/parser/SafeValues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,35 @@ internal class IsSafeValueVisitor : ICustomAstVisitor
public static bool IsAstSafe(Ast ast, GetSafeValueVisitor.SafeValueContext safeValueContext)
{
IsSafeValueVisitor visitor = new IsSafeValueVisitor(safeValueContext);
if ((bool)ast.Accept(visitor) && visitor._visitCount < MaxVisitCount)
{
return true;
}
return false;
return visitor.IsAstSafe(ast);
}

internal IsSafeValueVisitor(GetSafeValueVisitor.SafeValueContext safeValueContext)
{
_safeValueContext = safeValueContext;
}

internal bool IsAstSafe(Ast ast)
{
if ((bool)ast.Accept(this) && _visitCount < MaxVisitCount)
{
return true;
}
return false;
}

// A readonly singleton with the default SafeValueContext.
internal readonly static IsSafeValueVisitor Default = new IsSafeValueVisitor(GetSafeValueVisitor.SafeValueContext.Default);

// This is a check of the number of visits
private int _visitCount = 0;
private const int MaxVisitCount = 5000;
private uint _visitCount = 0;
private const uint MaxVisitCount = 5000;
private const int MaxHashtableKeyCount = 500;

// Used to determine if we are being called within a GetPowerShell() context,
// which does some additional security verification outside of the scope of
// what we can verify.
private GetSafeValueVisitor.SafeValueContext _safeValueContext;
private readonly GetSafeValueVisitor.SafeValueContext _safeValueContext;

public object VisitErrorStatement(ErrorStatementAst errorStatementAst) { return false; }
public object VisitErrorExpression(ErrorExpressionAst errorExpressionAst) { return false; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ bool IsScriptBlockInFactASafeHashtable()

// After the above steps, we know the ScriptBlockAst is in fact just a HashtableAst,
// now we need to check if the HashtableAst is safe.
return IsSafeValueVisitor.IsAstSafe(hashtableAst, GetSafeValueVisitor.SafeValueContext.Default);
return IsSafeValueVisitor.Default.IsAstSafe(hashtableAst);
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/System.Management.Automation/security/wldpNativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ private SystemPolicy()
/// <returns>An EnforcementMode that describes the system policy</returns>
public static SystemEnforcementMode GetSystemLockdownPolicy()
{
if (s_wasSystemPolicyDebugPolicy || (s_systemLockdownPolicy == null))
if (s_allowDebugOverridePolicy || (s_systemLockdownPolicy == null))
{
lock (s_systemLockdownPolicyLock)
{
if (s_wasSystemPolicyDebugPolicy || (s_systemLockdownPolicy == null))
if (s_allowDebugOverridePolicy || (s_systemLockdownPolicy == null))
{
s_systemLockdownPolicy = GetLockdownPolicy(null, null);
}
Expand All @@ -64,7 +64,7 @@ public static SystemEnforcementMode GetSystemLockdownPolicy()

private static object s_systemLockdownPolicyLock = new Object();
private static Nullable<SystemEnforcementMode> s_systemLockdownPolicy = null;
private static bool s_wasSystemPolicyDebugPolicy = false;
private static bool s_allowDebugOverridePolicy = false;

/// <summary>
/// Gets lockdown policy as applied to a file
Expand Down Expand Up @@ -340,7 +340,7 @@ private static SaferPolicy TestSaferPolicy(string testPathScript, string testPat

private static SystemEnforcementMode GetDebugLockdownPolicy(string path)
{
s_wasSystemPolicyDebugPolicy = true;
s_allowDebugOverridePolicy = true;

// Support fall-back debug hook for path exclusions on non-WOA platforms
if (path != null)
Expand Down Expand Up @@ -419,7 +419,7 @@ internal static bool IsClassInApprovedList(Guid clsid)
// Hook for testability. If we've got an environmental override, say that ADODB.Parameter
// is not allowed.
// 0000050b-0000-0010-8000-00aa006d2ea4 = ADODB.Parameter
if (s_wasSystemPolicyDebugPolicy)
if (s_allowDebugOverridePolicy)
{
if (String.Equals(clsid.ToString(), "0000050b-0000-0010-8000-00aa006d2ea4", StringComparison.OrdinalIgnoreCase))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,12 @@ try
# script debugger command processor.
$script = @'
Import-Module -Name HelpersSecurity
Import-Module -Name {0} -Force
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
Import-Module -Name {1} -Force
Import-Module -Name {0} -Force
Set-PSBreakpoint -Command PublicFn
PublicFn
'@ -f "$languageModuleDirectory\TestCmdletForConstrainedLanguage.dll", $trustedManifestFilePath
'@ -f $trustedManifestFilePath

[powershell] $ps = [powershell]::Create()
$ps.Runspace = $runspace
Expand Down
Loading