From de681d31d471ccd4b641056d436a1181a72efd63 Mon Sep 17 00:00:00 2001 From: Dan Travison Date: Wed, 31 Jan 2018 13:10:56 -0800 Subject: [PATCH 1/4] Remove operational and analytic from keywords Update scriptblock logging to always log to the operational channel define DefauiltKeywords and DefaultChannels in PSSysLogProvider.cs --- .../engine/PSConfiguration.cs | 9 ++------- .../engine/runtime/CompiledScriptBlock.cs | 6 +++--- .../utils/tracing/PSSysLogProvider.cs | 7 +++++-- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/System.Management.Automation/engine/PSConfiguration.cs b/src/System.Management.Automation/engine/PSConfiguration.cs index 8c60d6735d8..e51da3d5c61 100644 --- a/src/System.Management.Automation/engine/PSConfiguration.cs +++ b/src/System.Management.Automation/engine/PSConfiguration.cs @@ -247,8 +247,6 @@ internal PSLevel GetLogLevel() /// const string LogDefaultValue = "default"; - const PSChannel DefaultChannels = PSChannel.Operational; - /// /// Gets the bitmask of the PSChannel values to log. /// @@ -282,15 +280,12 @@ internal PSChannel GetLogChannels() if (result == 0) { - result = DefaultChannels; + result = PSSysLogProvider.DefaultChannels; } return result; } - // by default, do not include analytic events. - const PSKeyword DefaultKeywords = (PSKeyword) (0xFFFFFFFFFFFFFFFF & ~(ulong)PSKeyword.UseAlwaysAnalytic); - /// /// Gets the bitmask of keywords to log. /// @@ -324,7 +319,7 @@ internal PSKeyword GetLogKeywords() if (result == 0) { - result = DefaultKeywords; + result = PSSysLogProvider.DefaultKeywords; } return result; diff --git a/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs b/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs index 6362edd0bcf..abf5c017b11 100644 --- a/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs +++ b/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs @@ -1321,7 +1321,7 @@ private static bool WriteScriptBlockToLog(ScriptBlock scriptBlock, int segment, // they can just wait on the compromised box and see the sensitive data eventually anyways. string errorMessage = StringUtil.Format(SecuritySupportStrings.CouldNotEncryptContent, textToLog, error.ToString()); - PSEtwLog.LogOperationalError(PSEventId.ScriptBlock_Compile_Detail, PSOpcode.Create, PSTask.ExecuteCommand, PSKeyword.UseAlwaysAnalytic, + PSEtwLog.LogOperationalError(PSEventId.ScriptBlock_Compile_Detail, PSOpcode.Create, PSTask.ExecuteCommand, PSKeyword.UseAlwaysOperational, 0, 0, errorMessage, scriptBlock.Id.ToString(), scriptBlock.File ?? String.Empty); } else @@ -1334,12 +1334,12 @@ private static bool WriteScriptBlockToLog(ScriptBlock scriptBlock, int segment, if (scriptBlock._scriptBlockData.HasSuspiciousContent) { - PSEtwLog.LogOperationalWarning(PSEventId.ScriptBlock_Compile_Detail, PSOpcode.Create, PSTask.ExecuteCommand, PSKeyword.UseAlwaysAnalytic, + PSEtwLog.LogOperationalWarning(PSEventId.ScriptBlock_Compile_Detail, PSOpcode.Create, PSTask.ExecuteCommand, PSKeyword.UseAlwaysOperational, segment + 1, segments, textToLog, scriptBlock.Id.ToString(), scriptBlock.File ?? String.Empty); } else { - PSEtwLog.LogOperationalVerbose(PSEventId.ScriptBlock_Compile_Detail, PSOpcode.Create, PSTask.ExecuteCommand, PSKeyword.UseAlwaysAnalytic, + PSEtwLog.LogOperationalVerbose(PSEventId.ScriptBlock_Compile_Detail, PSOpcode.Create, PSTask.ExecuteCommand, PSKeyword.UseAlwaysOperational, segment + 1, segments, textToLog, scriptBlock.Id.ToString(), scriptBlock.File ?? String.Empty); } diff --git a/src/System.Management.Automation/utils/tracing/PSSysLogProvider.cs b/src/System.Management.Automation/utils/tracing/PSSysLogProvider.cs index 49d5c8c2f29..7507c1c4402 100755 --- a/src/System.Management.Automation/utils/tracing/PSSysLogProvider.cs +++ b/src/System.Management.Automation/utils/tracing/PSSysLogProvider.cs @@ -17,8 +17,11 @@ internal class PSSysLogProvider : LogProvider { private static SysLogProvider s_provider; - // by default, do not include analytic events - internal const PSKeyword DefaultKeywords = (PSKeyword) (0xFFFFFFFFFFFFFFFF & ~(ulong)PSKeyword.UseAlwaysAnalytic); + // by default, do not include channel bits + internal const PSKeyword DefaultKeywords = (PSKeyword) (0x00FFFFFFFFFFFFFF); + + // the default enabled channel(s) + internal const PSChannel DefaultChannels = PSChannel.Operational; /// /// Class constructor. From dd7c46f4f34797c45d4c7259ce4ac06d75bb0d69 Mon Sep 17 00:00:00 2001 From: dantra Date: Wed, 31 Jan 2018 17:28:44 -0800 Subject: [PATCH 2/4] Fix PSChannel on Linux to use a bitmask handle UseAlwaysOperational and UseAlwaysAnalytic keywords but adding to _keywordFilter if the associated channels were selected in configuration Remove previous UseAlwaysAnalytic workaround in SysLogProvider.Log --- .../engine/PSConfiguration.cs | 4 ++-- .../engine/remoting/common/PSETWTracer.cs | 8 ++++++++ .../utils/tracing/SysLogProvider.cs | 17 +++++++++-------- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/System.Management.Automation/engine/PSConfiguration.cs b/src/System.Management.Automation/engine/PSConfiguration.cs index e51da3d5c61..8861e676c44 100644 --- a/src/System.Management.Automation/engine/PSConfiguration.cs +++ b/src/System.Management.Automation/engine/PSConfiguration.cs @@ -280,7 +280,7 @@ internal PSChannel GetLogChannels() if (result == 0) { - result = PSSysLogProvider.DefaultChannels; + result = System.Management.Automation.Tracing.PSSysLogProvider.DefaultChannels; } return result; @@ -319,7 +319,7 @@ internal PSKeyword GetLogKeywords() if (result == 0) { - result = PSSysLogProvider.DefaultKeywords; + result = System.Management.Automation.Tracing.PSSysLogProvider.DefaultKeywords; } return result; diff --git a/src/System.Management.Automation/engine/remoting/common/PSETWTracer.cs b/src/System.Management.Automation/engine/remoting/common/PSETWTracer.cs index 5008ab57dde..c037a51bc00 100644 --- a/src/System.Management.Automation/engine/remoting/common/PSETWTracer.cs +++ b/src/System.Management.Automation/engine/remoting/common/PSETWTracer.cs @@ -198,8 +198,16 @@ internal enum PSEventId : int [Flags] internal enum PSChannel : byte { + #if UNIX + // On Windows, PSChannel is the numeric channel id value. + // On Linux, PSChannel it is used to filter events and + // the underlying channel bitmask values are used instead. + Operational = 0x80, + Analytic = 0x40 + #else Operational = 0x10, Analytic = 0x11 + #endif } /// diff --git a/src/System.Management.Automation/utils/tracing/SysLogProvider.cs b/src/System.Management.Automation/utils/tracing/SysLogProvider.cs index 614bdbdc9ec..8f01321c104 100755 --- a/src/System.Management.Automation/utils/tracing/SysLogProvider.cs +++ b/src/System.Management.Automation/utils/tracing/SysLogProvider.cs @@ -102,6 +102,14 @@ public SysLogProvider(string applicationId, PSLevel level, PSKeyword keywords, P _keywordFilter = (ulong)keywords; _levelFilter = (byte) level; _channelFilter = (byte) channels; + if ((_channelFilter & (ulong) PSChannel.Operational) != 0) + { + _keywordFilter |= (ulong) PSKeyword.UseAlwaysOperational; + } + if ((_channelFilter & (ulong) PSChannel.Analytic) != 0) + { + _keywordFilter |= (ulong) PSKeyword.UseAlwaysAnalytic; + } } /// @@ -161,7 +169,7 @@ private static Guid Activity /// The PSKeyword to check. /// true if the specified level and keywords are enabled for logging. internal bool IsEnabled(PSLevel level, PSKeyword keywords) - { + { return ( ((ulong) keywords & _keywordFilter) != 0 && ((int) level <= _levelFilter) ); } @@ -313,13 +321,6 @@ public void SetActivity(Guid activity) /// The payload for the log message. public void Log(PSEventId eventId, PSChannel channel, PSTask task, PSOpcode opcode, PSLevel level, PSKeyword keyword, params object[] args) { - if (keyword == PSKeyword.UseAlwaysAnalytic) - { - // Use the 'DefaultKeywords' to work around the default keyword filter. - // Note that the PSKeyword argument is not really used in writing SysLog. - keyword = PSSysLogProvider.DefaultKeywords; - } - if (ShouldLog(level, keyword, channel)) { int threadId = Thread.CurrentThread.ManagedThreadId; From 7f6c89b1681932d72bd884af2cf03b7b15c9a59c Mon Sep 17 00:00:00 2001 From: dantra Date: Thu, 1 Feb 2018 10:23:38 -0800 Subject: [PATCH 3/4] Update PSChannel comment --- .../engine/remoting/common/PSETWTracer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/engine/remoting/common/PSETWTracer.cs b/src/System.Management.Automation/engine/remoting/common/PSETWTracer.cs index c037a51bc00..5c3b60dd06f 100644 --- a/src/System.Management.Automation/engine/remoting/common/PSETWTracer.cs +++ b/src/System.Management.Automation/engine/remoting/common/PSETWTracer.cs @@ -200,7 +200,7 @@ internal enum PSChannel : byte { #if UNIX // On Windows, PSChannel is the numeric channel id value. - // On Linux, PSChannel it is used to filter events and + // On Non-Windows, PSChannel it is used to filter events and // the underlying channel bitmask values are used instead. Operational = 0x80, Analytic = 0x40 From 15bb6769551e0ea947d370dad2c7d0752fb208d1 Mon Sep 17 00:00:00 2001 From: dantra Date: Thu, 1 Feb 2018 13:53:34 -0800 Subject: [PATCH 4/4] Address PR feedback. --- .../engine/remoting/common/PSETWTracer.cs | 18 ++++++++++++------ .../engine/runtime/CompiledScriptBlock.cs | 8 ++++---- .../utils/tracing/SysLogProvider.cs | 2 +- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/System.Management.Automation/engine/remoting/common/PSETWTracer.cs b/src/System.Management.Automation/engine/remoting/common/PSETWTracer.cs index 5c3b60dd06f..0088f2f136f 100644 --- a/src/System.Management.Automation/engine/remoting/common/PSETWTracer.cs +++ b/src/System.Management.Automation/engine/remoting/common/PSETWTracer.cs @@ -195,20 +195,26 @@ internal enum PSEventId : int /// /// Defines enumerations for channels /// + /// + /// On Windows, PSChannel is the numeric channel id value. + /// On Non-Windows, PSChannel is used to filter events and + /// the underlying channel bitmask values are used instead. + /// The bit values are the same as used on Windows. + /// +#if UNIX [Flags] internal enum PSChannel : byte { - #if UNIX - // On Windows, PSChannel is the numeric channel id value. - // On Non-Windows, PSChannel it is used to filter events and - // the underlying channel bitmask values are used instead. Operational = 0x80, Analytic = 0x40 - #else + } +#else + internal enum PSChannel : byte + { Operational = 0x10, Analytic = 0x11 - #endif } +#endif /// /// Defines enumerations for tasks diff --git a/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs b/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs index abf5c017b11..6b69f89d997 100644 --- a/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs +++ b/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs @@ -1405,7 +1405,7 @@ private static bool GetAndValidateEncryptionRecipients(ScriptBlock scriptBlock, // attacker seeing potentially sensitive data. Because if they aren't detected, then // they can just wait on the compromised box and see the sensitive data eventually anyways. string errorMessage = StringUtil.Format(SecuritySupportStrings.CouldNotUseCertificate, error.ToString()); - PSEtwLog.LogOperationalError(PSEventId.ScriptBlock_Compile_Detail, PSOpcode.Create, PSTask.ExecuteCommand, PSKeyword.UseAlwaysAnalytic, + PSEtwLog.LogOperationalError(PSEventId.ScriptBlock_Compile_Detail, PSOpcode.Create, PSTask.ExecuteCommand, PSKeyword.UseAlwaysOperational, 0, 0, errorMessage, scriptBlock.Id.ToString(), scriptBlock.File ?? String.Empty); return true; @@ -1430,7 +1430,7 @@ private static bool GetAndValidateEncryptionRecipients(ScriptBlock scriptBlock, } string errorMessage = StringUtil.Format(SecuritySupportStrings.CertificateContainsPrivateKey, certificateForLog); - PSEtwLog.LogOperationalError(PSEventId.ScriptBlock_Compile_Detail, PSOpcode.Create, PSTask.ExecuteCommand, PSKeyword.UseAlwaysAnalytic, + PSEtwLog.LogOperationalError(PSEventId.ScriptBlock_Compile_Detail, PSOpcode.Create, PSTask.ExecuteCommand, PSKeyword.UseAlwaysOperational, 0, 0, errorMessage, scriptBlock.Id.ToString(), scriptBlock.File ?? String.Empty); } } @@ -1794,7 +1794,7 @@ internal static void LogScriptBlockStart(ScriptBlock scriptBlock, Guid runspaceI if (GetScriptBlockLoggingSetting()?.EnableScriptBlockInvocationLogging == true) { - PSEtwLog.LogOperationalVerbose(PSEventId.ScriptBlock_Invoke_Start_Detail, PSOpcode.Create, PSTask.CommandStart, PSKeyword.UseAlwaysAnalytic, + PSEtwLog.LogOperationalVerbose(PSEventId.ScriptBlock_Invoke_Start_Detail, PSOpcode.Create, PSTask.CommandStart, PSKeyword.UseAlwaysOperational, scriptBlock.Id.ToString(), runspaceId.ToString()); } } @@ -1803,7 +1803,7 @@ internal static void LogScriptBlockEnd(ScriptBlock scriptBlock, Guid runspaceId) { if (GetScriptBlockLoggingSetting()?.EnableScriptBlockInvocationLogging == true) { - PSEtwLog.LogOperationalVerbose(PSEventId.ScriptBlock_Invoke_Complete_Detail, PSOpcode.Create, PSTask.CommandStop, PSKeyword.UseAlwaysAnalytic, + PSEtwLog.LogOperationalVerbose(PSEventId.ScriptBlock_Invoke_Complete_Detail, PSOpcode.Create, PSTask.CommandStop, PSKeyword.UseAlwaysOperational, scriptBlock.Id.ToString(), runspaceId.ToString()); } } diff --git a/src/System.Management.Automation/utils/tracing/SysLogProvider.cs b/src/System.Management.Automation/utils/tracing/SysLogProvider.cs index 8f01321c104..cd6d9d73927 100755 --- a/src/System.Management.Automation/utils/tracing/SysLogProvider.cs +++ b/src/System.Management.Automation/utils/tracing/SysLogProvider.cs @@ -169,7 +169,7 @@ private static Guid Activity /// The PSKeyword to check. /// true if the specified level and keywords are enabled for logging. internal bool IsEnabled(PSLevel level, PSKeyword keywords) - { + { return ( ((ulong) keywords & _keywordFilter) != 0 && ((int) level <= _levelFilter) ); }