Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CWS] Add 4 ebpf tests, one for each rate limiter algo #15064

Merged
merged 1 commit into from
Jan 16, 2023
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
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)
}
}