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