[하루한줄] CVE-2021-3490: Kernel Pwning with eBPF: a Love Story

URL

Kernel Pwning with eBPF: a Love Story

Target

Ubuntu 20.10

kernel 5.8.0-25.26 ~ 5.8.0-52.58

Explain

eBPF는 런타임 중 안전하게 커널 코드를 삽입하기 위해 Verifier와 BPF instruction을 사용합니다. Verifier는 레지스터의 값의 변화와 그 값들의 허용 범위(이하 range)등을 추적해 memory load와 store의 out-of-bound 여부를 검사합니다. 32-bit range를 갖는 레지스터와 64-bit range를 갖는 레지스터끼리의 Bitwise 연산(BPF_AND, BPF_OR, BPF_XOR)이 끝난 후 그에 맞게 32-bit range를 업데이트 하는 과정에서 오류가 발생해 out-of-bound read/write를 할 수 있습니다.

static void scalar_min_max_and(struct bpf_reg_state *dst_reg,
                              struct bpf_reg_state *src_reg)
{
    bool src_known = tnum_is_const(src_reg->var_off);
    bool dst_known = tnum_is_const(dst_reg->var_off);
    s64 smin_val = src_reg->smin_value;
    u64 umin_val = src_reg->umin_value;

    if (src_known && dst_known) {
            __mark_reg_known(dst_reg, dst_reg->var_off.value);
            return;
    }
  ...
}