현재 알려진 바로는 3가지의 버그가 존재하고, 2가지는 Spectre, 1가지는 Meltdown 버그라 칭해지고 있습니다.
- CVE-2017-5753 (variant 1 / Spectre) : Bounds-check bypass
- CVE-2017-5715 (variant 2 / Spectre) : Branch Target Injection
- CVE-2017-5754 (variant 3 / Meltdown) : Rogue Data Load
이 글은 Spectre bug와 Meltdown bug를 소개하는 것이 목적이 아닙니다. 이 버그에 대한 기술적인 글들은 많이 올라와 있으므로, 여기서는 RHEL/CentOS 환경에서 어떻게 적용할 것인가에 대하여 논하려 합니다.
일단, 버그가 알려진지 5일 정도 지난 시점에서, 벤더 별 OS kernel patch가 발표 되고, H/W 벤더들의 bios firmware 들이 발표가 되고 있는 상황에서 성능 저하 이슈와 패치 적용 이슈를 어떻게 해야 하는지에 대하여 논하려고 합니다.
현재, 나오고 있는 H/W bios patch는 CVE-2017-5715 (variant 2) 에 대해서만 해결을 하고 있으며, bios 만으로 해결은 안되고 software 적인 patch(즉 kernel patch)도 같이 필요한 상황입니다.
CVE-2017-5753 (variant 1)과 CVE-2017-5754 (variant 3)은 H/W 적으로 수정이 불가능 하고 software 적으로만 해결이 가능 합니다. 그리고 성능 저하의 문제는 CVE-2017-5754 (variant 3) meltdown patch에서 발생을 하게 됩니다.
meltdown patch의 경우 user 영역에서 kernel 영역의 memory 주소를 알지 못하게 하기 위하여 page table을 isolate 시켜 버리는데, 문제는 page table이 분리되다 보니 kernel syscall 이 호출 될 때 마다 분리된 kernel page table도 매번 호출이 되어야 하는 overhead가 발생하여 성능이 저하가 되는 것 입니다.
이 3가지 패치에 대하여 RHEL/Centos 의 커널은 3가지 옵션을 제공 합니다. (패치가 적용된 커널들은 /sys에 다음의 파일들이 생성되며, 파일 값은 1이 기본 입니다.)
[root@host ~]# cat /sys/kernel/debug/x86/pti_enabled
1
cat /sys/kernel/debug/x86/ibpb_enabled
1
cat /sys/kernel/debug/x86/ibrs_enabled
1
CentOS 6 의 경우에는 /sys/kernel/debug 를 아래와 같이 mount 해 주어야 합니다.[root@host ~]# mount -t debugfs nodev /sys/kernel/debug
Intel CPU의 경우,
variant #1, #2, #3 을 모두 fix
[root@host ~]# echo "1" > /sys/kernel/debug/x86/pti_enabled
[root@host ~]# echo "1" > /sys/kernel/debug/x86/ibpb_enabled
[root@host ~]# echo "1" > /sys/kernel/debug/x86/ibrs_enabled
microcode update가 필요 없는 아주 오래된 intel cpu의 경우
[root@host ~]# echo "1" > /sys/kernel/debug/x86/pti_enabled
[root@host ~]# echo "0" > /sys/kernel/debug/x86/ibpb_enabled
[root@host ~]# echo "1" > /sys/kernel/debug/x86/ibrs_enabled
와 같이 해 주시면 됩니다.
AMD cpu의 경우에는 meltdown 은 적용이 필요 없으며,
H/W patch (bios upgrade)가 가능할 경우
[root@host ~]# echo "0" > /sys/kernel/debug/x86/pti_enabled
[root@host ~]# echo "0" > /sys/kernel/debug/x86/ibpb_enabled
[root@host ~]# echo "2" > /sys/kernel/debug/x86/ibrs_enabled
microcode 업데이트 없이 분기 예측을 사용할 수 없는 오래된 CPU의 경우
[root@host ~]# echo "0" > /sys/kernel/debug/x86/pti_enabled
[root@host ~]# echo "2" > /sys/kernel/debug/x86/ibpb_enabled
[root@host ~]# echo "1" > /sys/kernel/debug/x86/ibrs_enabled
로 해 주시면 됩니다.
물론 이 설정들은 runtime 설정이 가능 하며, 대신 persist 하지 않으므로 booting 시 마다 처리를 해 주어야 합니다. 또한, rc.local 에서 처리를 할 경우 rc.local 보다 먼저 실행되는 process 의 경우에는 이 설정의 영향을 받지 않기 때문에 기본 설정은 booting 시의 kernel parameter로 반영 하는 것이 좋습니다. 각 옵션에 해당하는 kernel parameter는 다음과 같습니다. (설정 값을 0으로 하는 것과 같습니다.)
noibrs noibpb nopti
여기까지는 아주 원론적으로 bug를 fix 하는 방법에 대하여 알아 보았습니다.
이 정보를 토대로 하면, spectre bug와 meltdown bug에 대하여 각각 정책을 취할 수 있게 됩니다. 예를 들어, 보안 버그가 중요하지만 성능 저하가 더 큰 문제인 경우, 해당 서버가 isolate 가 되어 있다면 과감하게 meltdown bug patch를 포기하는 정책도 가능 하다는 의미입니다.
현재, 이 기능을 사용할 수 있는 커널은
CentOS 7 3.10.0-693.11.6.el7부터 사용이 가능 합니다. 물론, 이전 커널들은 page table isolate 같은 것을 하지 않았으니 이 기능 자체가 필요 없는 것이고요.
CentOS 6 2.6.32-696.18.7.el6
이 정보를 토대로 spectre 와 meltdown 버그에 대한 정책을 결정하는데 도움이 되기를 바랍니다.
이 문서는 https://access.redhat.com/articles/3311301 문서를 토대로 작성을 하였음을 밝힙니다.
Comments List
https://access.redhat.com/articles/3311301 에 업데이트 된 내용이 있습니다.
retp_enabled 이 추가가 되었습니다.
영구적으로 적용하지 않는 옵션은 "spectre_v2=off nopti" 이렇게 kernel parameter에 넣어도 된다고 하는 군요. 링크 페이지 참조 하시기 바랍니다.
retp_enable 는 google이 발표한 성능 저하 없는 spectre retpoline 패치 기능을 의미하는데, gcc 도 같이 업데이트가 되어야 합니다. 단, skylake 에서는 retp 대신에 ibrs 를 사용한다고 되어 있습니다.
즉, CentOS 에서 retp_enable 을 사용하려면, gcc 와 libgcc 도 같이 최신 버전으로 업데이트 되어야 합니다.
CentOS 6.9랑 7.4 만 패치가 보이는데요 6.6 이나 7.0 같은 이외버전은 커널 어떤거 받으면 될까요? ㅠㅠ
6.6 이나 7.0 의 경우에는 RHEL 의 정책에 의해 별도로 license 계약을 체결해야 합니다.
또는, 6.9 나 7.4 로 업데이트를 해 주시면 됩니다. 업데이트는 간단하게 yum update 명령으로 업데이트가 가능 합니다. 6.x 나 7.X 간의 업데이트는 최소한의 하위 호환성을 보장 하면서 update 되기 때문에 update가 힘든 편은 아닙니다. 특시 APM 위주의 서비스는 그냥 업데이트를 따라 가셔도 거의 무방 합니다.