• Yonghong Song's avatar
    bpf: fix kernel page fault in lpm map trie_get_next_key · 6dd1ec6c
    Yonghong Song authored
    Commit b471f2f1 ("bpf: implement MAP_GET_NEXT_KEY command
    for LPM_TRIE map") introduces a bug likes below:
    
        if (!rcu_dereference(trie->root))
            return -ENOENT;
        if (!key || key->prefixlen > trie->max_prefixlen) {
            root = &trie->root;
            goto find_leftmost;
        }
        ......
      find_leftmost:
        for (node = rcu_dereference(*root); node;) {
    
    In the code after label find_leftmost, it is assumed
    that *root should not be NULL, but it is not true as
    it is possbile trie->root is changed to NULL by an
    asynchronous delete operation.
    
    The issue is reported by syzbot and Eric Dumazet with the
    below error log:
      ......
      kasan: CONFIG_KASAN_INLINE enabled
      kasan: GPF could be caused by NULL-ptr deref or user memory access
      general protection fault: 0000 [#1] SMP KASAN
      Dumping ftrace buffer:
         (ftrace buffer empty)
      Modules linked in:
      CPU: 1 PID: 8033 Comm: syz-executor3 Not tainted 4.15.0-rc8+ #4
      Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
      RIP: 0010:trie_get_next_key+0x3c2/0xf10 kernel/bpf/lpm_trie.c:682
      ......
    
    This patch fixed the issue by use local rcu_dereferenced
    pointer instead of *(&trie->root) later on.
    
    Fixes: b471f2f1 ("bpf: implement MAP_GET_NEXT_KEY command or LPM_TRIE map")
    Reported-by: default avatarsyzbot <syzkaller@googlegroups.com>
    Reported-by: default avatarEric Dumazet <edumazet@google.com>
    Signed-off-by: default avatarYonghong Song <yhs@fb.com>
    Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    6dd1ec6c
lpm_trie.c 19.8 KB