Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Remove bpf_cgroup_kptr_get() kfunc

Now that bpf_cgroup_acquire() is KF_RCU | KF_RET_NULL,
bpf_cgroup_kptr_get() is redundant. Let's remove it, and update
selftests to instead use bpf_cgroup_acquire() where appropriate. The
next patch will update the BPF documentation to not mention
bpf_cgroup_kptr_get().

Signed-off-by: David Vernet <void@manifault.com>
Link: https://lore.kernel.org/r/20230411041633.179404-2-void@manifault.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

David Vernet and committed by
Alexei Starovoitov
6499fe6e 1d712839

+14 -99
-32
kernel/bpf/helpers.c
··· 2041 2041 } 2042 2042 2043 2043 /** 2044 - * bpf_cgroup_kptr_get - Acquire a reference on a struct cgroup kptr. A cgroup 2045 - * kptr acquired by this kfunc which is not subsequently stored in a map, must 2046 - * be released by calling bpf_cgroup_release(). 2047 - * @cgrpp: A pointer to a cgroup kptr on which a reference is being acquired. 2048 - */ 2049 - __bpf_kfunc struct cgroup *bpf_cgroup_kptr_get(struct cgroup **cgrpp) 2050 - { 2051 - struct cgroup *cgrp; 2052 - 2053 - rcu_read_lock(); 2054 - /* Another context could remove the cgroup from the map and release it 2055 - * at any time, including after we've done the lookup above. This is 2056 - * safe because we're in an RCU read region, so the cgroup is 2057 - * guaranteed to remain valid until at least the rcu_read_unlock() 2058 - * below. 2059 - */ 2060 - cgrp = READ_ONCE(*cgrpp); 2061 - 2062 - if (cgrp && !cgroup_tryget(cgrp)) 2063 - /* If the cgroup had been removed from the map and freed as 2064 - * described above, cgroup_tryget() will return false. The 2065 - * cgroup will be freed at some point after the current RCU gp 2066 - * has ended, so just return NULL to the user. 2067 - */ 2068 - cgrp = NULL; 2069 - rcu_read_unlock(); 2070 - 2071 - return cgrp; 2072 - } 2073 - 2074 - /** 2075 2044 * bpf_cgroup_release - Release the reference acquired on a cgroup. 2076 2045 * If this kfunc is invoked in an RCU read region, the cgroup is guaranteed to 2077 2046 * not be freed until the current grace period has ended, even if its refcount ··· 2283 2314 2284 2315 #ifdef CONFIG_CGROUPS 2285 2316 BTF_ID_FLAGS(func, bpf_cgroup_acquire, KF_ACQUIRE | KF_RCU | KF_RET_NULL) 2286 - BTF_ID_FLAGS(func, bpf_cgroup_kptr_get, KF_ACQUIRE | KF_KPTR_GET | KF_RET_NULL) 2287 2317 BTF_ID_FLAGS(func, bpf_cgroup_release, KF_RELEASE) 2288 2318 BTF_ID_FLAGS(func, bpf_cgroup_ancestor, KF_ACQUIRE | KF_RCU | KF_RET_NULL) 2289 2319 BTF_ID_FLAGS(func, bpf_cgroup_from_id, KF_ACQUIRE | KF_RET_NULL)
+2 -1
tools/testing/selftests/bpf/progs/cgrp_kfunc_common.h
··· 21 21 } __cgrps_kfunc_map SEC(".maps"); 22 22 23 23 struct cgroup *bpf_cgroup_acquire(struct cgroup *p) __ksym; 24 - struct cgroup *bpf_cgroup_kptr_get(struct cgroup **pp) __ksym; 25 24 void bpf_cgroup_release(struct cgroup *p) __ksym; 26 25 struct cgroup *bpf_cgroup_ancestor(struct cgroup *cgrp, int level) __ksym; 27 26 struct cgroup *bpf_cgroup_from_id(u64 cgid) __ksym; 27 + void bpf_rcu_read_lock(void) __ksym; 28 + void bpf_rcu_read_unlock(void) __ksym; 28 29 29 30 static inline struct __cgrps_kfunc_map_value *cgrps_kfunc_map_value_lookup(struct cgroup *cgrp) 30 31 {
+8 -60
tools/testing/selftests/bpf/progs/cgrp_kfunc_failure.c
··· 134 134 } 135 135 136 136 SEC("tp_btf/cgroup_mkdir") 137 - __failure __msg("arg#0 expected pointer to map value") 138 - int BPF_PROG(cgrp_kfunc_get_non_kptr_param, struct cgroup *cgrp, const char *path) 139 - { 140 - struct cgroup *kptr; 141 - 142 - /* Cannot use bpf_cgroup_kptr_get() on a non-kptr, even on a valid cgroup. */ 143 - kptr = bpf_cgroup_kptr_get(&cgrp); 144 - if (!kptr) 145 - return 0; 146 - 147 - bpf_cgroup_release(kptr); 148 - 149 - return 0; 150 - } 151 - 152 - SEC("tp_btf/cgroup_mkdir") 153 - __failure __msg("arg#0 expected pointer to map value") 154 - int BPF_PROG(cgrp_kfunc_get_non_kptr_acquired, struct cgroup *cgrp, const char *path) 155 - { 156 - struct cgroup *kptr, *acquired; 157 - 158 - acquired = bpf_cgroup_acquire(cgrp); 159 - if (!acquired) 160 - return 0; 161 - 162 - /* Cannot use bpf_cgroup_kptr_get() on a non-map-value, even if the kptr was acquired. */ 163 - kptr = bpf_cgroup_kptr_get(&acquired); 164 - bpf_cgroup_release(acquired); 165 - if (!kptr) 166 - return 0; 167 - 168 - bpf_cgroup_release(kptr); 169 - 170 - return 0; 171 - } 172 - 173 - SEC("tp_btf/cgroup_mkdir") 174 - __failure __msg("arg#0 expected pointer to map value") 175 - int BPF_PROG(cgrp_kfunc_get_null, struct cgroup *cgrp, const char *path) 176 - { 177 - struct cgroup *kptr; 178 - 179 - /* Cannot use bpf_cgroup_kptr_get() on a NULL pointer. */ 180 - kptr = bpf_cgroup_kptr_get(NULL); 181 - if (!kptr) 182 - return 0; 183 - 184 - bpf_cgroup_release(kptr); 185 - 186 - return 0; 187 - } 188 - 189 - SEC("tp_btf/cgroup_mkdir") 190 137 __failure __msg("Unreleased reference") 191 138 int BPF_PROG(cgrp_kfunc_xchg_unreleased, struct cgroup *cgrp, const char *path) 192 139 { ··· 154 207 } 155 208 156 209 SEC("tp_btf/cgroup_mkdir") 157 - __failure __msg("Unreleased reference") 158 - int BPF_PROG(cgrp_kfunc_get_unreleased, struct cgroup *cgrp, const char *path) 210 + __failure __msg("must be referenced or trusted") 211 + int BPF_PROG(cgrp_kfunc_rcu_get_release, struct cgroup *cgrp, const char *path) 159 212 { 160 213 struct cgroup *kptr; 161 214 struct __cgrps_kfunc_map_value *v; ··· 164 217 if (!v) 165 218 return 0; 166 219 167 - kptr = bpf_cgroup_kptr_get(&v->cgrp); 168 - if (!kptr) 169 - return 0; 170 - 171 - /* Kptr acquired above is never released. */ 220 + bpf_rcu_read_lock(); 221 + kptr = v->cgrp; 222 + if (kptr) 223 + /* Can't release a cgroup kptr stored in a map. */ 224 + bpf_cgroup_release(kptr); 225 + bpf_rcu_read_unlock(); 172 226 173 227 return 0; 174 228 }
+4 -6
tools/testing/selftests/bpf/progs/cgrp_kfunc_success.c
··· 126 126 return 0; 127 127 } 128 128 129 - kptr = bpf_cgroup_kptr_get(&v->cgrp); 130 - if (!kptr) { 129 + bpf_rcu_read_lock(); 130 + kptr = v->cgrp; 131 + if (!kptr) 131 132 err = 3; 132 - return 0; 133 - } 134 - 135 - bpf_cgroup_release(kptr); 133 + bpf_rcu_read_unlock(); 136 134 137 135 return 0; 138 136 }