• Alexei Starovoitov's avatar
    net: filter: x86: fix JIT address randomization · ba6f34fe
    Alexei Starovoitov authored
    commit 773cd38f upstream.
    
    bpf_alloc_binary() adds 128 bytes of room to JITed program image
    and rounds it up to the nearest page size. If image size is close
    to page size (like 4000), it is rounded to two pages:
    round_up(4000 + 4 + 128) == 8192
    then 'hole' is computed as 8192 - (4000 + 4) = 4188
    If prandom_u32() % hole selects a number >= PAGE_SIZE - sizeof(*header)
    then kernel will crash during bpf_jit_free():
    
    kernel BUG at arch/x86/mm/pageattr.c:887!
    Call Trace:
     [<ffffffff81037285>] change_page_attr_set_clr+0x135/0x460
     [<ffffffff81694cc0>] ? _raw_spin_unlock_irq+0x30/0x50
     [<ffffffff810378ff>] set_memory_rw+0x2f/0x40
     [<ffffffffa01a0d8d>] bpf_jit_free_deferred+0x2d/0x60
     [<ffffffff8106bf98>] process_one_work+0x1d8/0x6a0
     [<ffffffff8106bf38>] ? process_one_work+0x178/0x6a0
     [<ffffffff8106c90c>] worker_thread+0x11c/0x370
    
    since bpf_jit_free() does:
      unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
      struct bpf_binary_header *header = (void *)addr;
    to compute start address of 'bpf_binary_header'
    and header->pages will pass junk to:
      set_memory_rw(addr, header->pages);
    
    Fix it by making sure that &header->image[prandom_u32() % hole] and &header
    are in the same page
    
    Fixes: 314beb9b ("x86: bpf_jit_comp: secure bpf jit against spraying attacks")
    Signed-off-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
    Acked-by: default avatarEric Dumazet <edumazet@google.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
    ba6f34fe
bpf_jit_comp.c 22.6 KB