Skip to content

Commit

Permalink
[CWS] Add 4 tests, one for each kernel rate limiter algo (#15064)
Browse files Browse the repository at this point in the history
  • Loading branch information
spikat authored Jan 16, 2023
1 parent c548704 commit 1d69d14
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 6 deletions.
2 changes: 1 addition & 1 deletion pkg/ebpf/bytecode/runtime/runtime-security.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pkg/security/ebpf/c/activity_dump.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,9 @@ enum rate_limiter_algo_ids {
__attribute__((always_inline)) u8 activity_dump_rate_limiter_reset_period(u64 now, struct activity_dump_rate_limiter_ctx* rate_ctx_p) {
rate_ctx_p->current_period = now;
rate_ctx_p->counter = 0;
#ifndef __BALOUM__ // do not change algo during unit tests
rate_ctx_p->algo_id = now % RL_ALGO_TOTAL_NUMBER;
#endif /* __BALOUM__ */
return 1;
}

Expand Down
128 changes: 128 additions & 0 deletions pkg/security/ebpf/c/activity_dump_ratelimiter_test.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#ifndef _ACTIVITY_DUMP_RATELIMITER_TEST_H_
#define _ACTIVITY_DUMP_RATELIMITER_TEST_H_

#include "defs.h"
#include "activity_dump.h"
#include "baloum.h"
#include "utils.h"

#define AD_RL_TEST_RATE 500
#define NUMBER_OF_PERIOD_PER_TEST 10

SEC("test/ad_ratelimiter_basic")
int test_ad_ratelimiter_basic()
{
u64 now = bpf_ktime_get_ns();

struct activity_dump_config config;
config.events_rate = AD_RL_TEST_RATE;

struct activity_dump_rate_limiter_ctx ctx;
ctx.counter = 0;
ctx.current_period = now;
ctx.algo_id = RL_ALGO_BASIC; // force algo basic
u32 cookie = 0;
bpf_map_update_elem(&activity_dump_rate_limiters, &cookie, &ctx, BPF_ANY);

for (int period_cpt = 0; period_cpt < NUMBER_OF_PERIOD_PER_TEST; period_cpt++, now += SEC_TO_NS(2)) {
assert_not_zero(activity_dump_rate_limiter_allow(&config, cookie, now, 0),
"event not allowed which should be");
for (int i = 0; i < AD_RL_TEST_RATE; i++) {
assert_not_zero(activity_dump_rate_limiter_allow(&config, cookie, now + i, 1),
"event not allowed which should be");
}

assert_zero(activity_dump_rate_limiter_allow(&config, cookie, now, 0),
"event allowed which should not be");
for (int i = 0; i < AD_RL_TEST_RATE; i++) {
assert_zero(activity_dump_rate_limiter_allow(&config, cookie, now + i, 1),
"event allowed which should not be");
}
assert_zero(activity_dump_rate_limiter_allow(&config, cookie, now, 0),
"event allowed which should not be");
}
return 0;
}

SEC("test/ad_ratelimiter_basic_half")
int test_ad_ratelimiter_basic_half()
{
u64 now = bpf_ktime_get_ns();

struct activity_dump_config config;
config.events_rate = AD_RL_TEST_RATE;

struct activity_dump_rate_limiter_ctx ctx;
ctx.counter = 0;
ctx.current_period = now;
ctx.algo_id = RL_ALGO_BASIC_HALF; // force algo basic half
u32 cookie = 0;
bpf_map_update_elem(&activity_dump_rate_limiters, &cookie, &ctx, BPF_ANY);

for (int period_cpt = 0; period_cpt < NUMBER_OF_PERIOD_PER_TEST; period_cpt++, now += SEC_TO_NS(1)) {
assert_not_zero(activity_dump_rate_limiter_allow(&config, cookie, now, 0),
"event not allowed which should be");
for (int i = 0; i < AD_RL_TEST_RATE / 2; i++) {
assert_not_zero(activity_dump_rate_limiter_allow(&config, cookie, now + i, 1),
"event not allowed which should be");
}

assert_zero(activity_dump_rate_limiter_allow(&config, cookie, now, 0),
"event allowed which should not be");
for (int i = 0; i < AD_RL_TEST_RATE / 2; i++) {
assert_zero(activity_dump_rate_limiter_allow(&config, cookie, now + i, 1),
"event allowed which should not be");
}
assert_zero(activity_dump_rate_limiter_allow(&config, cookie, now, 0),
"event allowed which should not be");
}
return 0;
}

__attribute__((always_inline)) int test_ad_ratelimiter_variable_droprate(int algo)
{
u64 now = bpf_ktime_get_ns();

struct activity_dump_config config;
config.events_rate = AD_RL_TEST_RATE;

struct activity_dump_rate_limiter_ctx ctx;
ctx.counter = 0;
ctx.current_period = now;
ctx.algo_id = algo; // force algo
u32 cookie = 0;
bpf_map_update_elem(&activity_dump_rate_limiters, &cookie, &ctx, BPF_ANY);

for (int period_cpt = 0; period_cpt < NUMBER_OF_PERIOD_PER_TEST; period_cpt++, now += SEC_TO_NS(2)) {
assert_not_zero(activity_dump_rate_limiter_allow(&config, cookie, now, 0),
"event not allowed which should be");
for (int i = 0; i < AD_RL_TEST_RATE / 4; i++) {
assert_not_zero(activity_dump_rate_limiter_allow(&config, cookie, now + i, 1),
"event not allowed which should be");
}

int total_allowed = 0;
for (int i = 0; i < AD_RL_TEST_RATE * 10; i++) {
if (activity_dump_rate_limiter_allow(&config, cookie, now + i, 1)) {
total_allowed++;
}
}
assert_greater_than(total_allowed, AD_RL_TEST_RATE * 3 / 4, "nope");
assert_lesser_than(total_allowed, AD_RL_TEST_RATE / 10, "nope");
}
return 0;
}

SEC("test/ad_ratelimiter_decreasing_droprate")
int test_ad_ratelimiter_decreasing_droprate()
{
return test_ad_ratelimiter_variable_droprate(RL_ALGO_DECREASING_DROPRATE);
}

SEC("test/ad_ratelimiter_increasing_droprate")
int test_ad_ratelimiter_increasing_droprate()
{
return test_ad_ratelimiter_variable_droprate(RL_ALGO_INCREASING_DROPRATE);
}

#endif /* _ACTIVITY_DUMP_RATELIMITER_TEST_H_ */
30 changes: 29 additions & 1 deletion pkg/security/ebpf/c/baloum.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,34 @@ static int (*baloum_sleep)(__u64 ns) = (void *)0xfffb;
return -1; \
}

#define assert_greater_than(v1, v2, msg) \
if (v1 > v2) \
{ \
bpf_printk("assert line %d : v1 == v2 : %s", __LINE__, msg); \
return -1; \
}

#define assert_lesser_than(v1, v2, msg) \
if (v1 < v2) \
{ \
bpf_printk("assert line %d : v1 == v2 : %s", __LINE__, msg); \
return -1; \
}

#define assert_greater_or_equal_than(v1, v2, msg) \
if (v1 >= v2) \
{ \
bpf_printk("assert line %d : v1 == v2 : %s", __LINE__, msg); \
return -1; \
}

#define assert_lesser_or_equal_than(v1, v2, msg) \
if (v1 <= v2) \
{ \
bpf_printk("assert line %d : v1 == v2 : %s", __LINE__, msg); \
return -1; \
}

#define assert_not_null(v1, msg) \
if (v1 == NULL) \
{ \
Expand All @@ -75,4 +103,4 @@ static int (*baloum_sleep)(__u64 ns) = (void *)0xfffb;

#endif

#endif
#endif
5 changes: 2 additions & 3 deletions pkg/security/ebpf/c/discarders.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
#ifndef _DISCARDERS_H
#define _DISCARDERS_H

#include "utils.h"

#define REVISION_ARRAY_SIZE 4096

#define INODE_DISCARDER_TYPE 0
#define PID_DISCARDER_TYPE 1

#define NS_TO_SEC(x) x / 1000000000
#define SEC_TO_NS(x) x * 1000000000

struct discarder_stats_t {
u64 discarders_added;
u64 event_discarded;
Expand Down
3 changes: 2 additions & 1 deletion pkg/security/ebpf/c/tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
#define _TESTS_H

#include "discarders_test.h"
#include "activity_dump_ratelimiter_test.h"

#endif
#endif
7 changes: 7 additions & 0 deletions pkg/security/ebpf/c/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef _UTILS_H_
#define _UTILS_H_

#define NS_TO_SEC(x) (x) / 1000000000
#define SEC_TO_NS(x) (x) * 1000000000

#endif /* _UTILS_H_ */
47 changes: 47 additions & 0 deletions pkg/security/ebpf/tests/activity_dump_ratelimiter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.

//go:build linux && ebpf_bindata
// +build linux,ebpf_bindata

package tests

import (
"testing"

"github.com/safchain/baloum/pkg/baloum"
)

func TestActivityDumpRateLimiterBasic(t *testing.T) {
var ctx baloum.StdContext
code, err := newVM(t).RunProgram(&ctx, "test/ad_ratelimiter_basic")
if err != nil || code != 0 {
t.Errorf("unexpected error: %v, %d", err, code)
}
}

func TestActivityDumpRateLimiterBasicHalf(t *testing.T) {
var ctx baloum.StdContext
code, err := newVM(t).RunProgram(&ctx, "test/ad_ratelimiter_basic_half")
if err != nil || code != 0 {
t.Errorf("unexpected error: %v, %d", err, code)
}
}

func TestActivityDumpRateLimiterDecreasingDroprate(t *testing.T) {
var ctx baloum.StdContext
code, err := newVM(t).RunProgram(&ctx, "test/ad_ratelimiter_decreasing_droprate")
if err != nil || code != 0 {
t.Errorf("unexpected error: %v, %d", err, code)
}
}

func TestActivityDumpRateLimiterIncreasingDroprate(t *testing.T) {
var ctx baloum.StdContext
code, err := newVM(t).RunProgram(&ctx, "test/ad_ratelimiter_increasing_droprate")
if err != nil || code != 0 {
t.Errorf("unexpected error: %v, %d", err, code)
}
}

0 comments on commit 1d69d14

Please sign in to comment.