Skip to content

Commit 2c2b876

Browse files
authored
[ASM] upgrade WAF to 1.7.0 and WAF rules to 1.5.0 (#3742)
1 parent a506a35 commit 2c2b876

File tree

50 files changed

+136
-295
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+136
-295
lines changed

tracer/build/_build/Build.Steps.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ partial class Build
5858

5959
AbsolutePath NativeBuildDirectory => RootDirectory / "obj";
6060

61-
const string LibDdwafVersion = "1.5.1";
61+
const string LibDdwafVersion = "1.7.0";
6262

6363
const string OlderLibDdwafVersion = "1.4.0";
6464

@@ -474,7 +474,8 @@ async Task DownloadWafVersion(string libddwafVersion = null, string uncompressFo
474474
var (arch, _) = GetUnixArchitectureAndExtension();
475475
var (archWaf, ext) = GetLibDdWafUnixArchitectureAndExtension();
476476
var source = MonitoringHomeDirectory / (IsOsx ? "osx" : arch);
477-
var oldVersionPath = oldVersionTempPath / "runtimes" / archWaf / "native" / $"libddwaf.{ext}";
477+
var patchedArchWaf = (IsOsx ? archWaf + "-x64" : archWaf);
478+
var oldVersionPath = oldVersionTempPath / "runtimes" / patchedArchWaf / "native" / $"libddwaf.{ext}";
478479
foreach (var fmk in frameworks)
479480
{
480481
// We have to copy into the _root_ test bin folder here, not the arch sub-folder.
@@ -2019,9 +2020,8 @@ private void MakeGrpcToolsExecutable()
20192020
private (string Arch, string Ext) GetLibDdWafUnixArchitectureAndExtension() =>
20202021
(IsOsx) switch
20212022
{
2022-
// (true) => ($"osx-{UnixArchitectureIdentifier}", "dylib"), //LibDdWaf doesn't support osx-arm64 yet.
2023-
(true) => ($"osx-x64", "dylib"),
2024-
(false) => ($"linux-{UnixArchitectureIdentifier}", "so"), // LibDdWaf doesn't
2023+
(true) => ($"osx", "dylib"), // LibDdWaf is universal binary on osx
2024+
(false) => ($"linux-{UnixArchitectureIdentifier}", "so"),
20252025
};
20262026

20272027
private (string Arch, string Ext) GetUnixArchitectureAndExtension() =>

tracer/build/smoke_test_snapshots/smoke_test_snapshots.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"parent_id": 1,
3838
"type": "web",
3939
"meta": {
40-
"_dd.appsec.waf.version": "1.5.1",
40+
"_dd.appsec.waf.version": "1.7.0",
4141
"_dd.runtime_family": "dotnet",
4242
"aspnet_core.endpoint": "AspNetCoreSmokeTest.ValuesController.Get (AspNetCoreSmokeTest)",
4343
"aspnet_core.route": "api/values",

tracer/build/smoke_test_snapshots/smoke_test_snapshots_2_1.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"parent_id": 1,
3838
"type": "web",
3939
"meta": {
40-
"_dd.appsec.waf.version": "1.5.1",
40+
"_dd.appsec.waf.version": "1.7.0",
4141
"_dd.runtime_family": "dotnet",
4242
"aspnet_core.route": "api/values",
4343
"component": "aspnet_core",

tracer/src/Datadog.Trace/AppSec/Concurrency/ReaderWriterLock.Core.cs

Lines changed: 0 additions & 66 deletions
This file was deleted.

tracer/src/Datadog.Trace/AppSec/Concurrency/ReaderWriterLock.Framework.cs

Lines changed: 0 additions & 78 deletions
This file was deleted.

tracer/src/Datadog.Trace/AppSec/Security.cs

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ internal class Security : IDatadogSecurity, IDisposable
3030
private static Security _instance;
3131
private static bool _globalInstanceInitialized;
3232
private static object _globalInstanceLock = new();
33-
private readonly Concurrency.ReaderWriterLock _wafLocker = new();
3433
private readonly SecuritySettings _settings;
3534
private LibraryInitializationResult _libraryInitializationResult;
3635
private IWaf _waf;
@@ -328,28 +327,17 @@ private void UpdateStatus(bool fromRemoteConfig = false)
328327
_wafInitializationResult = Waf.Waf.Create(_wafLibraryInvoker, _settings.ObfuscationParameterKeyRegex, _settings.ObfuscationParameterValueRegex, _settings.Rules, _remoteRulesJson);
329328
if (_wafInitializationResult.Success)
330329
{
331-
if (_wafLocker.EnterWriteLock())
332-
{
333-
var oldWaf = _waf;
334-
_waf = _wafInitializationResult.Waf;
335-
oldWaf?.Dispose();
336-
_wafLocker.ExitWriteLock();
337-
Log.Debug("Disposed old waf and affected new waf");
338-
UpdateRulesData();
339-
AddInstrumentationsAndProducts(fromRemoteConfig);
340-
}
341-
else
342-
{
343-
_wafInitializationResult.Waf?.Dispose();
344-
Log.Warning("Could not replace waf because the writer lock couldn't be acquired within the specified timeout {timeout}", Concurrency.ReaderWriterLock.TimeoutInMs.ToString());
345-
}
330+
var oldWaf = _waf;
331+
_waf = _wafInitializationResult.Waf;
332+
oldWaf?.Dispose();
333+
Log.Debug("Disposed old waf and affected new waf");
334+
UpdateRulesData();
335+
AddInstrumentationsAndProducts(fromRemoteConfig);
346336
}
347337
else
348338
{
349-
_wafLocker.EnterWriteLock();
350339
_waf?.Dispose();
351340
_wafInitializationResult.Waf?.Dispose();
352-
_wafLocker.ExitWriteLock();
353341
_settings.Enabled = false;
354342
}
355343
}
@@ -404,15 +392,14 @@ internal void SetTraceSamplingPriority(Span span)
404392
}
405393
}
406394

407-
internal IContext CreateAdditiveContext() => _waf?.CreateContext(_wafLocker);
395+
internal IContext CreateAdditiveContext() => _waf?.CreateContext();
408396

409397
private void RunShutdown()
410398
{
411399
AsmRemoteConfigurationProducts.AsmDataProduct.ConfigChanged -= AsmDataProductConfigChanged;
412400
AsmRemoteConfigurationProducts.AsmProduct.ConfigChanged -= AsmProductConfigChanged;
413401
AsmRemoteConfigurationProducts.AsmFeaturesProduct.ConfigChanged -= FeaturesProductConfigChanged;
414402
AsmRemoteConfigurationProducts.AsmDDProduct.ConfigChanged -= AsmDDProductConfigChanged;
415-
_wafLocker.Dispose();
416403
Dispose();
417404
}
418405
}

tracer/src/Datadog.Trace/AppSec/Waf/Context.cs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using System;
88
using System.Collections.Generic;
99
using System.Diagnostics;
10-
using Datadog.Trace.AppSec.Concurrency;
1110
using Datadog.Trace.AppSec.Waf.NativeBindings;
1211
using Datadog.Trace.Logging;
1312
using Datadog.Trace.Util;
@@ -18,12 +17,14 @@ namespace Datadog.Trace.AppSec.Waf
1817
internal class Context : IContext
1918
{
2019
private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor<Context>();
20+
21+
// the context handle should be locked, it is not safe for concurrent access and two
22+
// waf events may be processed at the same time due to code being run asynchronously
23+
private readonly object _sync = new object();
2124
private readonly IntPtr _contextHandle;
2225

2326
private readonly Waf _waf;
2427

25-
// this lock is to avoid accessing the waf object from the Context while it's being disposed. Other events involving the waf arent concurrent (rcm is not) and thread safe (other methods on native waf)
26-
private readonly ReaderWriterLock _wafLocker;
2728
private readonly List<Obj> _argCache = new();
2829
private readonly Stopwatch _stopwatch;
2930
private readonly WafLibraryInvoker _wafLibraryInvoker;
@@ -32,9 +33,8 @@ internal class Context : IContext
3233
private ulong _totalRuntimeOverRuns;
3334

3435
// Beware this class is created on a thread but can be disposed on another so don't trust the lock is not going to be held
35-
private Context(IntPtr contextHandle, Waf waf, ReaderWriterLock wafLocker, WafLibraryInvoker wafLibraryInvoker)
36+
private Context(IntPtr contextHandle, Waf waf, WafLibraryInvoker wafLibraryInvoker)
3637
{
37-
_wafLocker = wafLocker;
3838
_contextHandle = contextHandle;
3939
_waf = waf;
4040
_wafLibraryInvoker = wafLibraryInvoker;
@@ -43,7 +43,7 @@ private Context(IntPtr contextHandle, Waf waf, ReaderWriterLock wafLocker, WafLi
4343

4444
~Context() => Dispose(false);
4545

46-
public static IContext? GetContext(IntPtr contextHandle, Waf waf, ReaderWriterLock wafLocker, WafLibraryInvoker wafLibraryInvoker)
46+
public static IContext? GetContext(IntPtr contextHandle, Waf waf, WafLibraryInvoker wafLibraryInvoker)
4747
{
4848
// in high concurrency, the waf passed as argument here could have been disposed just above in between creation / waf update so last test here
4949
if (waf.Disposed)
@@ -52,8 +52,7 @@ private Context(IntPtr contextHandle, Waf waf, ReaderWriterLock wafLocker, WafLi
5252
return null;
5353
}
5454

55-
var hasLock = wafLocker.IsReadLockHeld || wafLocker.EnterReadLock();
56-
return hasLock ? new Context(contextHandle, waf, wafLocker, wafLibraryInvoker) : null;
55+
return new Context(contextHandle, waf, wafLibraryInvoker);
5756
}
5857

5958
public IResult? Run(IDictionary<string, object> addresses, ulong timeoutMicroSeconds)
@@ -81,7 +80,12 @@ private Context(IntPtr contextHandle, Waf waf, ReaderWriterLock wafLocker, WafLi
8180
_stopwatch.Start();
8281
using var pwArgs = Encoder.Encode(addresses, _wafLibraryInvoker, _argCache, applySafetyLimits: true);
8382
var rawArgs = pwArgs.RawPtr;
84-
var code = _waf.Run(_contextHandle, rawArgs, ref retNative, timeoutMicroSeconds);
83+
84+
DDWAF_RET_CODE code;
85+
lock (_sync)
86+
{
87+
code = _waf.Run(_contextHandle, rawArgs, ref retNative, timeoutMicroSeconds);
88+
}
8589

8690
_stopwatch.Stop();
8791
_totalRuntimeOverRuns += retNative.TotalRuntime / 1000;
@@ -113,9 +117,10 @@ public void Dispose(bool disposing)
113117
arg.Dispose();
114118
}
115119

116-
_wafLibraryInvoker.ContextDestroy(_contextHandle);
117-
118-
_wafLocker.ExitReadLock();
120+
lock (_sync)
121+
{
122+
_wafLibraryInvoker.ContextDestroy(_contextHandle);
123+
}
119124
}
120125

121126
public void Dispose()

tracer/src/Datadog.Trace/AppSec/Waf/IWaf.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
using System;
77
using System.Collections.Generic;
8-
using Datadog.Trace.AppSec.Concurrency;
98
using Datadog.Trace.AppSec.RcmModels.AsmData;
109
using Datadog.Trace.AppSec.Waf.NativeBindings;
1110

@@ -15,7 +14,7 @@ internal interface IWaf : IDisposable
1514
{
1615
public string Version { get; }
1716

18-
public IContext CreateContext(ReaderWriterLock wafLocker);
17+
public IContext CreateContext();
1918

2019
public bool UpdateRulesData(IEnumerable<RuleData> res);
2120

tracer/src/Datadog.Trace/AppSec/Waf/Initialization/LibraryLocationHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ internal static string GetLibName(FrameworkDescription fwk, string libVersion =
180180
internal static string[] GetRuntimeIds(FrameworkDescription fwk)
181181
=> fwk.OSPlatform switch
182182
{
183-
OSPlatformName.MacOS => new[] { $"osx-x64" },
183+
OSPlatformName.MacOS => new[] { $"osx" },
184184
OSPlatformName.Windows => new[] { $"win-{fwk.ProcessArchitecture}" },
185185
OSPlatformName.Linux => fwk.ProcessArchitecture == ProcessArchitecture.Arm64
186186
? new[] { "linux-arm64" }

tracer/src/Datadog.Trace/AppSec/Waf/Waf.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ internal static InitializationResult Create(WafLibraryInvoker wafLibraryInvoker,
7272
/// </summary>
7373
/// <returns>Context object to perform matching using the provided WAF instance</returns>
7474
/// <exception cref="Exception">Exception</exception>
75-
public IContext? CreateContext(Concurrency.ReaderWriterLock wafLocker)
75+
public IContext? CreateContext()
7676
{
7777
if (Disposed)
7878
{
@@ -88,7 +88,7 @@ internal static InitializationResult Create(WafLibraryInvoker wafLibraryInvoker,
8888
throw new Exception(InitContextError);
8989
}
9090

91-
return Context.GetContext(contextHandle, this, wafLocker, _wafLibraryInvoker);
91+
return Context.GetContext(contextHandle, this, _wafLibraryInvoker);
9292
}
9393

9494
// Requires a non disposed waf handle

0 commit comments

Comments
 (0)