diff options
Diffstat (limited to 'kernel/bpf')
-rw-r--r-- | kernel/bpf/cgroup.c | 3 | ||||
-rw-r--r-- | kernel/bpf/syscall.c | 31 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 6 |
3 files changed, 35 insertions, 5 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 | */ |