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

bpf: Make bpf_cgroup_acquire() KF_RCU | KF_RET_NULL

struct cgroup is already an RCU-safe type in the verifier. We can
therefore update bpf_cgroup_acquire() to be KF_RCU | KF_RET_NULL, and
subsequently remove bpf_cgroup_kptr_get(). This patch does the first of
these by updating bpf_cgroup_acquire() to be KF_RCU | KF_RET_NULL, and
also updates selftests accordingly.

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

authored by

David Vernet and committed by
Alexei Starovoitov
1d712839 10fd5f70

+40 -10
+2 -3
kernel/bpf/helpers.c
··· 2037 2037 */ 2038 2038 __bpf_kfunc struct cgroup *bpf_cgroup_acquire(struct cgroup *cgrp) 2039 2039 { 2040 - cgroup_get(cgrp); 2041 - return cgrp; 2040 + return cgroup_tryget(cgrp) ? cgrp : NULL; 2042 2041 } 2043 2042 2044 2043 /** ··· 2313 2314 BTF_ID_FLAGS(func, bpf_rbtree_first, KF_RET_NULL) 2314 2315 2315 2316 #ifdef CONFIG_CGROUPS 2316 - BTF_ID_FLAGS(func, bpf_cgroup_acquire, KF_ACQUIRE | KF_TRUSTED_ARGS) 2317 + BTF_ID_FLAGS(func, bpf_cgroup_acquire, KF_ACQUIRE | KF_RCU | KF_RET_NULL) 2317 2318 BTF_ID_FLAGS(func, bpf_cgroup_kptr_get, KF_ACQUIRE | KF_KPTR_GET | KF_RET_NULL) 2318 2319 BTF_ID_FLAGS(func, bpf_cgroup_release, KF_RELEASE) 2319 2320 BTF_ID_FLAGS(func, bpf_cgroup_ancestor, KF_ACQUIRE | KF_RCU | KF_RET_NULL)
+5
tools/testing/selftests/bpf/progs/cgrp_kfunc_common.h
··· 61 61 } 62 62 63 63 acquired = bpf_cgroup_acquire(cgrp); 64 + if (!acquired) { 65 + bpf_map_delete_elem(&__cgrps_kfunc_map, &id); 66 + return -ENOENT; 67 + } 68 + 64 69 old = bpf_kptr_xchg(&v->cgrp, acquired); 65 70 if (old) { 66 71 bpf_cgroup_release(old);
+29 -6
tools/testing/selftests/bpf/progs/cgrp_kfunc_failure.c
··· 41 41 42 42 /* Can't invoke bpf_cgroup_acquire() on an untrusted pointer. */ 43 43 acquired = bpf_cgroup_acquire(v->cgrp); 44 + if (acquired) 45 + bpf_cgroup_release(acquired); 46 + 47 + return 0; 48 + } 49 + 50 + SEC("tp_btf/cgroup_mkdir") 51 + __failure __msg("Possibly NULL pointer passed to trusted arg0") 52 + int BPF_PROG(cgrp_kfunc_acquire_no_null_check, struct cgroup *cgrp, const char *path) 53 + { 54 + struct cgroup *acquired; 55 + 56 + acquired = bpf_cgroup_acquire(cgrp); 57 + /* 58 + * Can't invoke bpf_cgroup_release() without checking the return value 59 + * of bpf_cgroup_acquire(). 60 + */ 44 61 bpf_cgroup_release(acquired); 45 62 46 63 return 0; ··· 71 54 72 55 /* Can't invoke bpf_cgroup_acquire() on a random frame pointer. */ 73 56 acquired = bpf_cgroup_acquire((struct cgroup *)&stack_cgrp); 74 - bpf_cgroup_release(acquired); 57 + if (acquired) 58 + bpf_cgroup_release(acquired); 75 59 76 60 return 0; 77 61 } ··· 85 67 86 68 /* Can't acquire an untrusted struct cgroup * pointer. */ 87 69 acquired = bpf_cgroup_acquire(cgrp); 88 - bpf_cgroup_release(acquired); 70 + if (acquired) 71 + bpf_cgroup_release(acquired); 89 72 90 73 return 0; 91 74 } ··· 99 80 100 81 /* Can't invoke bpf_cgroup_acquire() on a pointer obtained from walking a trusted cgroup. */ 101 82 acquired = bpf_cgroup_acquire(cgrp->old_dom_cgrp); 102 - bpf_cgroup_release(acquired); 83 + if (acquired) 84 + bpf_cgroup_release(acquired); 103 85 104 86 return 0; 105 87 } ··· 113 93 114 94 /* Can't invoke bpf_cgroup_acquire() on a NULL pointer. */ 115 95 acquired = bpf_cgroup_acquire(NULL); 116 - if (!acquired) 117 - return 0; 118 - bpf_cgroup_release(acquired); 96 + if (acquired) 97 + bpf_cgroup_release(acquired); 119 98 120 99 return 0; 121 100 } ··· 156 137 struct cgroup *kptr, *acquired; 157 138 158 139 acquired = bpf_cgroup_acquire(cgrp); 140 + if (!acquired) 141 + return 0; 159 142 160 143 /* Cannot use bpf_cgroup_kptr_get() on a non-map-value, even if the kptr was acquired. */ 161 144 kptr = bpf_cgroup_kptr_get(&acquired); ··· 277 256 return -ENOENT; 278 257 279 258 acquired = bpf_cgroup_acquire(cgrp); 259 + if (!acquired) 260 + return -ENOENT; 280 261 281 262 old = bpf_kptr_xchg(&v->cgrp, acquired); 282 263
+4 -1
tools/testing/selftests/bpf/progs/cgrp_kfunc_success.c
··· 38 38 return 0; 39 39 40 40 acquired = bpf_cgroup_acquire(cgrp); 41 - bpf_cgroup_release(acquired); 41 + if (!acquired) 42 + err = 1; 43 + else 44 + bpf_cgroup_release(acquired); 42 45 43 46 return 0; 44 47 }