[하루한줄] CVE-2020-27194: eBPF verifier bug
URL
Fuzzing for eBPF JIT bugs in the Linux kernel
Target
Linux kernel
eBPF
Explain
eBPF는 런타임 중 안전하게 커널 코드를 삽입하기 위해 Verifier와 BPF instruction을 사용합니다. Verifier는 레지스터의 값의 변화와 그 값들의 허용 범위(이하 range)등을 트래킹해 memory load와 store의 out-of-bound 여부를 검사하며, 32-bit와 64-bit 각각의 range를 구분해 관리합니다. OR연산이 끝난 후 그에 맞게 32-bit 레지스터의 range를 업데이트하는 scalar32_min_max_or()
함수는 이 구분이 확실하지 못하고, 버그를 유발합니다.
/* ORing two positives gives a positive, so safe to
* cast result into s64.
*/
dst_reg->s32_min_value = dst_reg->umin_value;
dst_reg->s32_max_value = dst_reg->umax_value;
64-bit range를 32-bit range로 casting 하는 scalar32_min_max_or()
의 코드 부분입니다. Verifier는 s32_min_value
와 s32_max_value
를 이용해 range를 트래킹 하는데, 만약 이 두 값이 같다면 레지스터 값을 상수로 인식하고 그에 따라 코드가 분기합니다.
만약 위 코드에서 dst_reg->umin_value
가 1이고, dst_reg->umax_value
가 25769803777이라면 dst_reg->s32_min_value
와 dst_reg->s32_max_value
둘 다 1로 저장되어 레지스터를 range가 아닌 상수로 인식하게 됩니다.
Reference
https://www.sosconhistory.net/soscon2018/pdf/day2_1100_3.pdf
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.