Skip to the content.

pkru

pkru 为什么会特殊处理来着?

如何使用

仅仅是看 man 机制就是不错的了,主要不是作为一个安全机制的, 而是对于传统的 READ WRITE EXEC 机制的扩展。

似乎基本的实现就是这样的

static inline void wrpkru(unsigned int pkru)
{
	unsigned int eax = pkru;
	unsigned int ecx = 0;
	unsigned int edx = 0;

	asm volatile(".byte 0x0f,0x01,0xef\n\t"
		     :
		     : "a"(eax), "c"(ecx), "d"(edx));
}

int pkey_set(int pkey, unsigned long rights, unsigned long flags)
{
	unsigned int pkru = (rights << (2 * pkey));
	return wrpkru(pkru);
}

int pkey_mprotect(void *ptr, size_t size, unsigned long orig_prot,
		  unsigned long pkey)
{
	return syscall(SYS_pkey_mprotect, ptr, size, orig_prot, pkey);
}


int pkey_free(unsigned long pkey)
{
	return syscall(SYS_pkey_free, pkey);
}

https://github.com/bminor/glibc/blob/master/sysdeps/unix/sysv/linux/x86/arch-pkey.h

的确是那么回事,就是读写的 pkru 寄存器即可。

和 xsave 的关系

至少在 qemu 的 x86_cpu_xrstor_all_areas 中看,这个也是区域中的一个:

    e = &x86_ext_save_areas[XSTATE_PKRU_BIT];
    if (e->size && e->offset) {
        const XSavePKRU *pkru;

        pkru = buf + e->offset;
        memcpy(&env->pkru, pkru, sizeof(env->pkru));
    }

虚拟机中到底支持 pkru 么?

为什么 pkru 是放到 fpu 中保存切换上下文的

[!NOTE] 参考 Deepseeek ,有待验证

PKRU(Protection Key Rights Register for Userspace): 是 x86 的内存保护密钥(Memory Protection Keys, MPK)机制的一部分。 虽然 PKRU 在逻辑上属于 FPU 状态(因为它是通过 XSAVE/XRSTOR 保存的),但出于安全和性能考虑,KVM 单独处理 PKRU 的切换。

在 VM-Entry/VM-Exit 时单独切换 PKRU: 即使 FPU 状态整体未切换(例如 lazy FPU 优化),PKRU 也会被显式保存和恢复。

这是因为 PKRU 控制内存访问权限,若错误地保留宿主机 PKRU 值,可能导致客户机访问非法内存或泄露信息。 guest_fpstate 包含客户机 FPU,但 PKRU 仍是宿主机的: 这句话有点反直觉,但意思是:guest_fpu 结构体中保存的是客户机的 FPU 寄存器值(如 XMM、YMM 等),但其中的 PKRU 字段并未更新为客户机的值,而是仍保留宿主机的 PKRU。 实际客户机的 PKRU 值由 KVM 单独维护(通常在 vcpu->arch.pkru 或类似字段中),并在 VM-Entry 时写入 CPU 的 PKRU 寄存器。

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。