what is cr4 register pinning

우리가 ret2usr 공격에 대한 mitigation으로 smep을 배웠다. 그리고 smep은 cr4 레지스터에 특정 비트로 확인이 된다는 것도 배웠다. 그럼 이런 생각을 할 수 있다. 그럼 커널에서 rop로 이 해당 비트를 클리어 하면 되는 거 아니야?

이런 생각을 하는 사람이 또 있어서 직접 테스트를 해보았다고 한다.

근데 봐보면,

C
void native_write_cr4(unsigned long val)
{
	unsigned long bits_changed = 0;

set_register:
	asm volatile("mov %0,%%cr4": "+r" (val) : : "memory");

	if (static_branch_likely(&cr_pinning)) {
		if (unlikely((val & cr4_pinned_mask) != cr4_pinned_bits)) {
			bits_changed = (val & cr4_pinned_mask) ^ cr4_pinned_bits;
			val = (val & ~cr4_pinned_mask) | cr4_pinned_bits;
			goto set_register;
		}
		/* Warn after we've corrected the changed bits. */
		WARN_ONCE(bits_changed, "pinned CR4 bits changed: 0x%lx!?\n",
			  bits_changed);
	}
}

다음과 같이 실제 커널 소스코드를 보면, cr4 레지스터를 바꿔도 smep 이나 smap같은 보안과 중요한 비트는 다시 set되게 코드를 작성해놨다. 따라서 코드에서 보이듯이 pin을 해놓았다고 한다. 즉, 커널에서 cr4 레지스터를 클리어 함으로써 하는 공격은 잘 통하지 않는다.