diff options
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r-- | kernel/bpf/syscall.c | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index cf5040fd5434..998377808102 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
@@ -1213,6 +1213,7 @@ static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock) | |||
1213 | /* bpf_prog_free_id() must be called first */ | 1213 | /* bpf_prog_free_id() must be called first */ |
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 | 1217 | ||
1217 | call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu); | 1218 | call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu); |
1218 | } | 1219 | } |
@@ -1437,9 +1438,9 @@ bpf_prog_load_check_attach_type(enum bpf_prog_type prog_type, | |||
1437 | } | 1438 | } |
1438 | 1439 | ||
1439 | /* last field in 'union bpf_attr' used by this command */ | 1440 | /* last field in 'union bpf_attr' used by this command */ |
1440 | #define BPF_PROG_LOAD_LAST_FIELD expected_attach_type | 1441 | #define BPF_PROG_LOAD_LAST_FIELD func_info_cnt |
1441 | 1442 | ||
1442 | static int bpf_prog_load(union bpf_attr *attr) | 1443 | static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr) |
1443 | { | 1444 | { |
1444 | enum bpf_prog_type type = attr->prog_type; | 1445 | enum bpf_prog_type type = attr->prog_type; |
1445 | struct bpf_prog *prog; | 1446 | struct bpf_prog *prog; |
@@ -1525,7 +1526,7 @@ static int bpf_prog_load(union bpf_attr *attr) | |||
1525 | goto free_prog; | 1526 | goto free_prog; |
1526 | 1527 | ||
1527 | /* run eBPF verifier */ | 1528 | /* run eBPF verifier */ |
1528 | err = bpf_check(&prog, attr); | 1529 | err = bpf_check(&prog, attr, uattr); |
1529 | if (err < 0) | 1530 | if (err < 0) |
1530 | goto free_used_maps; | 1531 | goto free_used_maps; |
1531 | 1532 | ||
@@ -2079,6 +2080,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, | |||
2079 | info.xlated_prog_len = 0; | 2080 | info.xlated_prog_len = 0; |
2080 | info.nr_jited_ksyms = 0; | 2081 | info.nr_jited_ksyms = 0; |
2081 | info.nr_jited_func_lens = 0; | 2082 | info.nr_jited_func_lens = 0; |
2083 | info.func_info_cnt = 0; | ||
2082 | goto done; | 2084 | goto done; |
2083 | } | 2085 | } |
2084 | 2086 | ||
@@ -2216,6 +2218,55 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, | |||
2216 | } | 2218 | } |
2217 | } | 2219 | } |
2218 | 2220 | ||
2221 | if (prog->aux->btf) { | ||
2222 | u32 ucnt, urec_size; | ||
2223 | |||
2224 | info.btf_id = btf_id(prog->aux->btf); | ||
2225 | |||
2226 | ucnt = info.func_info_cnt; | ||
2227 | info.func_info_cnt = prog->aux->func_cnt ? : 1; | ||
2228 | urec_size = info.func_info_rec_size; | ||
2229 | info.func_info_rec_size = sizeof(struct bpf_func_info); | ||
2230 | if (ucnt) { | ||
2231 | /* expect passed-in urec_size is what the kernel expects */ | ||
2232 | if (urec_size != info.func_info_rec_size) | ||
2233 | return -EINVAL; | ||
2234 | |||
2235 | if (bpf_dump_raw_ok()) { | ||
2236 | struct bpf_func_info kern_finfo; | ||
2237 | char __user *user_finfo; | ||
2238 | u32 i, insn_offset; | ||
2239 | |||
2240 | user_finfo = u64_to_user_ptr(info.func_info); | ||
2241 | if (prog->aux->func_cnt) { | ||
2242 | ucnt = min_t(u32, info.func_info_cnt, ucnt); | ||
2243 | insn_offset = 0; | ||
2244 | for (i = 0; i < ucnt; i++) { | ||
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 { | ||
2263 | info.func_info_cnt = 0; | ||
2264 | } | ||
2265 | } | ||
2266 | } else { | ||
2267 | info.func_info_cnt = 0; | ||
2268 | } | ||
2269 | |||
2219 | done: | 2270 | done: |
2220 | if (copy_to_user(uinfo, &info, info_len) || | 2271 | if (copy_to_user(uinfo, &info, info_len) || |
2221 | put_user(info_len, &uattr->info.info_len)) | 2272 | put_user(info_len, &uattr->info.info_len)) |
@@ -2501,7 +2552,7 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz | |||
2501 | err = map_get_next_key(&attr); | 2552 | err = map_get_next_key(&attr); |
2502 | break; | 2553 | break; |
2503 | case BPF_PROG_LOAD: | 2554 | case BPF_PROG_LOAD: |
2504 | err = bpf_prog_load(&attr); | 2555 | err = bpf_prog_load(&attr, uattr); |
2505 | break; | 2556 | break; |
2506 | case BPF_OBJ_PIN: | 2557 | case BPF_OBJ_PIN: |
2507 | err = bpf_obj_pin(&attr); | 2558 | err = bpf_obj_pin(&attr); |