[Precise][CVE-2015-4700] x86: bpf_jit: fix compilation of large bpf programs

Luis Henriques luis.henriques at canonical.com
Fri Jul 3 09:38:53 UTC 2015


On Fri, Jul 03, 2015 at 11:13:01AM +0200, Stefan Bader wrote:
> On 02.07.2015 20:28, Kamal Mostafa wrote:
> > From: Alexei Starovoitov <ast at plumgrid.com>
> > 
> > commit 3f7352bf21f8fd7ba3e2fcef9488756f188e12be upstream.
> > 
> > BugLink: http://bugs.launchpad.net/bugs/1469320
> > 
> > x86 has variable length encoding. x86 JIT compiler is trying
> > to pick the shortest encoding for given bpf instruction.
> > While doing so the jump targets are changing, so JIT is doing
> > multiple passes over the program. Typical program needs 3 passes.
> > Some very short programs converge with 2 passes. Large programs
> > may need 4 or 5. But specially crafted bpf programs may hit the
> > pass limit and if the program converges on the last iteration
> > the JIT compiler will be producing an image full of 'int 3' insns.
> > Fix this corner case by doing final iteration over bpf program.
> > 
> > Fixes: 0a14842f5a3c ("net: filter: Just In Time compiler for x86-64")
> > Reported-by: Daniel Borkmann <daniel at iogearbox.net>
> > Signed-off-by: Alexei Starovoitov <ast at plumgrid.com>
> > Tested-by: Daniel Borkmann <daniel at iogearbox.net>
> > Acked-by: Daniel Borkmann <daniel at iogearbox.net>
> > Signed-off-by: David S. Miller <davem at davemloft.net>
> > CVE-2015-4700
> > [ kamal: backport to 3.8 (Ubuntu Precise): context ]
> > Signed-off-by: Kamal Mostafa <kamal at canonical.com>
> > ---
> >  arch/x86/net/bpf_jit_comp.c | 7 ++++++-
> >  1 file changed, 6 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> > index 5a5b6e4..11e3100 100644
> > --- a/arch/x86/net/bpf_jit_comp.c
> > +++ b/arch/x86/net/bpf_jit_comp.c
> > @@ -150,7 +150,12 @@ void bpf_jit_compile(struct sk_filter *fp)
> >  	}
> >  	cleanup_addr = proglen; /* epilogue address */
> >  
> > -	for (pass = 0; pass < 10; pass++) {
> > +	/* JITed image shrinks with every pass and the loop iterates
> > +	 * until the image stops shrinking. Very large bpf programs
> > +	 * may converge on the last pass. In such case do one more
> > +	 * pass to emit the final image
> > +	 */
> > +	for (pass = 0; pass < 10 || image; pass++) {
> 
> Are you sure? Recent code is calling do_jit() inside the loop which can set
> image. I cannot see any way that would ever happen for the Precise code base...
>

do_jit() is actually a result of splitting bpf_jit_compile() in two
functions with commit f3c2af7ba17a ("net: filter: x86: split bpf_jit_compile()").

So, basically the code in do_jit() is just inlined in
bpf_jit_compile() and it does eventually change 'image' the same way
with memcpy (line 595).

Cheers,
--
Luís

> -Stefan
> 
> >  		u8 seen_or_pass0 = (pass == 0) ? (SEEN_XREG | SEEN_DATAREF | SEEN_MEM) : seen;
> >  		/* no prologue/epilogue for trivial filters (RET something) */
> >  		proglen = 0;
> > 
> 
> 



> -- 
> kernel-team mailing list
> kernel-team at lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team





More information about the kernel-team mailing list