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

Stefan Bader stefan.bader at canonical.com
Fri Jul 3 09:43:54 UTC 2015


On 03.07.2015 11:38, Luis Henriques wrote:
> 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).

Ah, I see. I got the indentation levels wrong and it looked to me like the loop
ended before the huge switch.

-Stefan

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


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20150703/98630941/attachment.sig>


More information about the kernel-team mailing list