1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */
3
4 #include <vmlinux.h>
5 #include <bpf/bpf_tracing.h>
6 #include <bpf/bpf_helpers.h>
7 #include <bpf/bpf_core_read.h>
8 #include "bpf_experimental.h"
9 #include "bpf_misc.h"
10
11 char _license[] SEC("license") = "GPL";
12
13 char value[16];
14
read_xattr(struct cgroup * cgroup)15 static __always_inline void read_xattr(struct cgroup *cgroup)
16 {
17 struct bpf_dynptr value_ptr;
18
19 bpf_dynptr_from_mem(value, sizeof(value), 0, &value_ptr);
20 bpf_cgroup_read_xattr(cgroup, "user.bpf_test",
21 &value_ptr);
22 }
23
24 SEC("lsm.s/socket_connect")
25 __success
BPF_PROG(trusted_cgroup_ptr_sleepable)26 int BPF_PROG(trusted_cgroup_ptr_sleepable)
27 {
28 u64 cgrp_id = bpf_get_current_cgroup_id();
29 struct cgroup *cgrp;
30
31 cgrp = bpf_cgroup_from_id(cgrp_id);
32 if (!cgrp)
33 return 0;
34
35 read_xattr(cgrp);
36 bpf_cgroup_release(cgrp);
37 return 0;
38 }
39
40 SEC("lsm/socket_connect")
41 __success
BPF_PROG(trusted_cgroup_ptr_non_sleepable)42 int BPF_PROG(trusted_cgroup_ptr_non_sleepable)
43 {
44 u64 cgrp_id = bpf_get_current_cgroup_id();
45 struct cgroup *cgrp;
46
47 cgrp = bpf_cgroup_from_id(cgrp_id);
48 if (!cgrp)
49 return 0;
50
51 read_xattr(cgrp);
52 bpf_cgroup_release(cgrp);
53 return 0;
54 }
55
56 SEC("lsm/socket_connect")
57 __success
BPF_PROG(use_css_iter_non_sleepable)58 int BPF_PROG(use_css_iter_non_sleepable)
59 {
60 u64 cgrp_id = bpf_get_current_cgroup_id();
61 struct cgroup_subsys_state *css;
62 struct cgroup *cgrp;
63
64 cgrp = bpf_cgroup_from_id(cgrp_id);
65 if (!cgrp)
66 return 0;
67
68 bpf_for_each(css, css, &cgrp->self, BPF_CGROUP_ITER_ANCESTORS_UP)
69 read_xattr(css->cgroup);
70
71 bpf_cgroup_release(cgrp);
72 return 0;
73 }
74
75 SEC("lsm.s/socket_connect")
76 __failure __msg("expected an RCU CS")
BPF_PROG(use_css_iter_sleepable_missing_rcu_lock)77 int BPF_PROG(use_css_iter_sleepable_missing_rcu_lock)
78 {
79 u64 cgrp_id = bpf_get_current_cgroup_id();
80 struct cgroup_subsys_state *css;
81 struct cgroup *cgrp;
82
83 cgrp = bpf_cgroup_from_id(cgrp_id);
84 if (!cgrp)
85 return 0;
86
87 bpf_for_each(css, css, &cgrp->self, BPF_CGROUP_ITER_ANCESTORS_UP)
88 read_xattr(css->cgroup);
89
90 bpf_cgroup_release(cgrp);
91 return 0;
92 }
93
94 SEC("lsm.s/socket_connect")
95 __success
BPF_PROG(use_css_iter_sleepable_with_rcu_lock)96 int BPF_PROG(use_css_iter_sleepable_with_rcu_lock)
97 {
98 u64 cgrp_id = bpf_get_current_cgroup_id();
99 struct cgroup_subsys_state *css;
100 struct cgroup *cgrp;
101
102 bpf_rcu_read_lock();
103 cgrp = bpf_cgroup_from_id(cgrp_id);
104 if (!cgrp)
105 goto out;
106
107 bpf_for_each(css, css, &cgrp->self, BPF_CGROUP_ITER_ANCESTORS_UP)
108 read_xattr(css->cgroup);
109
110 bpf_cgroup_release(cgrp);
111 out:
112 bpf_rcu_read_unlock();
113 return 0;
114 }
115
116 SEC("lsm/socket_connect")
117 __success
BPF_PROG(use_bpf_cgroup_ancestor)118 int BPF_PROG(use_bpf_cgroup_ancestor)
119 {
120 u64 cgrp_id = bpf_get_current_cgroup_id();
121 struct cgroup *cgrp, *ancestor;
122
123 cgrp = bpf_cgroup_from_id(cgrp_id);
124 if (!cgrp)
125 return 0;
126
127 ancestor = bpf_cgroup_ancestor(cgrp, 1);
128 if (!ancestor)
129 goto out;
130
131 read_xattr(cgrp);
132 bpf_cgroup_release(ancestor);
133 out:
134 bpf_cgroup_release(cgrp);
135 return 0;
136 }
137
138 SEC("cgroup/sendmsg4")
139 __success
BPF_PROG(cgroup_skb)140 int BPF_PROG(cgroup_skb)
141 {
142 u64 cgrp_id = bpf_get_current_cgroup_id();
143 struct cgroup *cgrp, *ancestor;
144
145 cgrp = bpf_cgroup_from_id(cgrp_id);
146 if (!cgrp)
147 return 0;
148
149 ancestor = bpf_cgroup_ancestor(cgrp, 1);
150 if (!ancestor)
151 goto out;
152
153 read_xattr(cgrp);
154 bpf_cgroup_release(ancestor);
155 out:
156 bpf_cgroup_release(cgrp);
157 return 0;
158 }
159