Implement support for PT_OPENBSD_NOBTCFI in lld(1). This can be set using
authorkettenis <kettenis@openbsd.org>
Wed, 19 Apr 2023 16:04:33 +0000 (16:04 +0000)
committerkettenis <kettenis@openbsd.org>
Wed, 19 Apr 2023 16:04:33 +0000 (16:04 +0000)
the -z nobtcfi option.

ok deraadt@

gnu/llvm/lld/ELF/Config.h
gnu/llvm/lld/ELF/Driver.cpp
gnu/llvm/lld/ELF/Writer.cpp
gnu/llvm/llvm/include/llvm/BinaryFormat/ELF.h
gnu/llvm/llvm/tools/llvm-objdump/ELFDump.cpp
gnu/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp

index e61c698..73d4c8b 100644 (file)
@@ -236,6 +236,7 @@ struct Configuration {
   bool zInitfirst;
   bool zInterpose;
   bool zKeepTextSectionPrefix;
+  bool zNoBtCfi;
   bool zNodefaultlib;
   bool zNodelete;
   bool zNodlopen;
index 24b8d78..ee98672 100644 (file)
@@ -462,7 +462,8 @@ static bool isKnownZFlag(StringRef s) {
          s == "initfirst" || s == "interpose" ||
          s == "keep-text-section-prefix" || s == "lazy" || s == "muldefs" ||
          s == "separate-code" || s == "separate-loadable-segments" ||
-         s == "start-stop-gc" || s == "nocombreloc" || s == "nocopyreloc" ||
+         s == "start-stop-gc" || s == "nobtcfi" ||
+         s == "nocombreloc" || s == "nocopyreloc" ||
          s == "nodefaultlib" || s == "nodelete" || s == "nodlopen" ||
          s == "noexecstack" || s == "nognustack" ||
          s == "nokeep-text-section-prefix" || s == "norelro" ||
@@ -1197,6 +1198,7 @@ static void readConfigs(opt::InputArgList &args) {
   config->zInterpose = hasZOption(args, "interpose");
   config->zKeepTextSectionPrefix = getZFlag(
       args, "keep-text-section-prefix", "nokeep-text-section-prefix", false);
+  config->zNoBtCfi = hasZOption(args, "nobtcfi");
   config->zNodefaultlib = hasZOption(args, "nodefaultlib");
   config->zNodelete = hasZOption(args, "nodelete");
   config->zNodlopen = hasZOption(args, "nodlopen");
index 8b5e4e2..e8de5f0 100644 (file)
@@ -2499,6 +2499,11 @@ std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs(Partition &part) {
   if (config->zWxneeded)
     addHdr(PT_OPENBSD_WXNEEDED, PF_X);
 
+  // PT_OPENBSD_NOBTCFI is an OpenBSD-specific header to mark that the
+  // executable is expected to violate branch-target CFI checks.
+  if (config->zNoBtCfi)
+    addHdr(PT_OPENBSD_NOBTCFI, PF_X);
+
   if (OutputSection *cmd = findSection(".note.gnu.property", partNo))
     addHdr(PT_GNU_PROPERTY, PF_R)->add(cmd);
 
index fa4139b..71cf3a6 100644 (file)
@@ -1306,6 +1306,7 @@ enum {
   PT_OPENBSD_MUTABLE = 0x65a3dbe5, // Like bss, but not immutable.
   PT_OPENBSD_RANDOMIZE = 0x65a3dbe6, // Fill with random data.
   PT_OPENBSD_WXNEEDED = 0x65a3dbe7,  // Program does W^X violations.
+  PT_OPENBSD_NOBTCFI = 0x65a3dbe8,   // Do not enforce branch target CFI
   PT_OPENBSD_BOOTDATA = 0x65a41be6,  // Section for boot arguments.
 
   // ARM program header types.
index 5e87efa..952a417 100644 (file)
@@ -249,6 +249,9 @@ static void printProgramHeaders(const ELFFile<ELFT> &Obj, StringRef FileName) {
     case ELF::PT_OPENBSD_MUTABLE:
       outs() << "OPENBSD_MUTABLE ";
       break;
+    case ELF::PT_OPENBSD_NOBTCFI:
+      outs() << "OPENBSD_NOBTCFI ";
+      break;
     case ELF::PT_OPENBSD_RANDOMIZE:
       outs() << "OPENBSD_RANDOMIZE ";
       break;
index f0708a7..97e6e25 100644 (file)
@@ -1372,6 +1372,7 @@ static StringRef segmentTypeToString(unsigned Arch, unsigned Type) {
     LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_MUTABLE);
     LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE);
     LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED);
+    LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_NOBTCFI);
     LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA);
   default:
     return "";