Skip to content

Commit cd324d7

Browse files
sinkapAlexei Starovoitov
authored andcommitted
bpf: Add selftests for local_storage
inode_local_storage: * Hook to the file_open and inode_unlink LSM hooks. * Create and unlink a temporary file. * Store some information in the inode's bpf_local_storage during file_open. * Verify that this information exists when the file is unlinked. sk_local_storage: * Hook to the socket_post_create and socket_bind LSM hooks. * Open and bind a socket and set the sk_storage in the socket_post_create hook using the start_server helper. * Verify if the information is set in the socket_bind hook. Signed-off-by: KP Singh <kpsingh@google.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Andrii Nakryiko <andriin@fb.com> Link: https://lore.kernel.org/bpf/20200825182919.1118197-8-kpsingh@chromium.org
1 parent 3089783 commit cd324d7

File tree

2 files changed

+200
-0
lines changed

2 files changed

+200
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Copyright (C) 2020 Google LLC.
5+
*/
6+
7+
#include <test_progs.h>
8+
#include <linux/limits.h>
9+
10+
#include "local_storage.skel.h"
11+
#include "network_helpers.h"
12+
13+
int create_and_unlink_file(void)
14+
{
15+
char fname[PATH_MAX] = "/tmp/fileXXXXXX";
16+
int fd;
17+
18+
fd = mkstemp(fname);
19+
if (fd < 0)
20+
return fd;
21+
22+
close(fd);
23+
unlink(fname);
24+
return 0;
25+
}
26+
27+
void test_test_local_storage(void)
28+
{
29+
struct local_storage *skel = NULL;
30+
int err, duration = 0, serv_sk = -1;
31+
32+
skel = local_storage__open_and_load();
33+
if (CHECK(!skel, "skel_load", "lsm skeleton failed\n"))
34+
goto close_prog;
35+
36+
err = local_storage__attach(skel);
37+
if (CHECK(err, "attach", "lsm attach failed: %d\n", err))
38+
goto close_prog;
39+
40+
skel->bss->monitored_pid = getpid();
41+
42+
err = create_and_unlink_file();
43+
if (CHECK(err < 0, "exec_cmd", "err %d errno %d\n", err, errno))
44+
goto close_prog;
45+
46+
CHECK(skel->data->inode_storage_result != 0, "inode_storage_result",
47+
"inode_local_storage not set\n");
48+
49+
serv_sk = start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0);
50+
if (CHECK(serv_sk < 0, "start_server", "failed to start server\n"))
51+
goto close_prog;
52+
53+
CHECK(skel->data->sk_storage_result != 0, "sk_storage_result",
54+
"sk_local_storage not set\n");
55+
56+
close(serv_sk);
57+
58+
close_prog:
59+
local_storage__destroy(skel);
60+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Copyright 2020 Google LLC.
5+
*/
6+
7+
#include <errno.h>
8+
#include <linux/bpf.h>
9+
#include <stdbool.h>
10+
#include <bpf/bpf_helpers.h>
11+
#include <bpf/bpf_tracing.h>
12+
13+
char _license[] SEC("license") = "GPL";
14+
15+
#define DUMMY_STORAGE_VALUE 0xdeadbeef
16+
17+
int monitored_pid = 0;
18+
int inode_storage_result = -1;
19+
int sk_storage_result = -1;
20+
21+
struct dummy_storage {
22+
__u32 value;
23+
};
24+
25+
struct {
26+
__uint(type, BPF_MAP_TYPE_INODE_STORAGE);
27+
__uint(map_flags, BPF_F_NO_PREALLOC);
28+
__type(key, int);
29+
__type(value, struct dummy_storage);
30+
} inode_storage_map SEC(".maps");
31+
32+
struct {
33+
__uint(type, BPF_MAP_TYPE_SK_STORAGE);
34+
__uint(map_flags, BPF_F_NO_PREALLOC | BPF_F_CLONE);
35+
__type(key, int);
36+
__type(value, struct dummy_storage);
37+
} sk_storage_map SEC(".maps");
38+
39+
/* TODO Use vmlinux.h once BTF pruning for embedded types is fixed.
40+
*/
41+
struct sock {} __attribute__((preserve_access_index));
42+
struct sockaddr {} __attribute__((preserve_access_index));
43+
struct socket {
44+
struct sock *sk;
45+
} __attribute__((preserve_access_index));
46+
47+
struct inode {} __attribute__((preserve_access_index));
48+
struct dentry {
49+
struct inode *d_inode;
50+
} __attribute__((preserve_access_index));
51+
struct file {
52+
struct inode *f_inode;
53+
} __attribute__((preserve_access_index));
54+
55+
56+
SEC("lsm/inode_unlink")
57+
int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim)
58+
{
59+
__u32 pid = bpf_get_current_pid_tgid() >> 32;
60+
struct dummy_storage *storage;
61+
62+
if (pid != monitored_pid)
63+
return 0;
64+
65+
storage = bpf_inode_storage_get(&inode_storage_map, victim->d_inode, 0,
66+
BPF_SK_STORAGE_GET_F_CREATE);
67+
if (!storage)
68+
return 0;
69+
70+
if (storage->value == DUMMY_STORAGE_VALUE)
71+
inode_storage_result = -1;
72+
73+
inode_storage_result =
74+
bpf_inode_storage_delete(&inode_storage_map, victim->d_inode);
75+
76+
return 0;
77+
}
78+
79+
SEC("lsm/socket_bind")
80+
int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,
81+
int addrlen)
82+
{
83+
__u32 pid = bpf_get_current_pid_tgid() >> 32;
84+
struct dummy_storage *storage;
85+
86+
if (pid != monitored_pid)
87+
return 0;
88+
89+
storage = bpf_sk_storage_get(&sk_storage_map, sock->sk, 0,
90+
BPF_SK_STORAGE_GET_F_CREATE);
91+
if (!storage)
92+
return 0;
93+
94+
if (storage->value == DUMMY_STORAGE_VALUE)
95+
sk_storage_result = -1;
96+
97+
sk_storage_result = bpf_sk_storage_delete(&sk_storage_map, sock->sk);
98+
return 0;
99+
}
100+
101+
SEC("lsm/socket_post_create")
102+
int BPF_PROG(socket_post_create, struct socket *sock, int family, int type,
103+
int protocol, int kern)
104+
{
105+
__u32 pid = bpf_get_current_pid_tgid() >> 32;
106+
struct dummy_storage *storage;
107+
108+
if (pid != monitored_pid)
109+
return 0;
110+
111+
storage = bpf_sk_storage_get(&sk_storage_map, sock->sk, 0,
112+
BPF_SK_STORAGE_GET_F_CREATE);
113+
if (!storage)
114+
return 0;
115+
116+
storage->value = DUMMY_STORAGE_VALUE;
117+
118+
return 0;
119+
}
120+
121+
SEC("lsm/file_open")
122+
int BPF_PROG(file_open, struct file *file)
123+
{
124+
__u32 pid = bpf_get_current_pid_tgid() >> 32;
125+
struct dummy_storage *storage;
126+
127+
if (pid != monitored_pid)
128+
return 0;
129+
130+
if (!file->f_inode)
131+
return 0;
132+
133+
storage = bpf_inode_storage_get(&inode_storage_map, file->f_inode, 0,
134+
BPF_LOCAL_STORAGE_GET_F_CREATE);
135+
if (!storage)
136+
return 0;
137+
138+
storage->value = DUMMY_STORAGE_VALUE;
139+
return 0;
140+
}

0 commit comments

Comments
 (0)