From: Alexei Starovoitov <alexei.starovoitov@gmail.com>
To: Pablo Neira Ayuso <pablo@netfilter.org>
Cc: Florian Westphal <fw@strlen.de>,
jannh@google.com, David Miller <davem@davemloft.net>,
phil@nwl.cc, laforge@gnumonks.org, daniel@iogearbox.net,
netdev@vger.kernel.org, netfilter-devel@vger.kernel.org
Subject: Re: nft/bpf interpreters and spectre2. Was: [PATCH RFC 0/4] net: add bpfilter
Date: Thu, 22 Feb 2018 09:06:45 -0800 [thread overview]
Message-ID: <20180222170643.lxipjzmjpeyqleyo@ast-mbp> (raw)
In-Reply-To: <20180222113915.4g27h7wy3mxk2lte@salvia>
On Thu, Feb 22, 2018 at 12:39:15PM +0100, Pablo Neira Ayuso wrote:
> Hi Alexei,
>
> On Wed, Feb 21, 2018 at 06:20:37PM -0800, Alexei Starovoitov wrote:
> > On Wed, Feb 21, 2018 at 01:13:03PM +0100, Florian Westphal wrote:
> > >
> > > Obvious candidates are: meta, numgen, limit, objref, quota, reject.
> > >
> > > We should probably also consider removing
> > > CONFIG_NFT_SET_RBTREE and CONFIG_NFT_SET_HASH and just always
> > > build both too (at least rbtree since that offers interval).
> > >
> > > For the indirect call issue we can use direct calls from eval loop for
> > > some of the more frequently used ones, similar to what we do already
> > > for nft_cmp_fast_expr.
> >
> > nft_cmp_fast_expr and other expressions mentioned above made me thinking...
> >
> > do we have the same issue with nft interpreter as we had with bpf one?
> > bpf interpreter was used as part of spectre2 attack to leak
> > information via cache side channel and let VM read hypervisor memory.
> > Due to that issue we removed bpf interpreter from the kernel code.
> > That's what CONFIG_BPF_JIT_ALWAYS_ON for...
> > but we still have nft interpreter in the kernel that can also
> > execute arbitrary nft expressions.
> >
> > Jann's exploit used the following bpf instructions:
> > struct bpf_insn evil_bytecode_instrs[] = {
> > // rax = target_byte_addr
> > { .code = BPF_LD | BPF_IMM | BPF_DW, .dst_reg = 0, .imm = target_byte_addr }, { .imm = target_byte_addr>>32 },
>
> We don't place pointers in the nft VM registers, it's basically
> illegal to do so, otherwise we would need more sophisticated verifier.
> I'm telling this because we don't have a way to point to any arbitrary
> address as in 'target_byte_addr' above.
these evil_bytecode_instrs never saw bpf verifier either.
That's the scary part of that poc.
The only requirement for poc to work is to have interpreter
in executable part of hypervisor code and speculatively jump into it
with arguments pointing to memory controlled by vm.
All static checks (done by bpf verifier and by nft validation) are bypassed.
The only way to defend from such exploit is either remove the interpreter
from the kernel or add _run-time_ checks and masks for every memory access
(similar to what is done for spectre1 mitigations).
In case of bpf it's impractical.
In case of nft I suspect so too. I don't yet see how nft can check
that skb pointer passed as part of nft_pktinfo is not an actual skb.
> > // rdi = timing_leak_array
> > { .code = BPF_LD | BPF_IMM | BPF_DW, .dst_reg = 1, .imm = host_timing_leak_addr }, { .imm = host_timing_leak_addr>>32 },
> > // rax = *(u8*)rax
> > { .code = BPF_LDX | BPF_MEM | BPF_B, .dst_reg = 0, .src_reg = 0, .off = 0 },
> > // rax = rax << ...
> > { .code = BPF_ALU64 | BPF_LSH | BPF_K, .dst_reg = 0, .imm = 10 - bit_idx },
> > // rax = rax & 0x400
> > { .code = BPF_ALU64 | BPF_AND | BPF_K, .dst_reg = 0, .imm = 0x400 },
> > // rax = rdi + rax
> > { .code = BPF_ALU64 | BPF_ADD | BPF_X, .dst_reg = 0, .src_reg = 1 },
> > // *(u8*) (rax + 0x800)
> > { .code = BPF_LDX | BPF_MEM | BPF_B, .dst_reg = 0, .src_reg = 0, .off = 0x800 },
> >
> > and a gadget to jump into __bpf_prog_run with insn pointing
> > to memory controlled by the guest while accessible
> > (at different virt address) by the hypervisor.
> >
> > It seems possible to construct similar sequence of instructions
> > out of nft expressions and use gadget that jumps into nft_do_chain().
> > The attacker would need to discover more kernel addresses:
> > nft_do_chain, nft_cmp_fast_ops, nft_payload_fast_ops, nft_bitwise_eval,
> > nft_lookup_eval, and nft_bitmap_lookup
> > to populate nft chains, rules and expressions in guest memory
> > comparing to bpf interpreter attack.
> >
> > Then in nft_do_chain(struct nft_pktinfo *pkt, void *priv)
> > pkt needs to point to fake struct sk_buff in guest memory with
> > skb->head == target_byte_addr
>
> We don't have a way to make this point to fake struct sk_buff.
yet. it's possible, since cpu is speculating and all such pointers
controlled by vm can be arbitrary.
> > The first nft expression can be nft_payload_fast_eval().
> > If it's properly constructed with
> > (nft_payload->based == NFT_PAYLOAD_NETWORK_HEADER, offset == 0, len == 0, dreg == 1)
>
> We can reject len == 0. To be honest, this is not done right now, but
> we can place a patch to validate this. Given this is a specialized
> networking virtual machine, it retain semantics, so fetching zero
> length data from a skbuff makes no sense, hence, we can return EINVAL
> via netlink when adding a rule that tries to do this.
Adding static check won't help.
next prev parent reply other threads:[~2018-02-22 17:06 UTC|newest]
Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-16 13:40 [PATCH RFC 0/4] net: add bpfilter Daniel Borkmann
2018-02-16 13:40 ` [PATCH RFC 1/4] modules: allow insmod load regular elf binaries Daniel Borkmann
2018-02-16 13:40 ` [PATCH RFC 2/4] bpf: introduce bpfilter commands Daniel Borkmann
2018-02-16 13:40 ` [PATCH RFC 3/4] net: initial bpfilter skeleton Daniel Borkmann
2018-02-16 13:40 ` [PATCH RFC 4/4] bpf: rough bpfilter codegen example hack Daniel Borkmann
2018-02-16 14:57 ` [PATCH RFC 0/4] net: add bpfilter Florian Westphal
2018-02-16 16:14 ` Florian Westphal
2018-02-16 20:44 ` Daniel Borkmann
2018-02-17 12:33 ` Harald Welte
2018-02-17 19:18 ` Florian Westphal
2018-02-16 22:33 ` David Miller
2018-02-17 12:21 ` Harald Welte
2018-02-17 20:10 ` Florian Westphal
2018-02-17 22:38 ` Florian Westphal
2018-02-16 16:53 ` Daniel Borkmann
2018-02-16 22:32 ` David Miller
2018-02-17 12:11 ` Harald Welte
2018-02-18 0:35 ` Florian Westphal
2018-02-19 12:03 ` Daniel Borkmann
2018-02-19 12:52 ` Harald Welte
2018-02-19 14:44 ` David Miller
2018-02-19 14:53 ` Florian Westphal
2018-02-19 15:07 ` David Miller
2018-02-19 15:20 ` Florian Westphal
2018-02-19 15:28 ` David Miller
2018-02-19 15:23 ` Harald Welte
2018-02-19 15:32 ` David Miller
2018-02-19 15:37 ` Jan Engelhardt
2018-02-19 15:43 ` David Miller
2018-02-19 15:36 ` David Miller
2018-02-19 17:20 ` Harald Welte
2018-02-19 17:29 ` David Miller
2018-02-19 18:37 ` Harald Welte
2018-02-19 18:47 ` David Miller
2018-02-19 17:40 ` Arturo Borrero Gonzalez
2018-02-19 18:06 ` Arturo Borrero Gonzalez
2018-02-19 18:43 ` David Miller
2018-02-19 15:00 ` David Miller
2018-02-19 14:59 ` Florian Westphal
2018-02-19 15:13 ` David Miller
2018-02-19 15:15 ` Florian Westphal
2018-02-19 15:27 ` David Miller
2018-02-19 15:38 ` Harald Welte
2018-02-19 15:44 ` David Miller
2018-02-19 17:14 ` Phil Sutter
2018-02-19 17:22 ` David Miller
2018-02-19 18:05 ` Phil Sutter
2018-02-19 18:41 ` David Miller
2018-02-19 20:41 ` Phil Sutter
2018-02-19 21:13 ` Florian Westphal
2018-02-20 10:44 ` Pablo Neira Ayuso
2018-02-20 14:07 ` Daniel Borkmann
2018-02-20 14:55 ` David Miller
2018-02-21 1:52 ` Alexei Starovoitov
2018-02-21 12:01 ` Pablo Neira Ayuso
2018-02-21 12:13 ` Florian Westphal
2018-02-22 2:20 ` nft/bpf interpreters and spectre2. Was: " Alexei Starovoitov
2018-02-22 11:39 ` Pablo Neira Ayuso
2018-02-22 17:06 ` Alexei Starovoitov [this message]
2018-02-22 18:47 ` Jann Horn
2018-02-19 17:41 ` Arturo Borrero Gonzalez
2018-02-19 21:30 ` Jozsef Kadlecsik
2018-02-19 15:27 ` Harald Welte
2018-02-19 15:31 ` David Miller
2018-02-19 17:09 ` Phil Sutter
2018-02-19 17:15 ` David Miller
2018-02-20 13:05 ` Phil Sutter
2018-02-20 9:35 ` Michal Kubecek
2018-02-20 18:10 ` Phil Sutter
2018-02-19 17:32 ` Harald Welte
2018-02-19 17:41 ` Arturo Borrero Gonzalez
2018-02-19 21:42 ` Willem de Bruijn
2018-02-18 23:35 ` Florian Westphal
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=20180222170643.lxipjzmjpeyqleyo@ast-mbp \
--to=alexei.starovoitov@gmail.com \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=fw@strlen.de \
--cc=jannh@google.com \
--cc=laforge@gnumonks.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pablo@netfilter.org \
--cc=phil@nwl.cc \
/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