Clang-Linux:报告CFI错误而不会崩溃.ftrap功能和-O2
clang-linux: reporting CFI errors without crashing. ftrap-function and -O2
我正在尝试使用clang手册中的-ftrap函数标志来捕获CFI(呼叫框架信息)错误。
这是生成CFI错误的基本示例:
#include <stdio.h>
#include <stdlib.h>
__attribute__((used)) extern "C" void CatchCfi() {
printf("catchedn");
}
struct Foo {
Foo(const char* s) : command(s) {}
virtual ~Foo() {}
void fooStuff() { printf("fooStuffn"); }
const char* command;
};
struct Bar {
Bar(const char* s) : name(s) {}
virtual ~Bar() {}
void barStuff() { printf("barStuffn"); }
const char* name;
};
enum class WhichObject { FooObject, BarObject };
static void* allocator(WhichObject w, const char* arg) {
switch (w) {
case WhichObject::FooObject:
return new Foo(arg);
case WhichObject::BarObject:
return new Bar(arg);
}
}
int main(int argc, const char* argv[]) {
void* ptr = nullptr;
(void)(argc);
(void)(argv);
ptr = allocator(WhichObject::BarObject, "system("/bin/sh")");
Foo* fooptr = static_cast<Foo*>(ptr);
fooptr->fooStuff();
printf("not printed when compiled with -O2n");
return 0;
}
我使用这些与CFI相关的clang选项构建它:
-ftrap-function=CatchCfi -fsanitize=cfi-vcall -fvisibility=hidden -fsanitize=cfi-derived-cast -fsanitize=cfi-unrelated-cast -flto=thin
当构建此示例而无需优化时,它会按照我的意愿起作用。输出:
catched
fooStuff
not printed when compiled with -O2
当我使用-O2选项构建它时出现问题:
catched
Trace/breakpoint trap (core dumped)
gdb表明该程序在CatchCFI返回之后即将接收Sigtrap:
(gdb) r
Starting program: /home/romex/browser/src/out/debug/hello_cfi
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
catched
Program received signal SIGTRAP, Trace/breakpoint trap.
0x000000000020118a in ?? ()
(gdb) bt
#0 0x000000000020118a in ?? ()
#1 0x00000000002010f0 in frame_dummy ()
#2 0x00007ffff748e830 in __libc_start_main (main=0x201180 <main(int, char const**)>, argc=1, argv=0x7fffffffde18, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7fffffffde08) at ../csu/libc-start.c:291
#3 0x0000000000201029 in _start ()
Warning: the current language does not match this frame.
(gdb)
如何解决这个问题?我想知道有人是否有一个成功的故事与Ftrap-unction Flag有关?可能有一些特定的优化标志修复了此错误?谢谢。
我已经更新了您的代码,因此它可以按预期工作。我的环境不会引起SIGTRAP
,因此我插入了__builtin_trap()
调用。如前所述,@ysc是UB。在陷阱功能返回后,该程序无法继续,您必须在SIGTRAP
提出之前将程序还原为众所周知的好状态。
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
jmp_buf env;
__attribute__((used)) extern "C" void CatchCfi() {
printf("catchedn");
longjmp(env, 1);
}
struct Foo {
Foo(const char* s) : command(s) {}
virtual ~Foo() {}
void fooStuff() { printf("fooStuffn"); }
const char* command;
};
struct Bar {
Bar(const char* s) : name(s) {}
virtual ~Bar() {}
void barStuff() { printf("barStuffn"); }
const char* name;
};
enum class WhichObject { FooObject, BarObject };
static void* allocator(WhichObject w, const char* arg) {
switch (w) {
case WhichObject::FooObject:
return new Foo(arg);
case WhichObject::BarObject:
return new Bar(arg);
}
}
int main(int argc, const char* argv[]) {
void* ptr = nullptr;
(void)(argc);
(void)(argv);
ptr = allocator(WhichObject::BarObject, "system("/bin/sh")");
int val = setjmp(env);
if (!val) {
Foo* fooptr = static_cast<Foo*>(ptr);
fooptr->fooStuff();
__builtin_trap();
}
printf("not printed when compiled with -O2n");
return 0;
}
因为 ptr
是Bar
的指针,
Foo* fooptr = static_cast<Foo*>(ptr);
fooptr->fooStuff();
是未定义的行为,编译器不会像您期望的那样强迫工作。
相关文章:
- 当回溯以零开始时,如何调试崩溃
- 内联映射初始化的动态atexit析构函数崩溃
- 执行函数时导致崩溃的变量
- 程序崩溃并显示"std::out_of_range"错误
- CoInitialize()在单独的线程上崩溃而不返回
- 使用调试/崩溃报告将应用程序部署到客户端
- 为什么所有C++编译器都会崩溃或挂起此代码
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 为什么我的多线程作业队列崩溃
- ExtractIconEx:可以工作,但偶尔会崩溃
- 为什么引用传递会导致此崩溃(C++)
- 试图创建流或fopen时程序崩溃
- 类对象数组的问题会导致崩溃
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- 为什么要增加导致崩溃的指针
- 在虚幻引擎中删除NXOpen对象时崩溃
- 为什么它只打印双链接列表的第一个值,而我的程序却崩溃了
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- Visual Studio在尝试读取resource.txt文件时崩溃
- Clang-Linux:报告CFI错误而不会崩溃.ftrap功能和-O2