diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/bpf/cgroup.c | 3 | ||||
-rw-r--r-- | kernel/bpf/syscall.c | 31 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 6 | ||||
-rw-r--r-- | kernel/trace/bpf_trace.c | 27 |
4 files changed, 53 insertions, 14 deletions
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index c1c0b60d3f2f..8730b24ed540 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c | |||
@@ -545,7 +545,7 @@ int __cgroup_bpf_check_dev_permission(short dev_type, u32 major, u32 minor, | |||
545 | EXPORT_SYMBOL(__cgroup_bpf_check_dev_permission); | 545 | EXPORT_SYMBOL(__cgroup_bpf_check_dev_permission); |
546 | 546 | ||
547 | static const struct bpf_func_proto * | 547 | static const struct bpf_func_proto * |
548 | cgroup_dev_func_proto(enum bpf_func_id func_id) | 548 | cgroup_dev_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) |
549 | { | 549 | { |
550 | switch (func_id) { | 550 | switch (func_id) { |
551 | case BPF_FUNC_map_lookup_elem: | 551 | case BPF_FUNC_map_lookup_elem: |
@@ -566,6 +566,7 @@ cgroup_dev_func_proto(enum bpf_func_id func_id) | |||
566 | 566 | ||
567 | static bool cgroup_dev_is_valid_access(int off, int size, | 567 | static bool cgroup_dev_is_valid_access(int off, int size, |
568 | enum bpf_access_type type, | 568 | enum bpf_access_type type, |
569 | const struct bpf_prog *prog, | ||
569 | struct bpf_insn_access_aux *info) | 570 | struct bpf_insn_access_aux *info) |
570 | { | 571 | { |
571 | const int size_default = sizeof(__u32); | 572 | const int size_default = sizeof(__u32); |
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 95ca2523fa6e..9d3b572d4dec 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
@@ -1171,8 +1171,27 @@ struct bpf_prog *bpf_prog_get_type_dev(u32 ufd, enum bpf_prog_type type, | |||
1171 | } | 1171 | } |
1172 | EXPORT_SYMBOL_GPL(bpf_prog_get_type_dev); | 1172 | EXPORT_SYMBOL_GPL(bpf_prog_get_type_dev); |
1173 | 1173 | ||
1174 | static int | ||
1175 | bpf_prog_load_check_attach_type(enum bpf_prog_type prog_type, | ||
1176 | enum bpf_attach_type expected_attach_type) | ||
1177 | { | ||
1178 | /* There are currently no prog types that require specifying | ||
1179 | * attach_type at load time. | ||
1180 | */ | ||
1181 | return 0; | ||
1182 | } | ||
1183 | |||
1184 | static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog, | ||
1185 | enum bpf_attach_type attach_type) | ||
1186 | { | ||
1187 | /* There are currently no prog types that require specifying | ||
1188 | * attach_type at load time. | ||
1189 | */ | ||
1190 | return 0; | ||
1191 | } | ||
1192 | |||
1174 | /* last field in 'union bpf_attr' used by this command */ | 1193 | /* last field in 'union bpf_attr' used by this command */ |
1175 | #define BPF_PROG_LOAD_LAST_FIELD prog_ifindex | 1194 | #define BPF_PROG_LOAD_LAST_FIELD expected_attach_type |
1176 | 1195 | ||
1177 | static int bpf_prog_load(union bpf_attr *attr) | 1196 | static int bpf_prog_load(union bpf_attr *attr) |
1178 | { | 1197 | { |
@@ -1209,11 +1228,16 @@ static int bpf_prog_load(union bpf_attr *attr) | |||
1209 | !capable(CAP_SYS_ADMIN)) | 1228 | !capable(CAP_SYS_ADMIN)) |
1210 | return -EPERM; | 1229 | return -EPERM; |
1211 | 1230 | ||
1231 | if (bpf_prog_load_check_attach_type(type, attr->expected_attach_type)) | ||
1232 | return -EINVAL; | ||
1233 | |||
1212 | /* plain bpf_prog allocation */ | 1234 | /* plain bpf_prog allocation */ |
1213 | prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER); | 1235 | prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER); |
1214 | if (!prog) | 1236 | if (!prog) |
1215 | return -ENOMEM; | 1237 | return -ENOMEM; |
1216 | 1238 | ||
1239 | prog->expected_attach_type = attr->expected_attach_type; | ||
1240 | |||
1217 | prog->aux->offload_requested = !!attr->prog_ifindex; | 1241 | prog->aux->offload_requested = !!attr->prog_ifindex; |
1218 | 1242 | ||
1219 | err = security_bpf_prog_alloc(prog->aux); | 1243 | err = security_bpf_prog_alloc(prog->aux); |
@@ -1474,6 +1498,11 @@ static int bpf_prog_attach(const union bpf_attr *attr) | |||
1474 | if (IS_ERR(prog)) | 1498 | if (IS_ERR(prog)) |
1475 | return PTR_ERR(prog); | 1499 | return PTR_ERR(prog); |
1476 | 1500 | ||
1501 | if (bpf_prog_attach_check_attach_type(prog, attr->attach_type)) { | ||
1502 | bpf_prog_put(prog); | ||
1503 | return -EINVAL; | ||
1504 | } | ||
1505 | |||
1477 | cgrp = cgroup_get_from_fd(attr->target_fd); | 1506 | cgrp = cgroup_get_from_fd(attr->target_fd); |
1478 | if (IS_ERR(cgrp)) { | 1507 | if (IS_ERR(cgrp)) { |
1479 | bpf_prog_put(prog); | 1508 | bpf_prog_put(prog); |
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 8acd2207e412..10024323031d 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
@@ -1323,7 +1323,7 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, | |||
1323 | }; | 1323 | }; |
1324 | 1324 | ||
1325 | if (env->ops->is_valid_access && | 1325 | if (env->ops->is_valid_access && |
1326 | env->ops->is_valid_access(off, size, t, &info)) { | 1326 | env->ops->is_valid_access(off, size, t, env->prog, &info)) { |
1327 | /* A non zero info.ctx_field_size indicates that this field is a | 1327 | /* A non zero info.ctx_field_size indicates that this field is a |
1328 | * candidate for later verifier transformation to load the whole | 1328 | * candidate for later verifier transformation to load the whole |
1329 | * field and then apply a mask when accessed with a narrower | 1329 | * field and then apply a mask when accessed with a narrower |
@@ -2349,7 +2349,7 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn | |||
2349 | } | 2349 | } |
2350 | 2350 | ||
2351 | if (env->ops->get_func_proto) | 2351 | if (env->ops->get_func_proto) |
2352 | fn = env->ops->get_func_proto(func_id); | 2352 | fn = env->ops->get_func_proto(func_id, env->prog); |
2353 | if (!fn) { | 2353 | if (!fn) { |
2354 | verbose(env, "unknown func %s#%d\n", func_id_name(func_id), | 2354 | verbose(env, "unknown func %s#%d\n", func_id_name(func_id), |
2355 | func_id); | 2355 | func_id); |
@@ -5572,7 +5572,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) | |||
5572 | insn = new_prog->insnsi + i + delta; | 5572 | insn = new_prog->insnsi + i + delta; |
5573 | } | 5573 | } |
5574 | patch_call_imm: | 5574 | patch_call_imm: |
5575 | fn = env->ops->get_func_proto(insn->imm); | 5575 | fn = env->ops->get_func_proto(insn->imm, env->prog); |
5576 | /* all functions that have prototype and verifier allowed | 5576 | /* all functions that have prototype and verifier allowed |
5577 | * programs to call them, must be real in-kernel functions | 5577 | * programs to call them, must be real in-kernel functions |
5578 | */ | 5578 | */ |
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 463e72d18c4c..d88e96d4e12c 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c | |||
@@ -524,7 +524,8 @@ static const struct bpf_func_proto bpf_probe_read_str_proto = { | |||
524 | .arg3_type = ARG_ANYTHING, | 524 | .arg3_type = ARG_ANYTHING, |
525 | }; | 525 | }; |
526 | 526 | ||
527 | static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id) | 527 | static const struct bpf_func_proto * |
528 | tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) | ||
528 | { | 529 | { |
529 | switch (func_id) { | 530 | switch (func_id) { |
530 | case BPF_FUNC_map_lookup_elem: | 531 | case BPF_FUNC_map_lookup_elem: |
@@ -568,7 +569,8 @@ static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id) | |||
568 | } | 569 | } |
569 | } | 570 | } |
570 | 571 | ||
571 | static const struct bpf_func_proto *kprobe_prog_func_proto(enum bpf_func_id func_id) | 572 | static const struct bpf_func_proto * |
573 | kprobe_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) | ||
572 | { | 574 | { |
573 | switch (func_id) { | 575 | switch (func_id) { |
574 | case BPF_FUNC_perf_event_output: | 576 | case BPF_FUNC_perf_event_output: |
@@ -582,12 +584,13 @@ static const struct bpf_func_proto *kprobe_prog_func_proto(enum bpf_func_id func | |||
582 | return &bpf_override_return_proto; | 584 | return &bpf_override_return_proto; |
583 | #endif | 585 | #endif |
584 | default: | 586 | default: |
585 | return tracing_func_proto(func_id); | 587 | return tracing_func_proto(func_id, prog); |
586 | } | 588 | } |
587 | } | 589 | } |
588 | 590 | ||
589 | /* bpf+kprobe programs can access fields of 'struct pt_regs' */ | 591 | /* bpf+kprobe programs can access fields of 'struct pt_regs' */ |
590 | static bool kprobe_prog_is_valid_access(int off, int size, enum bpf_access_type type, | 592 | static bool kprobe_prog_is_valid_access(int off, int size, enum bpf_access_type type, |
593 | const struct bpf_prog *prog, | ||
591 | struct bpf_insn_access_aux *info) | 594 | struct bpf_insn_access_aux *info) |
592 | { | 595 | { |
593 | if (off < 0 || off >= sizeof(struct pt_regs)) | 596 | if (off < 0 || off >= sizeof(struct pt_regs)) |
@@ -661,7 +664,8 @@ static const struct bpf_func_proto bpf_get_stackid_proto_tp = { | |||
661 | .arg3_type = ARG_ANYTHING, | 664 | .arg3_type = ARG_ANYTHING, |
662 | }; | 665 | }; |
663 | 666 | ||
664 | static const struct bpf_func_proto *tp_prog_func_proto(enum bpf_func_id func_id) | 667 | static const struct bpf_func_proto * |
668 | tp_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) | ||
665 | { | 669 | { |
666 | switch (func_id) { | 670 | switch (func_id) { |
667 | case BPF_FUNC_perf_event_output: | 671 | case BPF_FUNC_perf_event_output: |
@@ -669,11 +673,12 @@ static const struct bpf_func_proto *tp_prog_func_proto(enum bpf_func_id func_id) | |||
669 | case BPF_FUNC_get_stackid: | 673 | case BPF_FUNC_get_stackid: |
670 | return &bpf_get_stackid_proto_tp; | 674 | return &bpf_get_stackid_proto_tp; |
671 | default: | 675 | default: |
672 | return tracing_func_proto(func_id); | 676 | return tracing_func_proto(func_id, prog); |
673 | } | 677 | } |
674 | } | 678 | } |
675 | 679 | ||
676 | static bool tp_prog_is_valid_access(int off, int size, enum bpf_access_type type, | 680 | static bool tp_prog_is_valid_access(int off, int size, enum bpf_access_type type, |
681 | const struct bpf_prog *prog, | ||
677 | struct bpf_insn_access_aux *info) | 682 | struct bpf_insn_access_aux *info) |
678 | { | 683 | { |
679 | if (off < sizeof(void *) || off >= PERF_MAX_TRACE_SIZE) | 684 | if (off < sizeof(void *) || off >= PERF_MAX_TRACE_SIZE) |
@@ -721,7 +726,8 @@ static const struct bpf_func_proto bpf_perf_prog_read_value_proto = { | |||
721 | .arg3_type = ARG_CONST_SIZE, | 726 | .arg3_type = ARG_CONST_SIZE, |
722 | }; | 727 | }; |
723 | 728 | ||
724 | static const struct bpf_func_proto *pe_prog_func_proto(enum bpf_func_id func_id) | 729 | static const struct bpf_func_proto * |
730 | pe_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) | ||
725 | { | 731 | { |
726 | switch (func_id) { | 732 | switch (func_id) { |
727 | case BPF_FUNC_perf_event_output: | 733 | case BPF_FUNC_perf_event_output: |
@@ -731,7 +737,7 @@ static const struct bpf_func_proto *pe_prog_func_proto(enum bpf_func_id func_id) | |||
731 | case BPF_FUNC_perf_prog_read_value: | 737 | case BPF_FUNC_perf_prog_read_value: |
732 | return &bpf_perf_prog_read_value_proto; | 738 | return &bpf_perf_prog_read_value_proto; |
733 | default: | 739 | default: |
734 | return tracing_func_proto(func_id); | 740 | return tracing_func_proto(func_id, prog); |
735 | } | 741 | } |
736 | } | 742 | } |
737 | 743 | ||
@@ -781,7 +787,8 @@ static const struct bpf_func_proto bpf_get_stackid_proto_raw_tp = { | |||
781 | .arg3_type = ARG_ANYTHING, | 787 | .arg3_type = ARG_ANYTHING, |
782 | }; | 788 | }; |
783 | 789 | ||
784 | static const struct bpf_func_proto *raw_tp_prog_func_proto(enum bpf_func_id func_id) | 790 | static const struct bpf_func_proto * |
791 | raw_tp_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) | ||
785 | { | 792 | { |
786 | switch (func_id) { | 793 | switch (func_id) { |
787 | case BPF_FUNC_perf_event_output: | 794 | case BPF_FUNC_perf_event_output: |
@@ -789,12 +796,13 @@ static const struct bpf_func_proto *raw_tp_prog_func_proto(enum bpf_func_id func | |||
789 | case BPF_FUNC_get_stackid: | 796 | case BPF_FUNC_get_stackid: |
790 | return &bpf_get_stackid_proto_raw_tp; | 797 | return &bpf_get_stackid_proto_raw_tp; |
791 | default: | 798 | default: |
792 | return tracing_func_proto(func_id); | 799 | return tracing_func_proto(func_id, prog); |
793 | } | 800 | } |
794 | } | 801 | } |
795 | 802 | ||
796 | static bool raw_tp_prog_is_valid_access(int off, int size, | 803 | static bool raw_tp_prog_is_valid_access(int off, int size, |
797 | enum bpf_access_type type, | 804 | enum bpf_access_type type, |
805 | const struct bpf_prog *prog, | ||
798 | struct bpf_insn_access_aux *info) | 806 | struct bpf_insn_access_aux *info) |
799 | { | 807 | { |
800 | /* largest tracepoint in the kernel has 12 args */ | 808 | /* largest tracepoint in the kernel has 12 args */ |
@@ -816,6 +824,7 @@ const struct bpf_prog_ops raw_tracepoint_prog_ops = { | |||
816 | }; | 824 | }; |
817 | 825 | ||
818 | static bool pe_prog_is_valid_access(int off, int size, enum bpf_access_type type, | 826 | static bool pe_prog_is_valid_access(int off, int size, enum bpf_access_type type, |
827 | const struct bpf_prog *prog, | ||
819 | struct bpf_insn_access_aux *info) | 828 | struct bpf_insn_access_aux *info) |
820 | { | 829 | { |
821 | const int size_u64 = sizeof(u64); | 830 | const int size_u64 = sizeof(u64); |