Home | History | Annotate | Download | only in libelf
      1 /* Update data structures for changes.
      2    Copyright (C) 2000-2010, 2015 Red Hat, Inc.
      3    This file is part of elfutils.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 2000.
      5 
      6    This file is free software; you can redistribute it and/or modify
      7    it under the terms of either
      8 
      9      * the GNU Lesser General Public License as published by the Free
     10        Software Foundation; either version 3 of the License, or (at
     11        your option) any later version
     12 
     13    or
     14 
     15      * the GNU General Public License as published by the Free
     16        Software Foundation; either version 2 of the License, or (at
     17        your option) any later version
     18 
     19    or both in parallel, as here.
     20 
     21    elfutils is distributed in the hope that it will be useful, but
     22    WITHOUT ANY WARRANTY; without even the implied warranty of
     23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     24    General Public License for more details.
     25 
     26    You should have received copies of the GNU General Public License and
     27    the GNU Lesser General Public License along with this program.  If
     28    not, see <http://www.gnu.org/licenses/>.  */
     29 
     30 #ifdef HAVE_CONFIG_H
     31 # include <config.h>
     32 #endif
     33 
     34 #include <assert.h>
     35 #include <endian.h>
     36 #include <libelf.h>
     37 #include <stdbool.h>
     38 #include <string.h>
     39 #include <sys/param.h>
     40 
     41 #include "libelfP.h"
     42 #include "elf-knowledge.h"
     43 
     44 #ifndef LIBELFBITS
     45 # define LIBELFBITS 32
     46 #endif
     47 
     48 
     49 
     50 static int
     51 ELFW(default_ehdr,LIBELFBITS) (Elf *elf, ElfW2(LIBELFBITS,Ehdr) *ehdr,
     52 			       size_t shnum, int *change_bop)
     53 {
     54   /* Always write the magic bytes.  */
     55   if (memcmp (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
     56     {
     57       memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG);
     58       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
     59     }
     60 
     61   /* Always set the file class.  */
     62   update_if_changed (ehdr->e_ident[EI_CLASS], ELFW(ELFCLASS,LIBELFBITS),
     63 		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
     64 
     65   /* Set the data encoding if necessary.  */
     66   if (unlikely (ehdr->e_ident[EI_DATA] == ELFDATANONE))
     67     {
     68       ehdr->e_ident[EI_DATA] =
     69 	BYTE_ORDER == BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB;
     70       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
     71     }
     72   else if (unlikely (ehdr->e_ident[EI_DATA] >= ELFDATANUM))
     73     {
     74       __libelf_seterrno (ELF_E_DATA_ENCODING);
     75       return 1;
     76     }
     77   else
     78     *change_bop = ((BYTE_ORDER == LITTLE_ENDIAN
     79 		    && ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
     80 		   || (BYTE_ORDER == BIG_ENDIAN
     81 		       && ehdr->e_ident[EI_DATA] != ELFDATA2MSB));
     82 
     83   /* Unconditionally overwrite the ELF version.  */
     84   update_if_changed (ehdr->e_ident[EI_VERSION], EV_CURRENT,
     85 		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
     86 
     87   if (unlikely (ehdr->e_version == EV_NONE))
     88     {
     89       ehdr->e_version = EV_CURRENT;
     90       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
     91     }
     92   else if (unlikely (ehdr->e_version >= EV_NUM))
     93     {
     94       __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
     95       return 1;
     96     }
     97 
     98   if (unlikely (shnum >= SHN_LORESERVE))
     99     {
    100       update_if_changed (ehdr->e_shnum, 0,
    101 			 elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
    102     }
    103   else
    104     update_if_changed (ehdr->e_shnum, shnum,
    105 		       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
    106 
    107   if (unlikely (ehdr->e_ehsize != elf_typesize (LIBELFBITS, ELF_T_EHDR, 1)))
    108     {
    109       ehdr->e_ehsize = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
    110       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
    111     }
    112 
    113   /* If phnum is zero make sure e_phoff is also zero and not some random
    114      value.  That would cause trouble in update_file.  */
    115   if (ehdr->e_phnum == 0 && ehdr->e_phoff != 0)
    116     {
    117       ehdr->e_phoff = 0;
    118       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
    119     }
    120 
    121   return 0;
    122 }
    123 
    124 
    125 off_t
    126 internal_function
    127 __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
    128 {
    129   ElfW2(LIBELFBITS,Ehdr) *ehdr;
    130   int changed = 0;
    131   int ehdr_flags = 0;
    132 
    133   ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf);
    134 
    135   /* Set the default values.  */
    136   if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
    137     return -1;
    138 
    139   /* At least the ELF header is there.  */
    140   off_t size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
    141 
    142   /* Set the program header position.  */
    143   if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL
    144       && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN
    145 	  || ehdr->e_type == ET_CORE))
    146     (void) __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
    147   if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
    148     {
    149       /* Only executables, shared objects, and core files have a program
    150 	 header.  */
    151       if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
    152 	  && unlikely (ehdr->e_type != ET_CORE))
    153 	{
    154 	  __libelf_seterrno (ELF_E_INVALID_PHDR);
    155 	  return -1;
    156 	}
    157 
    158       size_t phnum;
    159       if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
    160 	return -1;
    161 
    162       if (elf->flags & ELF_F_LAYOUT)
    163 	{
    164 	  /* The user is supposed to fill out e_phoff.  Use it and
    165 	     e_phnum to determine the maximum extend.  */
    166 	  size = MAX ((size_t) size,
    167 		      ehdr->e_phoff
    168 		      + elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum));
    169 	}
    170       else
    171 	{
    172 	  update_if_changed (ehdr->e_phoff,
    173 			     elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
    174 			     ehdr_flags);
    175 
    176 	  /* We need no alignment here.  */
    177 	  size += elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum);
    178 	}
    179     }
    180 
    181   if (shnum > 0)
    182     {
    183       Elf_ScnList *list;
    184       bool first = true;
    185 
    186       assert (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0);
    187 
    188       if (shnum >= SHN_LORESERVE)
    189 	{
    190 	  /* We have to  fill in the number of sections in the header
    191 	     of the zeroth section.  */
    192 	  Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
    193 
    194 	  update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size,
    195 			     shnum, scn0->shdr_flags);
    196 	}
    197 
    198       /* Go over all sections and find out how large they are.  */
    199       list = &elf->state.ELFW(elf,LIBELFBITS).scns;
    200 
    201       /* Load the section headers if necessary.  This loads the
    202 	 headers for all sections.  */
    203       if (list->data[1].shdr.ELFW(e,LIBELFBITS) == NULL)
    204 	(void) __elfw2(LIBELFBITS,getshdr_wrlock) (&list->data[1]);
    205 
    206       do
    207 	{
    208 	  for (size_t cnt = first == true; cnt < list->cnt; ++cnt)
    209 	    {
    210 	      Elf_Scn *scn = &list->data[cnt];
    211 	      ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
    212 	      off_t offset = 0;
    213 
    214 	      assert (shdr != NULL);
    215 	      ElfW2(LIBELFBITS,Word) sh_entsize = shdr->sh_entsize;
    216 	      ElfW2(LIBELFBITS,Word) sh_align = shdr->sh_addralign ?: 1;
    217 	      if (unlikely (! powerof2 (sh_align)))
    218 		{
    219 		  __libelf_seterrno (ELF_E_INVALID_ALIGN);
    220 		  return -1;
    221 		}
    222 
    223 	      /* Set the sh_entsize value if we can reliably detect it.  */
    224 	      switch (shdr->sh_type)
    225 		{
    226 		case SHT_SYMTAB:
    227 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
    228 		  break;
    229 		case SHT_RELA:
    230 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELA, 1);
    231 		  break;
    232 		case SHT_GROUP:
    233 		  /* Only relocatable files can contain section groups.  */
    234 		  if (ehdr->e_type != ET_REL)
    235 		    {
    236 		      __libelf_seterrno (ELF_E_GROUP_NOT_REL);
    237 		      return -1;
    238 		    }
    239 		  /* FALLTHROUGH */
    240 		case SHT_SYMTAB_SHNDX:
    241 		  sh_entsize = elf_typesize (32, ELF_T_WORD, 1);
    242 		  break;
    243 		case SHT_HASH:
    244 		  sh_entsize = SH_ENTSIZE_HASH (ehdr);
    245 		  break;
    246 		case SHT_DYNAMIC:
    247 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_DYN, 1);
    248 		  break;
    249 		case SHT_REL:
    250 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_REL, 1);
    251 		  break;
    252 		case SHT_DYNSYM:
    253 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
    254 		  break;
    255 		case SHT_SUNW_move:
    256 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_MOVE, 1);
    257 		  break;
    258 		case SHT_SUNW_syminfo:
    259 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYMINFO, 1);
    260 		  break;
    261 		default:
    262 		  break;
    263 		}
    264 
    265 	      /* If the section header contained the wrong entry size
    266 		 correct it and mark the header as modified.  */
    267 	      update_if_changed (shdr->sh_entsize, sh_entsize,
    268 				 scn->shdr_flags);
    269 
    270 	      if (scn->data_read == 0
    271 		  && __libelf_set_rawdata_wrlock (scn) != 0)
    272 		/* Something went wrong.  The error value is already set.  */
    273 		return -1;
    274 
    275 	      /* Iterate over all data blocks.  */
    276 	      if (list->data[cnt].data_list_rear != NULL)
    277 		{
    278 		  Elf_Data_List *dl = &scn->data_list;
    279 
    280 		  while (dl != NULL)
    281 		    {
    282 		      Elf_Data *data = &dl->data.d;
    283 		      if (dl == &scn->data_list && data->d_buf == NULL
    284 			  && scn->rawdata.d.d_buf != NULL)
    285 			data = &scn->rawdata.d;
    286 
    287 		      if (unlikely (data->d_version == EV_NONE)
    288 			  || unlikely (data->d_version >= EV_NUM))
    289 			{
    290 			  __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
    291 			  return -1;
    292 			}
    293 
    294 		      if (unlikely (! powerof2 (data->d_align)))
    295 			{
    296 			  __libelf_seterrno (ELF_E_INVALID_ALIGN);
    297 			  return -1;
    298 			}
    299 
    300 		      sh_align = MAX (sh_align, data->d_align);
    301 
    302 		      if (elf->flags & ELF_F_LAYOUT)
    303 			{
    304 			  /* The user specified the offset and the size.
    305 			     All we have to do is check whether this block
    306 			     fits in the size specified for the section.  */
    307 			  if (unlikely ((GElf_Word) (data->d_off
    308 						     + data->d_size)
    309 					> shdr->sh_size))
    310 			    {
    311 			      __libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
    312 			      return -1;
    313 			    }
    314 			}
    315 		      else
    316 			{
    317 			  /* Determine the padding.  */
    318 			  offset = ((offset + data->d_align - 1)
    319 				    & ~(data->d_align - 1));
    320 
    321 			  update_if_changed (data->d_off, offset, changed);
    322 
    323 			  offset += data->d_size;
    324 			}
    325 
    326 		      /* Next data block.  */
    327 		      dl = dl->next;
    328 		    }
    329 		}
    330 	      else
    331 		/* Get the size of the section from the raw data.  If
    332 		   none is available the value is zero.  */
    333 		offset += scn->rawdata.d.d_size;
    334 
    335 	      if (elf->flags & ELF_F_LAYOUT)
    336 		{
    337 		  size = MAX ((GElf_Word) size,
    338 			      (shdr->sh_type != SHT_NOBITS
    339 			       ? shdr->sh_offset + shdr->sh_size : 0));
    340 
    341 		  /* The alignment must be a power of two.  This is a
    342 		     requirement from the ELF specification.  Additionally
    343 		     we test for the alignment of the section being large
    344 		     enough for the largest alignment required by a data
    345 		     block.  */
    346 		  if (unlikely (! powerof2 (shdr->sh_addralign))
    347 		      || unlikely ((shdr->sh_addralign ?: 1) < sh_align))
    348 		    {
    349 		      __libelf_seterrno (ELF_E_INVALID_ALIGN);
    350 		      return -1;
    351 		    }
    352 		}
    353 	      else
    354 		{
    355 		  /* How much alignment do we need for this section.  */
    356 		  update_if_changed (shdr->sh_addralign, sh_align,
    357 				     scn->shdr_flags);
    358 
    359 		  size = (size + sh_align - 1) & ~(sh_align - 1);
    360 		  int offset_changed = 0;
    361 		  update_if_changed (shdr->sh_offset, (GElf_Word) size,
    362 				     offset_changed);
    363 		  changed |= offset_changed;
    364 
    365 		  if (offset_changed && scn->data_list_rear == NULL)
    366 		    {
    367 		      /* The position of the section in the file
    368 			 changed.  Create the section data list.  */
    369 		      if (__elf_getdata_rdlock (scn, NULL) == NULL)
    370 			return -1;
    371 		    }
    372 
    373 		  /* See whether the section size is correct.  */
    374 		  update_if_changed (shdr->sh_size, (GElf_Word) offset,
    375 				     changed);
    376 
    377 		  if (shdr->sh_type != SHT_NOBITS)
    378 		    size += offset;
    379 
    380 		  scn->flags |= changed;
    381 		}
    382 
    383 	      /* Check that the section size is actually a multiple of
    384 		 the entry size.  */
    385 	      if (shdr->sh_entsize != 0 && shdr->sh_entsize != 1
    386 		  && (elf->flags & ELF_F_PERMISSIVE) == 0)
    387 		{
    388 		  /* For compressed sections check the uncompressed size.  */
    389 		  ElfW2(LIBELFBITS,Word) sh_size;
    390 		  if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
    391 		    sh_size = shdr->sh_size;
    392 		  else
    393 		    {
    394 		      ElfW2(LIBELFBITS,Chdr) *chdr;
    395 		      chdr = elfw2(LIBELFBITS,getchdr) (scn);
    396 		      if (unlikely (chdr == NULL))
    397 			return -1;
    398 		      sh_size = chdr->ch_size;
    399 		    }
    400 
    401 		  if (unlikely (sh_size % shdr->sh_entsize != 0))
    402 		    {
    403 		      __libelf_seterrno (ELF_E_INVALID_SHENTSIZE);
    404 		      return -1;
    405 		    }
    406 		}
    407 	    }
    408 
    409 	  assert (list->next == NULL || list->cnt == list->max);
    410 
    411 	  first = false;
    412 	}
    413       while ((list = list->next) != NULL);
    414 
    415       /* Store section information.  */
    416       update_if_changed (ehdr->e_shentsize,
    417 			 elf_typesize (LIBELFBITS, ELF_T_SHDR, 1), ehdr_flags);
    418       if (elf->flags & ELF_F_LAYOUT)
    419 	{
    420 	  /* The user is supposed to fill out e_shoff.  Use it and
    421 	     e_shnum (or sh_size of the dummy, first section header)
    422 	     to determine the maximum extend.  */
    423 	  size = MAX ((GElf_Word) size,
    424 		      (ehdr->e_shoff
    425 		       + (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
    426 	}
    427       else
    428 	{
    429 	  /* Align for section header table.
    430 
    431 	     Yes, we use `sizeof' and not `__alignof__' since we do not
    432 	     want to be surprised by architectures with less strict
    433 	     alignment rules.  */
    434 #define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
    435 	  size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
    436 
    437 	  update_if_changed (ehdr->e_shoff, (GElf_Word) size, elf->flags);
    438 
    439 	  /* Account for the section header size.  */
    440 	  size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
    441 	}
    442     }
    443 
    444   elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags;
    445 
    446   return size;
    447 }
    448