patches/binutils/2.20/150-pt-pax-flags-20090909.patch
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Tue Jan 12 19:24:03 2010 +0100 (2010-01-12)
changeset 1761 88020b2c3246
permissions -rw-r--r--
scripts/functions: change handling of nochdir

- 'nochdir' must be the first option
- have systematic pushd/popd, even if nochdir
     1 --- binutils-2.20/bfd/elf-bfd.h
     2 +++ binutils-2.20/bfd/elf-bfd.h
     3 @@ -1527,6 +1527,9 @@ struct elf_obj_tdata
     4    /* Segment flags for the PT_GNU_STACK segment.  */
     5    unsigned int stack_flags;
     6  
     7 +  /* Segment flags for the PT_PAX_FLAGS segment.  */
     8 +  unsigned int pax_flags;
     9 +
    10    /* Symbol version definitions in external objects.  */
    11    Elf_Internal_Verdef *verdef;
    12  
    13 --- binutils-2.20/bfd/elf.c
    14 +++ binutils-2.20/bfd/elf.c
    15 @@ -1081,6 +1081,7 @@ get_segment_type (unsigned int p_type)
    16      case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
    17      case PT_GNU_STACK: pt = "STACK"; break;
    18      case PT_GNU_RELRO: pt = "RELRO"; break;
    19 +    case PT_PAX_FLAGS: pt = "PAX_FLAGS"; break;
    20      default: pt = NULL; break;
    21      }
    22    return pt;
    23 @@ -2379,6 +2380,9 @@ bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int index)
    24      case PT_GNU_RELRO:
    25        return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "relro");
    26  
    27 +    case PT_PAX_FLAGS:
    28 +      return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "pax_flags");
    29 +
    30      default:
    31        /* Check for any processor-specific program segment types.  */
    32        bed = get_elf_backend_data (abfd);
    33 @@ -3393,6 +3397,11 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info)
    34        ++segs;
    35      }
    36  
    37 +    {
    38 +      /* We need a PT_PAX_FLAGS segment.  */
    39 +      ++segs;
    40 +    }
    41 +
    42    for (s = abfd->sections; s != NULL; s = s->next)
    43      {
    44        if ((s->flags & SEC_LOAD) != 0
    45 @@ -3972,6 +3981,20 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
    46  	    }
    47  	}
    48  
    49 +    {
    50 +      amt = sizeof (struct elf_segment_map);
    51 +      m = bfd_zalloc (abfd, amt);
    52 +      if (m == NULL)
    53 +	goto error_return;
    54 +      m->next = NULL;
    55 +      m->p_type = PT_PAX_FLAGS;
    56 +      m->p_flags = elf_tdata (abfd)->pax_flags;
    57 +      m->p_flags_valid = 1;
    58 +
    59 +      *pm = m;
    60 +      pm = &m->next;
    61 +    }
    62 +
    63        free (sections);
    64        elf_tdata (abfd)->segment_map = mfirst;
    65      }
    66 @@ -5176,7 +5199,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
    67         6. PT_TLS segment includes only SHF_TLS sections.
    68         7. SHF_TLS sections are only in PT_TLS or PT_LOAD segments.
    69         8. PT_DYNAMIC should not contain empty sections at the beginning
    70 -	  (with the possible exception of .dynamic).  */
    71 +	  (with the possible exception of .dynamic).
    72 +       9. PT_PAX_FLAGS segments do not include any sections.  */
    73  #define IS_SECTION_IN_INPUT_SEGMENT(section, segment, bed)		\
    74    ((((segment->p_paddr							\
    75        ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr)	\
    76 @@ -5184,6 +5208,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
    77       && (section->flags & SEC_ALLOC) != 0)				\
    78      || IS_NOTE (segment, section))					\
    79     && segment->p_type != PT_GNU_STACK					\
    80 +   && segment->p_type != PT_PAX_FLAGS					\
    81     && (segment->p_type != PT_TLS					\
    82         || (section->flags & SEC_THREAD_LOCAL))				\
    83     && (segment->p_type == PT_LOAD					\
    84 --- binutils-2.20/bfd/elflink.c
    85 +++ binutils-2.20/bfd/elflink.c
    86 @@ -5465,16 +5465,30 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
    87      return TRUE;
    88  
    89    bed = get_elf_backend_data (output_bfd);
    90 +
    91 +  elf_tdata (output_bfd)->pax_flags = PF_NORANDEXEC;
    92 +  if (info->execheap)
    93 +    elf_tdata (output_bfd)->pax_flags |= PF_NOMPROTECT;
    94 +  else if (info->noexecheap)
    95 +    elf_tdata (output_bfd)->pax_flags |= PF_MPROTECT;
    96 +
    97    if (info->execstack)
    98 -    elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
    99 +    {
   100 +      elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
   101 +      elf_tdata (output_bfd)->pax_flags |= PF_EMUTRAMP;
   102 +    }
   103    else if (info->noexecstack)
   104 -    elf_tdata (output_bfd)->stack_flags = PF_R | PF_W;
   105 +    {
   106 +      elf_tdata (output_bfd)->stack_flags = PF_R | PF_W;
   107 +      elf_tdata (output_bfd)->pax_flags |= PF_NOEMUTRAMP;
   108 +    }
   109    else
   110      {
   111        bfd *inputobj;
   112        asection *notesec = NULL;
   113        int exec = 0;
   114  
   115 +      elf_tdata (output_bfd)->pax_flags |= PF_NOEMUTRAMP;
   116        for (inputobj = info->input_bfds;
   117  	   inputobj;
   118  	   inputobj = inputobj->link_next)
   119 @@ -5487,7 +5501,11 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
   120  	  if (s)
   121  	    {
   122  	      if (s->flags & SEC_CODE)
   123 -		exec = PF_X;
   124 +		{
   125 +		  elf_tdata (output_bfd)->pax_flags &= ~PF_NOEMUTRAMP;
   126 +		  elf_tdata (output_bfd)->pax_flags |= PF_EMUTRAMP;
   127 +		  exec = PF_X;
   128 +		}
   129  	      notesec = s;
   130  	    }
   131  	  else if (bed->default_execstack)
   132 --- binutils-2.20/binutils/readelf.c
   133 +++ binutils-2.20/binutils/readelf.c
   134 @@ -2556,6 +2556,7 @@ get_segment_type (unsigned long p_type)
   135  			return "GNU_EH_FRAME";
   136      case PT_GNU_STACK:	return "GNU_STACK";
   137      case PT_GNU_RELRO:  return "GNU_RELRO";
   138 +    case PT_PAX_FLAGS:  return "PAX_FLAGS";
   139  
   140      default:
   141        if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
   142 --- binutils-2.20/include/bfdlink.h
   143 +++ binutils-2.20/include/bfdlink.h
   144 @@ -319,6 +319,14 @@ struct bfd_link_info
   145    /* TRUE if PT_GNU_RELRO segment should be created.  */
   146    unsigned int relro: 1;
   147  
   148 +  /* TRUE if PT_PAX_FLAGS segment should be created with PF_NOMPROTECT
   149 +     flags.  */
   150 +  unsigned int execheap: 1;
   151 +
   152 +  /* TRUE if PT_PAX_FLAGS segment should be created with PF_MPROTECT
   153 +     flags.  */
   154 +  unsigned int noexecheap: 1;
   155 +
   156    /* TRUE if we should warn when adding a DT_TEXTREL to a shared object.  */
   157    unsigned int warn_shared_textrel: 1;
   158  
   159 --- binutils-2.20/include/elf/common.h
   160 +++ binutils-2.20/include/elf/common.h
   161 @@ -422,6 +422,7 @@
   162  #define PT_SUNW_EH_FRAME PT_GNU_EH_FRAME      /* Solaris uses the same value */
   163  #define PT_GNU_STACK	(PT_LOOS + 0x474e551) /* Stack flags */
   164  #define PT_GNU_RELRO	(PT_LOOS + 0x474e552) /* Read-only after relocation */
   165 +#define PT_PAX_FLAGS	(PT_LOOS + 0x5041580) /* PaX flags */
   166  
   167  /* Program segment permissions, in program header p_flags field.  */
   168  
   169 @@ -432,6 +433,21 @@
   170  #define PF_MASKOS	0x0FF00000	/* New value, Oct 4, 1999 Draft */
   171  #define PF_MASKPROC	0xF0000000	/* Processor-specific reserved bits */
   172  
   173 +/* Flags to control PaX behavior.  */
   174 +
   175 +#define PF_PAGEEXEC	(1 << 4)	/* Enable  PAGEEXEC */
   176 +#define PF_NOPAGEEXEC	(1 << 5)	/* Disable PAGEEXEC */
   177 +#define PF_SEGMEXEC	(1 << 6)	/* Enable  SEGMEXEC */
   178 +#define PF_NOSEGMEXEC	(1 << 7)	/* Disable SEGMEXEC */
   179 +#define PF_MPROTECT	(1 << 8)	/* Enable  MPROTECT */
   180 +#define PF_NOMPROTECT	(1 << 9)	/* Disable MPROTECT */
   181 +#define PF_RANDEXEC	(1 << 10)	/* Enable  RANDEXEC */
   182 +#define PF_NORANDEXEC	(1 << 11)	/* Disable RANDEXEC */
   183 +#define PF_EMUTRAMP	(1 << 12)	/* Enable  EMUTRAMP */
   184 +#define PF_NOEMUTRAMP	(1 << 13)	/* Disable EMUTRAMP */
   185 +#define PF_RANDMMAP	(1 << 14)	/* Enable  RANDMMAP */
   186 +#define PF_NORANDMMAP	(1 << 15)	/* Disable RANDMMAP */
   187 +
   188  /* Values for section header, sh_type field.  */
   189  
   190  #define SHT_NULL	0		/* Section header table entry unused */
   191 --- binutils-2.20/ld/emultempl/elf32.em
   192 +++ binutils-2.20/ld/emultempl/elf32.em
   193 @@ -2159,6 +2159,16 @@ fragment <<EOF
   194  	  link_info.noexecstack = TRUE;
   195  	  link_info.execstack = FALSE;
   196  	}
   197 +      else if (strcmp (optarg, "execheap") == 0)
   198 +	{
   199 +	  link_info.execheap = TRUE;
   200 +	  link_info.noexecheap = FALSE;
   201 +	}
   202 +      else if (strcmp (optarg, "noexecheap") == 0)
   203 +	{
   204 +	  link_info.noexecheap = TRUE;
   205 +	  link_info.execheap = FALSE;
   206 +	}
   207  EOF
   208  
   209    if test -n "$COMMONPAGESIZE"; then
   210 @@ -2237,6 +2247,8 @@ fragment <<EOF
   211    fprintf (file, _("\
   212    -z execstack                Mark executable as requiring executable stack\n"));
   213    fprintf (file, _("\
   214 +  -z execheap                 Mark executable as requiring executable heap\n"));
   215 +  fprintf (file, _("\
   216    -z initfirst                Mark DSO to be initialized first at runtime\n"));
   217    fprintf (file, _("\
   218    -z interpose                Mark object to interpose all DSOs but executable\n"));
   219 @@ -2260,6 +2272,8 @@ fragment <<EOF
   220    -z nodump                   Mark DSO not available to dldump\n"));
   221    fprintf (file, _("\
   222    -z noexecstack              Mark executable as not requiring executable stack\n"));
   223 +  fprintf (file, _("\
   224 +  -z noexecheap               Mark executable as not requiring executable heap\n"));
   225  EOF
   226  
   227    if test -n "$COMMONPAGESIZE"; then
   228 --- binutils-2.20/ld/ldgram.y
   229 +++ binutils-2.20/ld/ldgram.y
   230 @@ -1116,6 +1116,8 @@ phdr_type:
   231  			    $$ = exp_intop (0x6474e550);
   232  			  else if (strcmp (s, "PT_GNU_STACK") == 0)
   233  			    $$ = exp_intop (0x6474e551);
   234 +			  else if (strcmp (s, "PT_PAX_FLAGS") == 0)
   235 +			    $$ = exp_intop (0x65041580);
   236  			  else
   237  			    {
   238  			      einfo (_("\