• Daniel Borkmann's avatar
    bpf: fix overflow in prog accounting · 5ccb071e
    Daniel Borkmann authored
    Commit aaac3ba9 ("bpf: charge user for creation of BPF maps and
    programs") made a wrong assumption of charging against prog->pages.
    Unlike map->pages, prog->pages are still subject to change when we
    need to expand the program through bpf_prog_realloc().
    
    This can for example happen during verification stage when we need to
    expand and rewrite parts of the program. Should the required space
    cross a page boundary, then prog->pages is not the same anymore as
    its original value that we used to bpf_prog_charge_memlock() on. Thus,
    we'll hit a wrap-around during bpf_prog_uncharge_memlock() when prog
    is freed eventually. I noticed this that despite having unlimited
    memlock, programs suddenly refused to load with EPERM error due to
    insufficient memlock.
    
    There are two ways to fix this issue. One would be to add a cached
    variable to struct bpf_prog that takes a snapshot of prog->pages at the
    time of charging. The other approach is to also account for resizes. I
    chose to go with the latter for a couple of reasons: i) We want accounting
    rather to be more accurate instead of further fooling limits, ii) adding
    yet another page counter on struct bpf_prog would also be a waste just
    for this purpose. We also do want to charge as early as possible to
    avoid going into the verifier just to find out later on that we crossed
    limits. The only place that needs to be fixed is bpf_prog_realloc(),
    since only here we expand the program, so we try to account for the
    needed delta and should we fail, call-sites check for outcome anyway.
    On cBPF to eBPF migrations, we don't grab a reference to the user as
    they are charged differently. With that in place, my test case worked
    fine.
    
    Fixes: aaac3ba9 ("bpf: charge user for creation of BPF maps and programs")
    Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
    Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    5ccb071e
syscall.c 23.2 KB