【问题标题】:How can I compile a program with Intel's Memory Protection Extensions (MPX) on a Mac?如何在 Mac 上使用英特尔的内存保护扩展 (MPX) 编译程序?
【发布时间】:2020-05-08 21:30:18
【问题描述】:

我正在尝试通过镜像this tutorial for Linux 在我的 Macbook Pro 上测试英特尔的内存保护扩展 (MPX)。我的处理器是 Intel Core i5-6267U,它确实能够使用 MPX,已通过运行 sysctl machdep.cpu | grep MPX 验证。但是,当我尝试编译以下测试程序时:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define noinline __attribute__((noinline))

char dog[] = "dog";
char password[] = "secr3t";

noinline
char dog_letter(int nr)
{
        return dog[nr];
}

int main(int argc, char **argv)
{
        int max = sizeof(dog);
        int i;

        if (argc >= 2)
                max = atoi(argv[1]);

        for (i = 0; i < max; i++)
                printf("dog[%d]: '%c'\n", i, dog_letter(i));

        return 0;
}

使用以下命令:

/usr/local/bin/gcc-8 -o mpx_test -fcheck-pointer-bounds -mmpx mpx_test.c

我收到以下错误字符串:

/var/folders/v0/g_jfwt1j0kj1cp6vjn818jjh0000gn/T//cc5F0fho.s:26:10: error: unexpected token in argument list
        bnd jle L2
                ^
/var/folders/v0/g_jfwt1j0kj1cp6vjn818jjh0000gn/T//cc5F0fho.s:37:11: error: unexpected token in argument list
        bnd call        _atoi
                        ^
/var/folders/v0/g_jfwt1j0kj1cp6vjn818jjh0000gn/T//cc5F0fho.s:41:10: error: unexpected token in argument list
        bnd jmp L3
                ^
/var/folders/v0/g_jfwt1j0kj1cp6vjn818jjh0000gn/T//cc5F0fho.s:45:11: error: unexpected token in argument list
        bnd call        _dog_letter
                        ^
/var/folders/v0/g_jfwt1j0kj1cp6vjn818jjh0000gn/T//cc5F0fho.s:57:9: error: unexpected token in argument list
        bnd jl  L4
                ^
/var/folders/v0/g_jfwt1j0kj1cp6vjn818jjh0000gn/T//cc5F0fho.s:61:2: error: invalid instruction mnemonic 'bnd'
        bnd ret
        ^~~
/var/folders/v0/g_jfwt1j0kj1cp6vjn818jjh0000gn/T//cc5F0fho.s:88:2: error: invalid instruction mnemonic 'bnd'
        bnd ret
        ^~~

如果我使用 -S 标志进行编译,我可以看到 GCC 生成的程序集确实具有特定于 MPX 的指令 (bnd...)。我还需要做什么来编译带有 MPX 保护的程序?

【问题讨论】:

  • GCC 没有删除 MPX 支持吗?
  • Apple 的汇编程序似乎还没有更新以理解 MPX。这可能意味着内核和 C 库也不支持 MPX。您将不得不等待支持此功能的新版 OSX。
  • 什么虚拟机?我听说 MPX 也已从 Linux 内核中删除。
  • 如果您想在 VM 中运行代码,请在 VM 中编译。您正在做的是将和组装编译成 MachO64 目标文件 MacOS,因此即使您遗漏了-fcheck-pointer-bounds -mmpx,您也很难在 Linux 上运行它
  • 我不知道 MPX 是否需要虚拟机管理程序和/或外部操作系统的支持才能在 VM 内部使用。你不妨试试看。

标签: c gcc x86 cpu intel


【解决方案1】:

我找到了一种解决方法,可以让我在我的 Mac 上使用 MPX——尽管它实际上只适用于小程序。我为使 MPX 为 内核空间 工作而采取的步骤如下:

  1. 启用 MPX。请参阅英特尔手册了解如何执行此操作。简而言之,需要向 MSR 写入一些位。
  2. 启动 Linux VM 或在任何其他具有支持 MPX 的汇编程序的系统上跳转。
  3. 在第二个系统上,写出 MPX 汇编指令(您希望在 Mac 上用于该程序)并汇编该程序。
  4. 通过objdump -d 反汇编程序,并将相关 MPX 指令和操作数的操作码复制到 Mac 上的内联汇编中。
  5. 在 Mac 上编译并运行 :)

这也应该适用于用户空间中的 MPX,只需稍微改变启用 MPX 的方式(XSAVE 用于用户空间的指令和用于内核空间的 MSR)。

作为复制操作码后 Mac 上的内联程序集的示例,请考虑以下内容。

__asm__ volatile (
        ".byte 0xf3, 0x0f, 0x1b, 0x40, 0x10     \t\n" // bndmk 16(%rax), %bnd0
        ".byte 0xf2, 0x0f, 0x1a, 0x40, 0x16     \t\n" // bndcu 22(%rax), %bnd0
        :
        : "a" (some_input)
    );

【讨论】:

  • inline-asm 语句不会告诉编译器 -16(%rbp) 是一个输入。您在这里完全依赖航位推算,以便在您的 Linux 和 Mac 构建之间的堆栈上实际拥有正确的指针。相反,您应该在asm volatile (".byte ..." : : "a"(some_local)); 等特定寄存器中请求指针输入您只读取该GP 寄存器,而GCC 不知道BND regs,因此您无需在它们上声明clobbers。但是,我认为您还需要声明一个虚拟内存输入,因此指向的内存 16(%rax) 也是一个输入。
  • 感谢@PeterCordes 对所有有用的 cmets。我更改了内联程序集以反映您的评论。如果我没有完全理解你,请告诉我。
  • 这就是我的建议,是的。我认为没有"memory" clobber 是正确的,因为它实际上并没有访问16(%rax) 的内存;我之前的评论是错误的。我不得不提醒自己 MPX 是如何工作的:bndmk 选择寻址模式并使用%rax(在这种情况下)作为下限,16 + %rax 作为上限。在我之前的评论中,我猜错了它是从内存中加载下限+上限16(%rax)
  • 是的,你是对的,它使用%rax 作为下限,16+%rax 作为上限。感谢您的帮助!
  • 所以这个代码片段只会引发#BR绑定异常,而不管输入时RAX中的值是什么,因为它在bndmk之后使用bndcu,地址超出边界。我不认为这对于在为 Mac 编译的代码中实际使用 MPX 迈出了很大的一步。为此,我认为您需要传递绑定寄存器并屏蔽编译器对内存的访问,因此绑定设置和检查在访问之前发生。或者只是在某个地方出现故障是可以的,即使是在加载或存储某些东西之后。
猜你喜欢
  • 2014-08-17
  • 2013-05-02
  • 2012-08-08
  • 2017-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
  • 2021-04-29
相关资源
最近更新 更多