Skip to content

Commit c227ee7

Browse files
authored
libddwaf v1.8.2 (#3)
1 parent 7281454 commit c227ee7

File tree

9 files changed

+162
-323
lines changed

9 files changed

+162
-323
lines changed

_tools/libddwaf-updater/update.sh

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#!/bin/bash
2+
3+
#
4+
# Unless explicitly stated otherwise all files in this repository are licensed
5+
# under the Apache License Version 2.0.
6+
# This product includes software developed at Datadog (https://www.datadoghq.com/).
7+
# Copyright 2016 Datadog, Inc.
8+
#
9+
10+
# Update the libddwaf to the latest GitHub release version.
11+
# Usage: ./update-libddwaf.sh
12+
#
13+
14+
set -ex
15+
16+
bindings_dir=$(readlink -f "$(dirname $0)/../../")
17+
18+
version=""
19+
if [ $# -eq 1 ]; then
20+
version=$1
21+
else
22+
echo Looking up for the latest GitHub release
23+
version=$(curl -s https://api.github.com/repos/DataDog/libddwaf/releases/latest | jq -r '.tag_name')
24+
fi
25+
26+
echo Updating to libddwaf v$version
27+
28+
tmpdir=$(mktemp -d /tmp/libddwaf-XXXXXXXX)
29+
echo Using $tmpdir
30+
31+
LD_REQUIRED_DEFINED="--require-defined=ddwaf_init \
32+
--require-defined=ddwaf_get_version \
33+
--require-defined=ddwaf_destroy \
34+
--require-defined=ddwaf_context_init \
35+
--require-defined=ddwaf_context_destroy \
36+
--require-defined=ddwaf_required_addresses \
37+
--require-defined=ddwaf_result_free"
38+
39+
run_binutils() {
40+
docker run -it --rm -v $bindings_dir:$bindings_dir -v $tmpdir:$tmpdir -w $PWD ghcr.io/datadog/binutils-gdb:2.38 $@
41+
}
42+
43+
run_strip() {
44+
run_binutils $1-strip --strip-dwo --strip-unneeded --strip-debug $2
45+
}
46+
47+
#
48+
# darwin/arm64
49+
#
50+
51+
echo Updating libddwaf for darwin/arm64
52+
curl -L https://github.com/DataDog/libddwaf/releases/download/$version/libddwaf-$version-darwin-arm64.tar.gz | tar -xz -C$tmpdir
53+
echo Copying the darwin/arm64 library
54+
cp -v $tmpdir/libddwaf-$version-darwin-arm64/lib/libddwaf.a.stripped $bindings_dir/lib/darwin-arm64/libddwaf.a
55+
56+
#
57+
# darwin/amd64
58+
#
59+
60+
echo Updating libddwaf for darwin/amd64yes
61+
curl -L https://github.com/DataDog/libddwaf/releases/download/$version/libddwaf-$version-darwin-x86_64.tar.gz | tar -xz -C$tmpdir
62+
echo Copying the darwin/amd64 library
63+
cp -v $tmpdir/libddwaf-$version-darwin-x86_64/lib/libddwaf.a.stripped $bindings_dir/lib/darwin-amd64/libddwaf.a
64+
65+
#
66+
# linux/amd64
67+
#
68+
69+
echo Updating libddwaf for linux/amd64
70+
# 1. Download the libddwaf build
71+
curl -L https://github.com/DataDog/libddwaf/releases/download/$version/libddwaf-$version-linux-x86_64.tar.gz | tar -xz -C$tmpdir
72+
# 2. Download the libc++ build
73+
libcxx_dir=$tmpdir/libc++-x86_64-linux
74+
mkdir $libcxx_dir
75+
curl -L https://github.com/DataDog/libddwaf/releases/download/$version/libc++-static-x86_64-linux.tar.gz | tar -xz -C$libcxx_dir
76+
# 3. Combine libddwaf.a + libc++.a + libc++abi.a + libunwind.a in a single
77+
# object file by using ld -r
78+
run_binutils x86_64-linux-gnu-ld \
79+
-r -o $bindings_dir/lib/linux-amd64/libddwaf.a \
80+
$LD_REQUIRED_DEFINED \
81+
$tmpdir/libddwaf-$version-linux-x86_64/lib/libddwaf.a $libcxx_dir/libc++.a $libcxx_dir/libc++abi.a $libcxx_dir/libunwind.a
82+
# 4. Strip
83+
run_strip x86_64-linux-gnu $bindings_dir/lib/linux-amd64/libddwaf.a
84+
85+
#
86+
# linux/arm64
87+
#
88+
89+
echo Updating libddwaf for linux/arm64
90+
# 1. Download the libddwaf build
91+
curl -L https://github.com/DataDog/libddwaf/releases/download/$version/libddwaf-$version-linux-aarch64.tar.gz | tar -xz -C$tmpdir
92+
# 2. Download the libc++ build
93+
libcxx_dir=$tmpdir/libc++-aarch64-linux
94+
mkdir $libcxx_dir
95+
curl -L https://github.com/DataDog/libddwaf/releases/download/$version/libc++-static-aarch64-linux.tar.gz | tar -xz -C$libcxx_dir
96+
# 3. Combine libddwaf.a + libc++.a + libc++abi.a + libunwind.a in a single
97+
# object file by using ld -r
98+
run_binutils aarch64-linux-gnu-ld \
99+
-r -o $bindings_dir/lib/linux-arm64/libddwaf.a \
100+
$LD_REQUIRED_DEFINED \
101+
$tmpdir/libddwaf-$version-linux-aarch64/lib/libddwaf.a $libcxx_dir/libc++.a $libcxx_dir/libc++abi.a $libcxx_dir/libunwind.a
102+
# 4. Strip
103+
run_strip aarch64-linux-gnu $bindings_dir/lib/linux-arm64/libddwaf.a
104+
105+
#
106+
# ddwaf.h
107+
# Note that we arbitrarily take it from the linux/amd64 archive as it does not
108+
# depend on the target.
109+
#
110+
echo Updating ddwaf.h
111+
cp -v $tmpdir/libddwaf-$version-linux-x86_64/include/ddwaf.h $bindings_dir/include

include/ddwaf.h

Lines changed: 38 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,17 @@
44
// This product includes software developed at Datadog (https://www.datadoghq.com/).
55
// Copyright 2021 Datadog, Inc.
66

7-
#ifndef pw_h
8-
#define pw_h
7+
#ifndef DDWAF_H
8+
#define DDWAF_H
99

1010
#ifdef __cplusplus
11+
namespace ddwaf{
12+
class waf;
13+
class context;
14+
} // namespace ddwaf
15+
using ddwaf_handle = ddwaf::waf *;
16+
using ddwaf_context = ddwaf::context *;
17+
1118
extern "C"
1219
{
1320
#endif
@@ -72,14 +79,7 @@ typedef enum
7279
DDWAF_LOG_OFF,
7380
} DDWAF_LOG_LEVEL;
7481

75-
#ifdef __cplusplus
76-
namespace ddwaf{
77-
class waf;
78-
class context;
79-
}
80-
using ddwaf_handle = ddwaf::waf *;
81-
using ddwaf_context = ddwaf::context *;
82-
#else
82+
#ifndef __cplusplus
8383
typedef struct _ddwaf_handle* ddwaf_handle;
8484
typedef struct _ddwaf_context* ddwaf_context;
8585
#endif
@@ -206,46 +206,40 @@ typedef void (*ddwaf_log_cb)(
206206
*
207207
* Initialize a ddwaf instance
208208
*
209-
* @param rule ddwaf::object containing the patterns to be used by the WAF. (nonnull)
209+
* @param rule ddwaf::object map containing rules, exclusions, rules_override and rules_data. (nonnull)
210210
* @param config Optional configuration of the WAF. (nullable)
211211
* @param info Optional ruleset parsing diagnostics. (nullable)
212212
*
213-
* @return Handle to the WAF instance.
213+
* @return Handle to the WAF instance or NULL on error.
214214
*
215215
* @note If config is NULL, default values will be used, including the default
216216
* free function (ddwaf_object_free).
217217
**/
218-
ddwaf_handle ddwaf_init(const ddwaf_object *rule,
218+
ddwaf_handle ddwaf_init(const ddwaf_object *ruleset,
219219
const ddwaf_config* config, ddwaf_ruleset_info *info);
220220

221221
/**
222-
* ddwaf_destroy
223-
*
224-
* Destroy a WAF instance.
222+
* ddwaf_update
225223
*
226-
* @param Handle to the WAF instance.
227-
*/
228-
void ddwaf_destroy(ddwaf_handle handle);
229-
230-
/**
231-
* ddwaf_update_rule_data
224+
* Update a ddwaf instance
232225
*
233-
* Update existing rules with new rule data.
226+
* @param rule ddwaf::object map containing rules, exclusions, rules_override and rules_data. (nonnull)
227+
* @param info Optional ruleset parsing diagnostics. (nullable)
234228
*
235-
* @param handle to the WAF instance.
236-
* @param data A ddwaf_object with the format [{id, type, [data]}].
237-
*/
238-
DDWAF_RET_CODE ddwaf_update_rule_data(ddwaf_handle handle, ddwaf_object *data);
229+
* @return Handle to the new WAF instance or NULL if there were no new updates
230+
* or there was an error processing the ruleset.
231+
**/
232+
ddwaf_handle ddwaf_update(ddwaf_handle handle, const ddwaf_object *ruleset,
233+
ddwaf_ruleset_info *info);
239234

240235
/**
241-
* ddwaf_toggle_rules
236+
* ddwaf_destroy
242237
*
243-
* Enable or disable rules (true -> rule enabled, false -> rule disabled).
238+
* Destroy a WAF instance.
244239
*
245-
* @param handle to the WAF instance.
246-
* @param data A ddwaf_object with the format {rule_id : boolean}.
240+
* @param Handle to the WAF instance.
247241
*/
248-
DDWAF_RET_CODE ddwaf_toggle_rules(ddwaf_handle handle, ddwaf_object *rule_map);
242+
void ddwaf_destroy(ddwaf_handle handle);
249243

250244
/**
251245
* ddwaf_ruleset_info_free
@@ -267,18 +261,6 @@ void ddwaf_ruleset_info_free(ddwaf_ruleset_info *info);
267261
* @return NULL if empty, otherwise a pointer to an array with size elements.
268262
**/
269263
const char* const* ddwaf_required_addresses(const ddwaf_handle handle, uint32_t *size);
270-
/**
271-
* ddwaf_required_rule_data_ids
272-
*
273-
* Get a list of required rule data IDs (if any). The memory is owned by the
274-
* WAF and should not be freed.
275-
*
276-
* @param Handle to the WAF instance.
277-
* @param size Output parameter in which the size will be returned. The value of
278-
* size will be 0 if the return value is NULL.
279-
* @return NULL if empty, otherwise a pointer to an array with size elements.
280-
**/
281-
const char* const* ddwaf_required_rule_data_ids(const ddwaf_handle handle, uint32_t *size);
282264

283265
/**
284266
* ddwaf_context_init
@@ -622,6 +604,17 @@ uint64_t ddwaf_object_get_unsigned(ddwaf_object *object);
622604
**/
623605
int64_t ddwaf_object_get_signed(ddwaf_object *object);
624606

607+
/**
608+
* ddwaf_object_get_bool
609+
*
610+
* Returns the boolean contained within the object.
611+
*
612+
* @param object The object from which to get the boolean.
613+
*
614+
* @return The boolean or false if the object is not a boolean.
615+
**/
616+
bool ddwaf_object_get_bool(ddwaf_object *object);
617+
625618
/**
626619
* ddwaf_object_get_index
627620
*
@@ -668,4 +661,4 @@ bool ddwaf_set_log_cb(ddwaf_log_cb cb, DDWAF_LOG_LEVEL min_level);
668661
}
669662
#endif /* __cplusplus */
670663

671-
#endif /* pw_h */
664+
#endif /*DDWAF_H */

lib/darwin-amd64/libddwaf.a

311 KB
Binary file not shown.

lib/darwin-arm64/libddwaf.a

265 KB
Binary file not shown.

lib/linux-amd64/libddwaf.a

-27.7 MB
Binary file not shown.

lib/linux-arm64/libddwaf.a

285 KB
Binary file not shown.

waf.go

Lines changed: 6 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import (
3535
"unicode"
3636
"unsafe"
3737

38-
rc "github.com/DataDog/datadog-agent/pkg/remoteconfig/state"
3938
"go.uber.org/atomic"
4039

4140
// Do not remove the following imports which allow supporting package
@@ -96,14 +95,16 @@ func NewHandle(jsonRule []byte, keyRegex, valueRegex string) (*Handle, error) {
9695
if err := json.Unmarshal(jsonRule, &rule); err != nil {
9796
return nil, fmt.Errorf("could not parse the WAF rule: %v", err)
9897
}
98+
return NewHandleFromRuleSet(rule, keyRegex, valueRegex)
99+
}
99100

101+
// NewHandleFromRuleSet creates a new instance of the WAF with the given ruleset and key/value regexps for obfuscation.
102+
func NewHandleFromRuleSet(ruleset interface{}, keyRegex, valueRegex string) (*Handle, error) {
100103
// Create a temporary unlimited encoder for the rules
101-
const intSize = 32 << (^uint(0) >> 63) // copied from recent versions of math.MaxInt
102-
const maxInt = 1<<(intSize-1) - 1 // copied from recent versions of math.MaxInt
103104
ruleEncoder := newMaxEncoder()
104-
wafRule, err := ruleEncoder.encode(rule)
105+
wafRule, err := ruleEncoder.encode(ruleset)
105106
if err != nil {
106-
return nil, fmt.Errorf("could not encode the JSON WAF rule into a WAF object: %v", err)
107+
return nil, fmt.Errorf("could not encode the WAF ruleset into a WAF object: %v", err)
107108
}
108109
defer freeWO(wafRule)
109110

@@ -219,34 +220,6 @@ func (h *Handle) RulesetInfo() RulesetInfo {
219220
return h.rulesetInfo
220221
}
221222

222-
// UpdateRulesData updates the data that some rules reference to.
223-
func (h *Handle) UpdateRulesData(data []rc.ASMDataRuleData) error {
224-
encoded, err := newMaxEncoder().encode(data)
225-
if err != nil {
226-
return fmt.Errorf("could not encode the JSON WAF rule data into a WAF object: %v", err)
227-
}
228-
defer freeWO(encoded)
229-
230-
return h.updateRulesData(encoded)
231-
}
232-
233-
// updateRuleData is the critical section of UpdateRuleData
234-
func (h *Handle) updateRulesData(data *wafObject) error {
235-
// Note about this lock: ddwaf_update_rule_data already is thread-safe to
236-
// use, but we chose to lock at the goroutine-level instead in order to
237-
// avoid locking OS threads and therefore prevent many other goroutines from
238-
// executing during that OS lock. If a goroutine locks due to this handle's
239-
// RWMutex, another goroutine gets executed on its OS thread.
240-
h.mu.Lock()
241-
defer h.mu.Unlock()
242-
243-
rc := C.ddwaf_update_rule_data(h.handle, data.ctype())
244-
if rc != C.DDWAF_OK {
245-
return fmt.Errorf("unexpected error number `%d` while updating the WAF rule data", rc)
246-
}
247-
return nil
248-
}
249-
250223
// Close the WAF handle. Note that this call doesn't block until the handle gets
251224
// released but instead let WAF contexts still use it until there's no more (eg.
252225
// when swapping the WAF handle with a new one).

waf_disabled.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ package waf
1111
import (
1212
"errors"
1313
"time"
14-
15-
rc "github.com/DataDog/datadog-agent/pkg/remoteconfig/state"
1614
)
1715

1816
type (
@@ -34,17 +32,17 @@ func Version() string { return "" }
3432
// NewHandle creates a new instance of the WAF with the given JSON rule.
3533
func NewHandle([]byte, string, string) (*Handle, error) { return nil, errDisabledReason }
3634

35+
// NewHandleFromRuleSet creates a new instance of the WAF with the given ruleset and key/value regexps for obfuscation.
36+
func NewHandleFromRuleSet(interface{}, string, string) (*Handle, error) {
37+
return nil, errDisabledReason
38+
}
39+
3740
// Addresses returns the list of addresses the WAF rule is expecting.
3841
func (*Handle) Addresses() []string { return nil }
3942

4043
// RulesetInfo returns the rules initialization metrics for the current WAF handle
4144
func (*Handle) RulesetInfo() RulesetInfo { return RulesetInfo{} }
4245

43-
// UpdateRuleData updates the data that some rules reference to.
44-
// The given rule data must be a raw JSON string of the form
45-
// [ {rule data #1}, ... {rule data #2} ]
46-
func (*Handle) UpdateRulesData(data []rc.ASMDataRuleData) error { return errDisabledReason }
47-
4846
// Close the WAF and release the underlying C memory as soon as there are
4947
// no more WAF contexts using the rule.
5048
func (*Handle) Close() {}

0 commit comments

Comments
 (0)