From: Daniel Borkmann <daniel@iogearbox.net>
To: alexei.starovoitov@gmail.com
Cc: netdev@vger.kernel.org, Daniel Borkmann <daniel@iogearbox.net>
Subject: [PATCH bpf-next v3 09/11] bpf: fix context access in tracing progs on 32 bit archs
Date: Sat, 2 Jun 2018 23:06:39 +0200 [thread overview]
Message-ID: <20180602210641.6163-10-daniel@iogearbox.net> (raw)
In-Reply-To: <20180602210641.6163-1-daniel@iogearbox.net>
Wang reported that all the testcases for BPF_PROG_TYPE_PERF_EVENT
program type in test_verifier report the following errors on x86_32:
172/p unpriv: spill/fill of different pointers ldx FAIL
Unexpected error message!
0: (bf) r6 = r10
1: (07) r6 += -8
2: (15) if r1 == 0x0 goto pc+3
R1=ctx(id=0,off=0,imm=0) R6=fp-8,call_-1 R10=fp0,call_-1
3: (bf) r2 = r10
4: (07) r2 += -76
5: (7b) *(u64 *)(r6 +0) = r2
6: (55) if r1 != 0x0 goto pc+1
R1=ctx(id=0,off=0,imm=0) R2=fp-76,call_-1 R6=fp-8,call_-1 R10=fp0,call_-1 fp-8=fp
7: (7b) *(u64 *)(r6 +0) = r1
8: (79) r1 = *(u64 *)(r6 +0)
9: (79) r1 = *(u64 *)(r1 +68)
invalid bpf_context access off=68 size=8
378/p check bpf_perf_event_data->sample_period byte load permitted FAIL
Failed to load prog 'Permission denied'!
0: (b7) r0 = 0
1: (71) r0 = *(u8 *)(r1 +68)
invalid bpf_context access off=68 size=1
379/p check bpf_perf_event_data->sample_period half load permitted FAIL
Failed to load prog 'Permission denied'!
0: (b7) r0 = 0
1: (69) r0 = *(u16 *)(r1 +68)
invalid bpf_context access off=68 size=2
380/p check bpf_perf_event_data->sample_period word load permitted FAIL
Failed to load prog 'Permission denied'!
0: (b7) r0 = 0
1: (61) r0 = *(u32 *)(r1 +68)
invalid bpf_context access off=68 size=4
381/p check bpf_perf_event_data->sample_period dword load permitted FAIL
Failed to load prog 'Permission denied'!
0: (b7) r0 = 0
1: (79) r0 = *(u64 *)(r1 +68)
invalid bpf_context access off=68 size=8
Reason is that struct pt_regs on x86_32 doesn't fully align to 8 byte
boundary due to its size of 68 bytes. Therefore, bpf_ctx_narrow_access_ok()
will then bail out saying that off & (size_default - 1) which is 68 & 7
doesn't cleanly align in the case of sample_period access from struct
bpf_perf_event_data, hence verifier wrongly thinks we might be doing an
unaligned access here though underlying arch can handle it just fine.
Therefore adjust this down to machine size and check and rewrite the
offset for narrow access on that basis. We also need to fix corresponding
pe_prog_is_valid_access(), since we hit the check for off % size != 0
(e.g. 68 % 8 -> 4) in the first and last test. With that in place, progs
for tracing work on x86_32.
Reported-by: Wang YanQing <udknight@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Wang YanQing <udknight@gmail.com>
---
include/linux/filter.h | 30 ++++++++++++++++++++++++------
kernel/bpf/verifier.c | 3 ++-
kernel/trace/bpf_trace.c | 10 ++++++++--
3 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 8e60f1e..45fc0f5 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -639,16 +639,34 @@ static inline bool bpf_prog_was_classic(const struct bpf_prog *prog)
return prog->type == BPF_PROG_TYPE_UNSPEC;
}
-static inline bool
-bpf_ctx_narrow_access_ok(u32 off, u32 size, const u32 size_default)
+static inline u32 bpf_ctx_off_adjust_machine(u32 size)
+{
+ const u32 size_machine = sizeof(unsigned long);
+
+ if (size > size_machine && size % size_machine == 0)
+ size = size_machine;
+
+ return size;
+}
+
+static inline bool bpf_ctx_narrow_align_ok(u32 off, u32 size_access,
+ u32 size_default)
{
- bool off_ok;
+ size_default = bpf_ctx_off_adjust_machine(size_default);
+ size_access = bpf_ctx_off_adjust_machine(size_access);
+
#ifdef __LITTLE_ENDIAN
- off_ok = (off & (size_default - 1)) == 0;
+ return (off & (size_default - 1)) == 0;
#else
- off_ok = (off & (size_default - 1)) + size == size_default;
+ return (off & (size_default - 1)) + size_access == size_default;
#endif
- return off_ok && size <= size_default && (size & (size - 1)) == 0;
+}
+
+static inline bool
+bpf_ctx_narrow_access_ok(u32 off, u32 size, u32 size_default)
+{
+ return bpf_ctx_narrow_align_ok(off, size, size_default) &&
+ size <= size_default && (size & (size - 1)) == 0;
}
#define bpf_classic_proglen(fprog) (fprog->len * sizeof(fprog->filter[0]))
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 5684b15..011def5 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -5349,6 +5349,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
*/
is_narrower_load = size < ctx_field_size;
if (is_narrower_load) {
+ u32 size_default = bpf_ctx_off_adjust_machine(ctx_field_size);
u32 off = insn->off;
u8 size_code;
@@ -5363,7 +5364,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
else if (ctx_field_size == 8)
size_code = BPF_DW;
- insn->off = off & ~(ctx_field_size - 1);
+ insn->off = off & ~(size_default - 1);
insn->code = BPF_LDX | BPF_MEM | size_code;
}
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index af1486d..752992c 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -880,8 +880,14 @@ static bool pe_prog_is_valid_access(int off, int size, enum bpf_access_type type
return false;
if (type != BPF_READ)
return false;
- if (off % size != 0)
- return false;
+ if (off % size != 0) {
+ if (sizeof(unsigned long) != 4)
+ return false;
+ if (size != 8)
+ return false;
+ if (off % size != 4)
+ return false;
+ }
switch (off) {
case bpf_ctx_range(struct bpf_perf_event_data, sample_period):
--
2.9.5
next prev parent reply other threads:[~2018-06-02 21:07 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-02 21:06 [PATCH bpf-next v3 00/11] Misc BPF improvements Daniel Borkmann
2018-06-02 21:06 ` [PATCH bpf-next v3 01/11] bpf: test case for map pointer poison with calls/branches Daniel Borkmann
2018-06-02 21:06 ` [PATCH bpf-next v3 02/11] bpf: add also cbpf long jump test cases with heavy expansion Daniel Borkmann
2018-06-02 21:06 ` [PATCH bpf-next v3 03/11] bpf: fixup error message from gpl helpers on license mismatch Daniel Borkmann
2018-06-02 21:06 ` [PATCH bpf-next v3 04/11] bpf: show prog and map id in fdinfo Daniel Borkmann
2018-06-02 21:06 ` [PATCH bpf-next v3 05/11] bpf: avoid retpoline for lookup/update/delete calls on maps Daniel Borkmann
2018-06-03 6:56 ` Jesper Dangaard Brouer
2018-06-03 16:11 ` Daniel Borkmann
2018-06-03 17:08 ` Jesper Dangaard Brouer
2018-06-04 11:02 ` Phil Sutter
2018-06-04 18:25 ` Jakub Kicinski
2018-06-04 19:45 ` Daniel Borkmann
2018-06-04 22:36 ` David Ahern
2018-06-02 21:06 ` [PATCH bpf-next v3 06/11] bpf: add bpf_skb_cgroup_id helper Daniel Borkmann
2018-06-02 21:06 ` [PATCH bpf-next v3 07/11] bpf: make sure to clear unused fields in tunnel/xfrm state fetch Daniel Borkmann
2018-06-02 21:06 ` [PATCH bpf-next v3 08/11] bpf: fix cbpf parser bug for octal numbers Daniel Borkmann
2018-06-02 21:06 ` Daniel Borkmann [this message]
2018-06-02 21:06 ` [PATCH bpf-next v3 10/11] bpf: sync bpf uapi header with tools Daniel Borkmann
2018-06-02 21:06 ` [PATCH bpf-next v3 11/11] bpf, doc: add missing patchwork url and libbpf to maintainers Daniel Borkmann
2018-06-03 15:08 ` [PATCH bpf-next v3 00/11] Misc BPF improvements Alexei Starovoitov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180602210641.6163-10-daniel@iogearbox.net \
--to=daniel@iogearbox.net \
--cc=alexei.starovoitov@gmail.com \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).