Skip to content

Commit 0ff2922

Browse files
dwindsorKernel Patches Daemon
authored andcommitted
selftests/bpf: Add cred local storage tests
Signed-off-by: David Windsor <[email protected]>
1 parent 45b5680 commit 0ff2922

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <test_progs.h>
4+
#include <unistd.h>
5+
#include <sys/wait.h>
6+
7+
#include "cred_storage.skel.h"
8+
9+
static void test_cred_lifecycle(void)
10+
{
11+
struct cred_storage *skel;
12+
pid_t child;
13+
int status, err;
14+
15+
skel = cred_storage__open_and_load();
16+
if (!ASSERT_OK_PTR(skel, "skel_load"))
17+
return;
18+
19+
err = cred_storage__attach(skel);
20+
if (!ASSERT_OK(err, "attach"))
21+
goto cleanup;
22+
23+
skel->data->cred_storage_result = -1;
24+
25+
skel->bss->monitored_pid = getpid();
26+
27+
child = fork();
28+
if (child == 0) {
29+
/* forces cred_prepare with new credentials */
30+
exit(0);
31+
} else if (child > 0) {
32+
waitpid(child, &status, 0);
33+
34+
/* give time for cred_free hook to run */
35+
usleep(10000);
36+
37+
/* verify that the dummy value was stored and persisted */
38+
ASSERT_EQ(skel->data->cred_storage_result, 0,
39+
"cred_storage_dummy_value");
40+
} else {
41+
ASSERT_TRUE(false, "fork failed");
42+
}
43+
44+
cleanup:
45+
cred_storage__destroy(skel);
46+
}
47+
48+
void test_cred_storage(void)
49+
{
50+
if (test__start_subtest("lifecycle"))
51+
test_cred_lifecycle();
52+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Copyright (C) 2025 David Windsor.
5+
*/
6+
7+
#include "vmlinux.h"
8+
#include <bpf/bpf_helpers.h>
9+
#include <bpf/bpf_tracing.h>
10+
11+
char _license[] SEC("license") = "GPL";
12+
13+
#define DUMMY_STORAGE_VALUE 0xdeadbeef
14+
15+
extern struct bpf_local_storage_data *bpf_cred_storage_get(struct bpf_map *map,
16+
struct cred *cred,
17+
void *init, int init__sz, __u64 flags) __ksym;
18+
19+
__u32 monitored_pid = 0;
20+
int cred_storage_result = -1;
21+
22+
struct cred_storage {
23+
__u32 value;
24+
};
25+
26+
struct {
27+
__uint(type, BPF_MAP_TYPE_CRED_STORAGE);
28+
__uint(map_flags, BPF_F_NO_PREALLOC);
29+
__type(key, int);
30+
__type(value, struct cred_storage);
31+
} cred_storage_map SEC(".maps");
32+
33+
SEC("lsm/cred_prepare")
34+
int BPF_PROG(cred_prepare, struct cred *new, const struct cred *old, gfp_t gfp)
35+
{
36+
__u32 pid = bpf_get_current_pid_tgid() >> 32;
37+
struct cred_storage init_storage = {
38+
.value = DUMMY_STORAGE_VALUE,
39+
};
40+
struct bpf_local_storage_data *sdata;
41+
struct cred_storage *storage;
42+
43+
if (pid != monitored_pid)
44+
return 0;
45+
46+
sdata = bpf_cred_storage_get((struct bpf_map *)&cred_storage_map, new, &init_storage,
47+
sizeof(init_storage), BPF_LOCAL_STORAGE_GET_F_CREATE);
48+
if (!sdata)
49+
return 0;
50+
51+
storage = (struct cred_storage *)sdata->data;
52+
if (!storage)
53+
return 0;
54+
55+
/* Verify the storage was initialized correctly */
56+
if (storage->value == DUMMY_STORAGE_VALUE)
57+
cred_storage_result = 0;
58+
59+
return 0;
60+
}
61+
62+
SEC("lsm/cred_free")
63+
int BPF_PROG(cred_free, struct cred *cred)
64+
{
65+
__u32 pid = bpf_get_current_pid_tgid() >> 32;
66+
struct bpf_local_storage_data *sdata;
67+
struct cred_storage *storage;
68+
69+
if (pid != monitored_pid)
70+
return 0;
71+
72+
/* Try to retrieve the storage that should have been created in prepare */
73+
sdata = bpf_cred_storage_get((struct bpf_map *)&cred_storage_map, cred,
74+
NULL, 0, 0);
75+
if (!sdata)
76+
return 0;
77+
78+
storage = (struct cred_storage *)sdata->data;
79+
if (!storage)
80+
return 0;
81+
82+
/* Verify the dummy value is still there during free */
83+
if (storage->value == DUMMY_STORAGE_VALUE)
84+
cred_storage_result = 0;
85+
86+
return 0;
87+
}

0 commit comments

Comments
 (0)