aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf/syscall.c
diff options
context:
space:
mode:
authorAndrey Ignatov <rdna@fb.com>2018-03-30 18:08:00 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2018-03-30 20:14:44 -0400
commit5e43f899b03a3492ce5fc44e8900becb04dae9c0 (patch)
tree2811b77402c54e99a10a74f8a1b092b4bc2e24f6 /kernel/bpf/syscall.c
parent807ae7daf5fb9ba9ef688344ae7c0d8cbebd211c (diff)
bpf: Check attach type at prog load time
== The problem == There are use-cases when a program of some type can be attached to multiple attach points and those attach points must have different permissions to access context or to call helpers. E.g. context structure may have fields for both IPv4 and IPv6 but it doesn't make sense to read from / write to IPv6 field when attach point is somewhere in IPv4 stack. Same applies to BPF-helpers: it may make sense to call some helper from some attach point, but not from other for same prog type. == The solution == Introduce `expected_attach_type` field in in `struct bpf_attr` for `BPF_PROG_LOAD` command. If scenario described in "The problem" section is the case for some prog type, the field will be checked twice: 1) At load time prog type is checked to see if attach type for it must be known to validate program permissions correctly. Prog will be rejected with EINVAL if it's the case and `expected_attach_type` is not specified or has invalid value. 2) At attach time `attach_type` is compared with `expected_attach_type`, if prog type requires to have one, and, if they differ, attach will be rejected with EINVAL. The `expected_attach_type` is now available as part of `struct bpf_prog` in both `bpf_verifier_ops->is_valid_access()` and `bpf_verifier_ops->get_func_proto()` () and can be used to check context accesses and calls to helpers correspondingly. Initially the idea was discussed by Alexei Starovoitov <ast@fb.com> and Daniel Borkmann <daniel@iogearbox.net> here: https://marc.info/?l=linux-netdev&m=152107378717201&w=2 Signed-off-by: Andrey Ignatov <rdna@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r--kernel/bpf/syscall.c31
1 files changed, 30 insertions, 1 deletions
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}
1172EXPORT_SYMBOL_GPL(bpf_prog_get_type_dev); 1172EXPORT_SYMBOL_GPL(bpf_prog_get_type_dev);
1173 1173
1174static int
1175bpf_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
1184static 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
1177static int bpf_prog_load(union bpf_attr *attr) 1196static 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);