aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf/syscall.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r--kernel/bpf/syscall.c33
1 files changed, 8 insertions, 25 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 998377808102..85cbeec06e50 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1214,6 +1214,7 @@ static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
1214 bpf_prog_free_id(prog, do_idr_lock); 1214 bpf_prog_free_id(prog, do_idr_lock);
1215 bpf_prog_kallsyms_del_all(prog); 1215 bpf_prog_kallsyms_del_all(prog);
1216 btf_put(prog->aux->btf); 1216 btf_put(prog->aux->btf);
1217 kvfree(prog->aux->func_info);
1217 1218
1218 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu); 1219 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
1219 } 1220 }
@@ -2219,46 +2220,28 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
2219 } 2220 }
2220 2221
2221 if (prog->aux->btf) { 2222 if (prog->aux->btf) {
2223 u32 krec_size = sizeof(struct bpf_func_info);
2222 u32 ucnt, urec_size; 2224 u32 ucnt, urec_size;
2223 2225
2224 info.btf_id = btf_id(prog->aux->btf); 2226 info.btf_id = btf_id(prog->aux->btf);
2225 2227
2226 ucnt = info.func_info_cnt; 2228 ucnt = info.func_info_cnt;
2227 info.func_info_cnt = prog->aux->func_cnt ? : 1; 2229 info.func_info_cnt = prog->aux->func_info_cnt;
2228 urec_size = info.func_info_rec_size; 2230 urec_size = info.func_info_rec_size;
2229 info.func_info_rec_size = sizeof(struct bpf_func_info); 2231 info.func_info_rec_size = krec_size;
2230 if (ucnt) { 2232 if (ucnt) {
2231 /* expect passed-in urec_size is what the kernel expects */ 2233 /* expect passed-in urec_size is what the kernel expects */
2232 if (urec_size != info.func_info_rec_size) 2234 if (urec_size != info.func_info_rec_size)
2233 return -EINVAL; 2235 return -EINVAL;
2234 2236
2235 if (bpf_dump_raw_ok()) { 2237 if (bpf_dump_raw_ok()) {
2236 struct bpf_func_info kern_finfo;
2237 char __user *user_finfo; 2238 char __user *user_finfo;
2238 u32 i, insn_offset;
2239 2239
2240 user_finfo = u64_to_user_ptr(info.func_info); 2240 user_finfo = u64_to_user_ptr(info.func_info);
2241 if (prog->aux->func_cnt) { 2241 ucnt = min_t(u32, info.func_info_cnt, ucnt);
2242 ucnt = min_t(u32, info.func_info_cnt, ucnt); 2242 if (copy_to_user(user_finfo, prog->aux->func_info,
2243 insn_offset = 0; 2243 krec_size * ucnt))
2244 for (i = 0; i < ucnt; i++) { 2244 return -EFAULT;
2245 kern_finfo.insn_offset = insn_offset;
2246 kern_finfo.type_id = prog->aux->func[i]->aux->type_id;
2247 if (copy_to_user(user_finfo, &kern_finfo,
2248 sizeof(kern_finfo)))
2249 return -EFAULT;
2250
2251 /* func[i]->len holds the prog len */
2252 insn_offset += prog->aux->func[i]->len;
2253 user_finfo += urec_size;
2254 }
2255 } else {
2256 kern_finfo.insn_offset = 0;
2257 kern_finfo.type_id = prog->aux->type_id;
2258 if (copy_to_user(user_finfo, &kern_finfo,
2259 sizeof(kern_finfo)))
2260 return -EFAULT;
2261 }
2262 } else { 2245 } else {
2263 info.func_info_cnt = 0; 2246 info.func_info_cnt = 0;
2264 } 2247 }