diff options
-rw-r--r-- | include/uapi/linux/bpf.h | 14 | ||||
-rw-r--r-- | kernel/bpf/syscall.c | 7 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 2 | ||||
-rw-r--r-- | tools/include/uapi/linux/bpf.h | 14 | ||||
-rw-r--r-- | tools/lib/bpf/bpf.c | 8 | ||||
-rw-r--r-- | tools/lib/bpf/bpf.h | 2 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/test_align.c | 4 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/test_verifier.c | 3 |
8 files changed, 45 insertions, 9 deletions
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 597afdbc1ab9..8050caea7495 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h | |||
@@ -232,6 +232,20 @@ enum bpf_attach_type { | |||
232 | */ | 232 | */ |
233 | #define BPF_F_STRICT_ALIGNMENT (1U << 0) | 233 | #define BPF_F_STRICT_ALIGNMENT (1U << 0) |
234 | 234 | ||
235 | /* If BPF_F_ANY_ALIGNMENT is used in BPF_PROF_LOAD command, the | ||
236 | * verifier will allow any alignment whatsoever. On platforms | ||
237 | * with strict alignment requirements for loads ands stores (such | ||
238 | * as sparc and mips) the verifier validates that all loads and | ||
239 | * stores provably follow this requirement. This flag turns that | ||
240 | * checking and enforcement off. | ||
241 | * | ||
242 | * It is mostly used for testing when we want to validate the | ||
243 | * context and memory access aspects of the verifier, but because | ||
244 | * of an unaligned access the alignment check would trigger before | ||
245 | * the one we are interested in. | ||
246 | */ | ||
247 | #define BPF_F_ANY_ALIGNMENT (1U << 1) | ||
248 | |||
235 | /* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */ | 249 | /* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */ |
236 | #define BPF_PSEUDO_MAP_FD 1 | 250 | #define BPF_PSEUDO_MAP_FD 1 |
237 | 251 | ||
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 85cbeec06e50..f9554d9a14e1 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
@@ -1452,9 +1452,14 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr) | |||
1452 | if (CHECK_ATTR(BPF_PROG_LOAD)) | 1452 | if (CHECK_ATTR(BPF_PROG_LOAD)) |
1453 | return -EINVAL; | 1453 | return -EINVAL; |
1454 | 1454 | ||
1455 | if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT) | 1455 | if (attr->prog_flags & ~(BPF_F_STRICT_ALIGNMENT | BPF_F_ANY_ALIGNMENT)) |
1456 | return -EINVAL; | 1456 | return -EINVAL; |
1457 | 1457 | ||
1458 | if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && | ||
1459 | (attr->prog_flags & BPF_F_ANY_ALIGNMENT) && | ||
1460 | !capable(CAP_SYS_ADMIN)) | ||
1461 | return -EPERM; | ||
1462 | |||
1458 | /* copy eBPF program license from user space */ | 1463 | /* copy eBPF program license from user space */ |
1459 | if (strncpy_from_user(license, u64_to_user_ptr(attr->license), | 1464 | if (strncpy_from_user(license, u64_to_user_ptr(attr->license), |
1460 | sizeof(license) - 1) < 0) | 1465 | sizeof(license) - 1) < 0) |
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 9584438fa2cc..71988337ac14 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
@@ -6505,6 +6505,8 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, | |||
6505 | env->strict_alignment = !!(attr->prog_flags & BPF_F_STRICT_ALIGNMENT); | 6505 | env->strict_alignment = !!(attr->prog_flags & BPF_F_STRICT_ALIGNMENT); |
6506 | if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) | 6506 | if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) |
6507 | env->strict_alignment = true; | 6507 | env->strict_alignment = true; |
6508 | if (attr->prog_flags & BPF_F_ANY_ALIGNMENT) | ||
6509 | env->strict_alignment = false; | ||
6508 | 6510 | ||
6509 | ret = replace_map_fd_with_map_ptr(env); | 6511 | ret = replace_map_fd_with_map_ptr(env); |
6510 | if (ret < 0) | 6512 | if (ret < 0) |
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 597afdbc1ab9..8050caea7495 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h | |||
@@ -232,6 +232,20 @@ enum bpf_attach_type { | |||
232 | */ | 232 | */ |
233 | #define BPF_F_STRICT_ALIGNMENT (1U << 0) | 233 | #define BPF_F_STRICT_ALIGNMENT (1U << 0) |
234 | 234 | ||
235 | /* If BPF_F_ANY_ALIGNMENT is used in BPF_PROF_LOAD command, the | ||
236 | * verifier will allow any alignment whatsoever. On platforms | ||
237 | * with strict alignment requirements for loads ands stores (such | ||
238 | * as sparc and mips) the verifier validates that all loads and | ||
239 | * stores provably follow this requirement. This flag turns that | ||
240 | * checking and enforcement off. | ||
241 | * | ||
242 | * It is mostly used for testing when we want to validate the | ||
243 | * context and memory access aspects of the verifier, but because | ||
244 | * of an unaligned access the alignment check would trigger before | ||
245 | * the one we are interested in. | ||
246 | */ | ||
247 | #define BPF_F_ANY_ALIGNMENT (1U << 1) | ||
248 | |||
235 | /* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */ | 249 | /* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */ |
236 | #define BPF_PSEUDO_MAP_FD 1 | 250 | #define BPF_PSEUDO_MAP_FD 1 |
237 | 251 | ||
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index ce1822194590..c19226cccf39 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c | |||
@@ -279,9 +279,9 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, | |||
279 | } | 279 | } |
280 | 280 | ||
281 | int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, | 281 | int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, |
282 | size_t insns_cnt, int strict_alignment, | 282 | size_t insns_cnt, __u32 prog_flags, const char *license, |
283 | const char *license, __u32 kern_version, | 283 | __u32 kern_version, char *log_buf, size_t log_buf_sz, |
284 | char *log_buf, size_t log_buf_sz, int log_level) | 284 | int log_level) |
285 | { | 285 | { |
286 | union bpf_attr attr; | 286 | union bpf_attr attr; |
287 | 287 | ||
@@ -295,7 +295,7 @@ int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, | |||
295 | attr.log_level = log_level; | 295 | attr.log_level = log_level; |
296 | log_buf[0] = 0; | 296 | log_buf[0] = 0; |
297 | attr.kern_version = kern_version; | 297 | attr.kern_version = kern_version; |
298 | attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0; | 298 | attr.prog_flags = prog_flags; |
299 | 299 | ||
300 | return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); | 300 | return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); |
301 | } | 301 | } |
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index 09e8bbe111d4..60392b70587c 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h | |||
@@ -98,7 +98,7 @@ LIBBPF_API int bpf_load_program(enum bpf_prog_type type, | |||
98 | char *log_buf, size_t log_buf_sz); | 98 | char *log_buf, size_t log_buf_sz); |
99 | LIBBPF_API int bpf_verify_program(enum bpf_prog_type type, | 99 | LIBBPF_API int bpf_verify_program(enum bpf_prog_type type, |
100 | const struct bpf_insn *insns, | 100 | const struct bpf_insn *insns, |
101 | size_t insns_cnt, int strict_alignment, | 101 | size_t insns_cnt, __u32 prog_flags, |
102 | const char *license, __u32 kern_version, | 102 | const char *license, __u32 kern_version, |
103 | char *log_buf, size_t log_buf_sz, | 103 | char *log_buf, size_t log_buf_sz, |
104 | int log_level); | 104 | int log_level); |
diff --git a/tools/testing/selftests/bpf/test_align.c b/tools/testing/selftests/bpf/test_align.c index 5f377ec53f2f..3c789d03b629 100644 --- a/tools/testing/selftests/bpf/test_align.c +++ b/tools/testing/selftests/bpf/test_align.c | |||
@@ -620,8 +620,8 @@ static int do_test_single(struct bpf_align_test *test) | |||
620 | 620 | ||
621 | prog_len = probe_filter_length(prog); | 621 | prog_len = probe_filter_length(prog); |
622 | fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, | 622 | fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, |
623 | prog, prog_len, 1, "GPL", 0, | 623 | prog, prog_len, BPF_F_STRICT_ALIGNMENT, |
624 | bpf_vlog, sizeof(bpf_vlog), 2); | 624 | "GPL", 0, bpf_vlog, sizeof(bpf_vlog), 2); |
625 | if (fd_prog < 0 && test->result != REJECT) { | 625 | if (fd_prog < 0 && test->result != REJECT) { |
626 | printf("Failed to load program.\n"); | 626 | printf("Failed to load program.\n"); |
627 | printf("%s", bpf_vlog); | 627 | printf("%s", bpf_vlog); |
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index 5eace1f606fb..78e779c35869 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c | |||
@@ -14275,7 +14275,8 @@ static void do_test_single(struct bpf_test *test, bool unpriv, | |||
14275 | prog_len = probe_filter_length(prog); | 14275 | prog_len = probe_filter_length(prog); |
14276 | 14276 | ||
14277 | fd_prog = bpf_verify_program(prog_type, prog, prog_len, | 14277 | fd_prog = bpf_verify_program(prog_type, prog, prog_len, |
14278 | test->flags & F_LOAD_WITH_STRICT_ALIGNMENT, | 14278 | test->flags & F_LOAD_WITH_STRICT_ALIGNMENT ? |
14279 | BPF_F_STRICT_ALIGNMENT : 0, | ||
14279 | "GPL", 0, bpf_vlog, sizeof(bpf_vlog), 1); | 14280 | "GPL", 0, bpf_vlog, sizeof(bpf_vlog), 1); |
14280 | 14281 | ||
14281 | expected_ret = unpriv && test->result_unpriv != UNDEF ? | 14282 | expected_ret = unpriv && test->result_unpriv != UNDEF ? |