Implement --execute-only (and turn --no-execute-only from a no-op into an
authorkettenis <kettenis@openbsd.org>
Mon, 9 Jan 2023 14:36:38 +0000 (14:36 +0000)
committerkettenis <kettenis@openbsd.org>
Mon, 9 Jan 2023 14:36:38 +0000 (14:36 +0000)
options that does the opposite).

Note that this option is likely to be ineffective without changes to the
linker scripts.  A change that adjusts the hppa linker scripts will follow
shortly.  Other architectures will need some work.

ok deraadt@

gnu/usr.bin/binutils-2.17/bfd/elf.c
gnu/usr.bin/binutils-2.17/include/bfdlink.h
gnu/usr.bin/binutils-2.17/ld/lexsup.c

index 2d2ed03..a2804f5 100644 (file)
@@ -4597,7 +4597,8 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
 
          if (! m->p_flags_valid)
            {
-             p->p_flags |= PF_R;
+             if ((flags & SEC_CODE) == 0 || !link_info->execute_only)
+               p->p_flags |= PF_R;
              if ((flags & SEC_CODE) != 0)
                p->p_flags |= PF_X;
              if ((flags & SEC_READONLY) == 0)
index e419f77..8c17bf8 100644 (file)
@@ -264,6 +264,9 @@ struct bfd_link_info
   /* TRUE if ok to have multiple definition.  */
   unsigned int allow_multiple_definition: 1;
 
+  /* TRUE if output program should be marked to request W^X permission */
+  unsigned int execute_only: 1;
+
   /* TRUE if output program should be marked to request W^X permission */
   unsigned int wxneeded: 1;
 
index ab1da63..2e3a6e9 100644 (file)
@@ -77,6 +77,8 @@ enum option_values
   OPTION_EL,
   OPTION_EMBEDDED_RELOCS,
   OPTION_EXPORT_DYNAMIC,
+  OPTION_EXECUTE_ONLY,
+  OPTION_NO_EXECUTE_ONLY,
   OPTION_HELP,
   OPTION_IGNORE,
   OPTION_MAP,
@@ -361,6 +363,10 @@ static const struct ld_option ld_options[] =
     TWO_DASHES },
   { {"embedded-relocs", no_argument, NULL, OPTION_EMBEDDED_RELOCS},
     '\0', NULL, N_("Generate embedded relocs"), TWO_DASHES},
+  { {"execute-only", no_argument, NULL, OPTION_EXECUTE_ONLY},
+    '\0', NULL, N_("Mark executable sections unreadable"), TWO_DASHES},
+  { {"no-execute-only", no_argument, NULL, OPTION_NO_EXECUTE_ONLY},
+    '\0', NULL, N_("Do not mark executable sections unreadable"), TWO_DASHES},
   { {"fatal-warnings", no_argument, NULL, OPTION_WARN_FATAL},
     '\0', NULL, N_("Treat warnings as errors"),
     TWO_DASHES },
@@ -525,8 +531,6 @@ static const struct ld_option ld_options[] =
     TWO_DASHES },
   { {"wrap", required_argument, NULL, OPTION_WRAP},
     '\0', N_("SYMBOL"), N_("Use wrapper functions for SYMBOL"), TWO_DASHES },
-  { {"no-execute-only", no_argument, NULL, OPTION_IGNORE},
-    '\0', NULL, N_("Ignored for lld compatibility"), TWO_DASHES},
 };
 
 #define OPTION_COUNT ARRAY_SIZE (ld_options)
@@ -771,6 +775,12 @@ parse_args (unsigned argc, char **argv)
        case OPTION_EMBEDDED_RELOCS:
          command_line.embedded_relocs = TRUE;
          break;
+       case OPTION_EXECUTE_ONLY:
+         link_info.execute_only = TRUE;
+         break;
+       case OPTION_NO_EXECUTE_ONLY:
+         link_info.execute_only = FALSE;
+         break;
        case OPTION_EXPORT_DYNAMIC:
        case 'E': /* HP/UX compatibility.  */
          link_info.export_dynamic = TRUE;