Skip to content

Commit

Permalink
[ELF] Add -z cet-report
Browse files Browse the repository at this point in the history
Fixes #229
  • Loading branch information
rui314 committed Jan 9, 2022
1 parent 778f862 commit 31a43a7
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 2 deletions.
6 changes: 6 additions & 0 deletions elf/cmdline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,12 @@ void parse_nonpositional_args(Context<E> &ctx,
ctx.arg.z_now = true;
} else if (read_z_flag(args, "lazy")) {
ctx.arg.z_now = false;
} else if (read_z_flag(args, "cet-report=none")) {
ctx.arg.z_cet_report = CET_REPORT_NONE;
} else if (read_z_flag(args, "cet-report=warning")) {
ctx.arg.z_cet_report = CET_REPORT_WARNING;
} else if (read_z_flag(args, "cet-report=error")) {
ctx.arg.z_cet_report = CET_REPORT_ERROR;
} else if (read_z_flag(args, "execstack")) {
ctx.arg.z_execstack = true;
} else if (read_z_arg(ctx, args, arg, "max-page-size")) {
Expand Down
5 changes: 5 additions & 0 deletions elf/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,10 @@ static int elf_main(int argc, char **argv) {
// Beyond this point, no new files will be added to ctx.objs
// or ctx.dsos.

// Handle `-z cet-report`.
if (ctx.arg.z_cet_report != CET_REPORT_NONE)
check_cet_errors(ctx);

// If we are linking a .so file, remaining undefined symbols does
// not cause a linker error. Instead, they are treated as if they
// were imported symbols.
Expand All @@ -551,6 +555,7 @@ static int elf_main(int argc, char **argv) {
if (!ctx.arg.allow_multiple_definition)
check_duplicate_symbols(ctx);

// Handle --require-defined
for (std::string_view name : ctx.arg.require_defined)
if (!get_symbol(ctx, name)->file)
Error(ctx) << "--require-defined: undefined symbol: " << name;
Expand Down
8 changes: 8 additions & 0 deletions elf/mold.h
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,7 @@ template <typename E> void convert_common_symbols(Context<E> &);
template <typename E> void compute_merged_section_sizes(Context<E> &);
template <typename E> void bin_sections(Context<E> &);
template <typename E> ObjectFile<E> *create_internal_file(Context<E> &);
template <typename E> void check_cet_errors(Context<E> &);
template <typename E> void check_duplicate_symbols(Context<E> &);
template <typename E> void sort_init_fini(Context<E> &);
template <typename E> std::vector<Chunk<E> *>
Expand Down Expand Up @@ -1168,6 +1169,12 @@ typedef enum {
NOSEPARATE_CODE,
} SeparateCodeKind;

typedef enum {
CET_REPORT_NONE,
CET_REPORT_WARNING,
CET_REPORT_ERROR,
} CetReportKind;

struct VersionPattern {
u16 ver_idx;
std::vector<std::string_view> patterns;
Expand Down Expand Up @@ -1218,6 +1225,7 @@ struct Context {
// Command-line arguments
struct {
BuildId build_id;
CetReportKind z_cet_report = CET_REPORT_NONE;
CompressKind compress_debug_sections = COMPRESS_NONE;
SeparateCodeKind z_separate_code = SEPARATE_LOADABLE_SEGMENTS;
UnresolvedKind unresolved_symbols = UNRESOLVED_ERROR;
Expand Down
3 changes: 1 addition & 2 deletions elf/output-chunks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1766,8 +1766,7 @@ template <typename E>
void NotePropertySection<E>::update_shdr(Context<E> &ctx) {
features = -1;
for (ObjectFile<E> *file : ctx.objs)
if (file != ctx.internal_obj)
features &= file->features;
features &= file->features;

if (ctx.arg.z_shstk)
features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
Expand Down
29 changes: 29 additions & 0 deletions elf/passes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ ObjectFile<E> *create_internal_file(Context<E> &ctx) {
obj->symbols.push_back(new Symbol<E>);
obj->first_global = 1;
obj->is_alive = true;
obj->features = -1;
obj->priority = 1;

auto add = [&](std::string_view name) {
Expand Down Expand Up @@ -407,6 +408,33 @@ ObjectFile<E> *create_internal_file(Context<E> &ctx) {
return obj;
}

template <typename E>
void check_cet_errors(Context<E> &ctx) {
bool warning = (ctx.arg.z_cet_report == CET_REPORT_WARNING);
bool error = (ctx.arg.z_cet_report == CET_REPORT_ERROR);
assert(warning || error);

for (ObjectFile<E> *file : ctx.objs) {
if (!(file->features & GNU_PROPERTY_X86_FEATURE_1_IBT)) {
if (warning)
Warn(ctx) << *file << ": -cet-report=warning: "
<< "missing GNU_PROPERTY_X86_FEATURE_1_IBT";
else
Error(ctx) << *file << ": -cet-report=error: "
<< "missing GNU_PROPERTY_X86_FEATURE_1_IBT";
}

if (!(file->features & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) {
if (warning)
Warn(ctx) << *file << ": -cet-report=warning: "
<< "missing GNU_PROPERTY_X86_FEATURE_1_SHSTK";
else
Error(ctx) << *file << ": -cet-report=error: "
<< "missing GNU_PROPERTY_X86_FEATURE_1_SHSTK";
}
}
}

template <typename E>
void check_duplicate_symbols(Context<E> &ctx) {
Timer t(ctx, "check_dup_syms");
Expand Down Expand Up @@ -1091,6 +1119,7 @@ void compress_debug_sections(Context<E> &ctx) {
template void compute_merged_section_sizes(Context<E> &ctx); \
template void bin_sections(Context<E> &ctx); \
template ObjectFile<E> *create_internal_file(Context<E> &ctx); \
template void check_cet_errors(Context<E> &ctx); \
template void check_duplicate_symbols(Context<E> &ctx); \
template void sort_init_fini(Context<E> &ctx); \
template std::vector<Chunk<E> *> collect_output_sections(Context<E> &ctx); \
Expand Down
28 changes: 28 additions & 0 deletions test/elf/z-cet-report.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash
export LANG=
set -e
CC="${CC:-cc}"
CXX="${CXX:-c++}"
testname=$(basename -s .sh "$0")
echo -n "Testing $testname ... "
cd "$(dirname "$0")"/../..
mold="$(pwd)/mold"
t=out/test/elf/$testname
mkdir -p $t

cat <<EOF | $CC -o $t/a.o -c -x assembler -
.globl main
main:
EOF

$CC -B. -o $t/exe $t/a.o

$CC -B. -o $t/exe $t/a.o -Wl,-z,cet-report=warning >& $t/log
grep -q 'a.o: -cet-report=warning: missing GNU_PROPERTY_X86_FEATURE_1_IBT' $t/log
grep -q 'a.o: -cet-report=warning: missing GNU_PROPERTY_X86_FEATURE_1_SHSTK' $t/log

! $CC -B. -o $t/exe $t/a.o -Wl,-z,cet-report=error >& $t/log
grep -q 'a.o: -cet-report=error: missing GNU_PROPERTY_X86_FEATURE_1_IBT' $t/log
grep -q 'a.o: -cet-report=error: missing GNU_PROPERTY_X86_FEATURE_1_SHSTK' $t/log

echo OK

0 comments on commit 31a43a7

Please sign in to comment.