public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Alexei Starovoitov <alexei.starovoitov@gmail.com>
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 12:39:15 +0100	[thread overview]
Message-ID: <20180222113915.4g27h7wy3mxk2lte@salvia> (raw)
In-Reply-To: <20180222022036.lysyiaotj7kcglf5@ast-mbp.dhcp.thefacebook.com>

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.

> // 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.

> 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.

> it will do arbitrary load of
> *(u8 *)dest = *(u8 *)ptr;
> from target_byte_addr into register 1 of nft state machine
> (dest is u32 array of registers in the stack of nft_do_chain)
> Second nft expression can be nft_bitwise_eval() to mask particular
> bit in register 1.
> Then nft_cmp_eval() to check whether bit is one or zero and
> conditional NFT_BREAK out of first nft expression into second nft rule.
> The last conditional nft_immediate_eval() in the first rule will set
> register 1 to 0x400 * 8 while the first nft_bitwise_eval() in
> the second rule with do r1 &= 0x400 * 8.
> So at this point r1 will have either 0x400 * 8 or 0 depending
> on value of speculatively loaded bit.
> The last expression can be nft_lookup_eval() with 
> nft_lookup->set->ops->lookup == nft_bitmap_lookup
> which will do nft_bitmap->bitmap[idx] where idx = r1 / 8
> The memory used for this last nft_lookup/bitmap expression is
> both an instruction and timing_leak_array itself.
> If I'm not mistaken, this sequence of nft expression will
> speculatively execute very similar logic as in evil_bytecode_instrs[]

My impression is that several assumptions above are not correct.

> The amount of actual speculative native cpu load/stores/branches is
> probably more than executed by bpf interpreter for these evil bytecodes,
> but likely well within cpu speculation window of 100+ insns.
> 
> Obviously such exploit is harder to do than bpf based one.
> Do we need to do anything about it ?
> May be it's easier to find gadgets in .text of vmlinux
> instead of messing with interpreters?
> 
> Jann,
> can you comment on removing interpreters in general?
> Do we need to worry about having bpf and/or nft interpreter
> in the kernel?

Jann, any review on that front is very much welcome, so please let me
know if you find any real problem.

Thanks for reviewing!

  reply	other threads:[~2018-02-22 11:39 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 [this message]
2018-02-22 17:06                                   ` Alexei Starovoitov
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=20180222113915.4g27h7wy3mxk2lte@salvia \
    --to=pablo@netfilter.org \
    --cc=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=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