aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/bpf.h14
-rw-r--r--kernel/bpf/syscall.c7
-rw-r--r--kernel/bpf/verifier.c2
-rw-r--r--tools/include/uapi/linux/bpf.h14
-rw-r--r--tools/lib/bpf/bpf.c8
-rw-r--r--tools/lib/bpf/bpf.h2
-rw-r--r--tools/testing/selftests/bpf/test_align.c4
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c3
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
281int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, 281int 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);
99LIBBPF_API int bpf_verify_program(enum bpf_prog_type type, 99LIBBPF_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 ?