Skip to content

Commit 9ffd05d

Browse files
author
Alexei Starovoitov
committed
Merge branch 'improve-test-coverage-sparc'
David Miller says: ==================== On sparc64 a ton of test cases in test_verifier.c fail because the memory accesses in the test case are unaligned (or cannot be proven to be aligned by the verifier). Perhaps we can eventually try to (carefully) modify each test case which has this problem to not use unaligned accesses but: 1) That is delicate work. 2) The changes might not fully respect the original intention of the testcase. 3) In some cases, such a transformation might not even be feasible at all. So add an "any alignment" flag to tell the verifier to forcefully disable it's alignment checks completely. test_verifier.c is then annotated to use this flag when necessary. The presence of the flag in each test case is good documentation to anyone who wants to actually tackle the job of eliminating the unaligned memory accesses in the test cases. I've also seen several weird things in test cases, like trying to access __skb->mark in a packet buffer. This gets rid of 104 test_verifier.c failures on sparc64. Changes since v1: 1) Explain the new BPF_PROG_LOAD flag in easier to understand terms. Suggested by Alexei. 2) Make bpf_verify_program() just take a __u32 prog_flags instead of just accumulating boolean arguments over and over. Also suggested by Alexei. Changes since RFC: 1) Only the admin can allow the relaxation of alignment restrictions on inefficient unaligned access architectures. 2) Use F_NEEDS_EFFICIENT_UNALIGNED_ACCESS instead of making a new flag. 3) Annotate in the output, when we have a test case that the verifier accepted but we did not try to execute because we are on an inefficient unaligned access platform. Maybe with some arch machinery we can avoid this in the future. Signed-off-by: David S. Miller <davem@davemloft.net> ==================== Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2 parents 88945f4 + 0a68632 commit 9ffd05d

File tree

8 files changed

+128
-25
lines changed

8 files changed

+128
-25
lines changed

include/uapi/linux/bpf.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,20 @@ enum bpf_attach_type {
232232
*/
233233
#define BPF_F_STRICT_ALIGNMENT (1U << 0)
234234

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+
235249
/* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */
236250
#define BPF_PSEUDO_MAP_FD 1
237251

kernel/bpf/syscall.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1452,9 +1452,14 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
14521452
if (CHECK_ATTR(BPF_PROG_LOAD))
14531453
return -EINVAL;
14541454

1455-
if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT)
1455+
if (attr->prog_flags & ~(BPF_F_STRICT_ALIGNMENT | BPF_F_ANY_ALIGNMENT))
14561456
return -EINVAL;
14571457

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+
14581463
/* copy eBPF program license from user space */
14591464
if (strncpy_from_user(license, u64_to_user_ptr(attr->license),
14601465
sizeof(license) - 1) < 0)

kernel/bpf/verifier.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6505,6 +6505,8 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr,
65056505
env->strict_alignment = !!(attr->prog_flags & BPF_F_STRICT_ALIGNMENT);
65066506
if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
65076507
env->strict_alignment = true;
6508+
if (attr->prog_flags & BPF_F_ANY_ALIGNMENT)
6509+
env->strict_alignment = false;
65086510

65096511
ret = replace_map_fd_with_map_ptr(env);
65106512
if (ret < 0)

tools/include/uapi/linux/bpf.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,20 @@ enum bpf_attach_type {
232232
*/
233233
#define BPF_F_STRICT_ALIGNMENT (1U << 0)
234234

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+
235249
/* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */
236250
#define BPF_PSEUDO_MAP_FD 1
237251

tools/lib/bpf/bpf.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,9 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
279279
}
280280

281281
int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
282-
size_t insns_cnt, int strict_alignment,
283-
const char *license, __u32 kern_version,
284-
char *log_buf, size_t log_buf_sz, int log_level)
282+
size_t insns_cnt, __u32 prog_flags, const char *license,
283+
__u32 kern_version, char *log_buf, size_t log_buf_sz,
284+
int log_level)
285285
{
286286
union bpf_attr attr;
287287

@@ -295,7 +295,7 @@ int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
295295
attr.log_level = log_level;
296296
log_buf[0] = 0;
297297
attr.kern_version = kern_version;
298-
attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0;
298+
attr.prog_flags = prog_flags;
299299

300300
return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
301301
}

tools/lib/bpf/bpf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ LIBBPF_API int bpf_load_program(enum bpf_prog_type type,
9898
char *log_buf, size_t log_buf_sz);
9999
LIBBPF_API int bpf_verify_program(enum bpf_prog_type type,
100100
const struct bpf_insn *insns,
101-
size_t insns_cnt, int strict_alignment,
101+
size_t insns_cnt, __u32 prog_flags,
102102
const char *license, __u32 kern_version,
103103
char *log_buf, size_t log_buf_sz,
104104
int log_level);

tools/testing/selftests/bpf/test_align.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -620,8 +620,8 @@ static int do_test_single(struct bpf_align_test *test)
620620

621621
prog_len = probe_filter_length(prog);
622622
fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
623-
prog, prog_len, 1, "GPL", 0,
624-
bpf_vlog, sizeof(bpf_vlog), 2);
623+
prog, prog_len, BPF_F_STRICT_ALIGNMENT,
624+
"GPL", 0, bpf_vlog, sizeof(bpf_vlog), 2);
625625
if (fd_prog < 0 && test->result != REJECT) {
626626
printf("Failed to load program.\n");
627627
printf("%s", bpf_vlog);

0 commit comments

Comments
 (0)