• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Update data structures for changes.
2    Copyright (C) 2000-2010, 2015, 2016 Red Hat, Inc.
3    This file is part of elfutils.
4    Written by Ulrich Drepper <drepper@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 
40 #include <system.h>
41 #include "libelfP.h"
42 #include "elf-knowledge.h"
43 
44 #ifndef LIBELFBITS
45 # define LIBELFBITS 32
46 #endif
47 
48 /* Some fields contain 32/64 sizes.  We cannot use Elf32/64_Word for those,
49    since those are both 32bits.  Elf32/64_Xword is always 64bits.  */
50 #define Elf32_SizeWord Elf32_Word
51 #define Elf64_SizeWord Elf64_Xword
52 
53 
54 static int
ELFW(default_ehdr,LIBELFBITS)55 ELFW(default_ehdr,LIBELFBITS) (Elf *elf, ElfW2(LIBELFBITS,Ehdr) *ehdr,
56 			       size_t shnum, int *change_bop)
57 {
58   /* Always write the magic bytes.  */
59   if (memcmp (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
60     {
61       memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG);
62       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
63     }
64 
65   /* Always set the file class.  */
66   update_if_changed (ehdr->e_ident[EI_CLASS], ELFW(ELFCLASS,LIBELFBITS),
67 		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
68 
69   /* Set the data encoding if necessary.  */
70   if (unlikely (ehdr->e_ident[EI_DATA] == ELFDATANONE))
71     {
72       ehdr->e_ident[EI_DATA] =
73 	BYTE_ORDER == BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB;
74       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
75     }
76   else if (unlikely (ehdr->e_ident[EI_DATA] >= ELFDATANUM))
77     {
78       __libelf_seterrno (ELF_E_DATA_ENCODING);
79       return 1;
80     }
81   else
82     *change_bop = ((BYTE_ORDER == LITTLE_ENDIAN
83 		    && ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
84 		   || (BYTE_ORDER == BIG_ENDIAN
85 		       && ehdr->e_ident[EI_DATA] != ELFDATA2MSB));
86 
87   /* Unconditionally overwrite the ELF version.  */
88   update_if_changed (ehdr->e_ident[EI_VERSION], EV_CURRENT,
89 		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
90 
91   if (unlikely (ehdr->e_version == EV_NONE))
92     {
93       ehdr->e_version = EV_CURRENT;
94       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
95     }
96   else if (unlikely (ehdr->e_version != EV_CURRENT))
97     {
98       __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
99       return 1;
100     }
101 
102   if (unlikely (shnum >= SHN_LORESERVE))
103     {
104       update_if_changed (ehdr->e_shnum, 0,
105 			 elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
106     }
107   else
108     update_if_changed (ehdr->e_shnum, shnum,
109 		       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
110 
111   if (unlikely (ehdr->e_ehsize != elf_typesize (LIBELFBITS, ELF_T_EHDR, 1)))
112     {
113       ehdr->e_ehsize = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
114       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
115     }
116 
117   /* If phnum is zero make sure e_phoff is also zero and not some random
118      value.  That would cause trouble in update_file.  */
119   if (ehdr->e_phnum == 0 && ehdr->e_phoff != 0)
120     {
121       ehdr->e_phoff = 0;
122       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
123     }
124 
125   return 0;
126 }
127 
128 
129 int64_t
130 internal_function
__elfw2(LIBELFBITS,updatenull_wrlock)131 __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
132 {
133   ElfW2(LIBELFBITS,Ehdr) *ehdr;
134   int changed = 0;
135   int ehdr_flags = 0;
136 
137   ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf);
138 
139   /* Set the default values.  */
140   if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
141     return -1;
142 
143   /* At least the ELF header is there.  */
144   ElfW2(LIBELFBITS,SizeWord) size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
145 
146   /* Set the program header position.  */
147   if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
148     (void) __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
149   if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
150     {
151       size_t phnum;
152       if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
153 	return -1;
154 
155       if (elf->flags & ELF_F_LAYOUT)
156 	{
157 	  /* The user is supposed to fill out e_phoff.  Use it and
158 	     e_phnum to determine the maximum extend.  */
159 	  size = MAX (size,
160 		      ehdr->e_phoff
161 		      + elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum));
162 	}
163       else
164 	{
165 	  update_if_changed (ehdr->e_phoff,
166 			     elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
167 			     ehdr_flags);
168 
169 	  /* We need no alignment here.  */
170 	  size += elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum);
171 	}
172     }
173 
174   if (shnum > 0)
175     {
176       struct Elf_Scn *scn1 = NULL;
177       Elf_ScnList *list;
178       bool first = true;
179 
180       assert (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0);
181 
182       if (shnum >= SHN_LORESERVE)
183 	{
184 	  /* We have to  fill in the number of sections in the header
185 	     of the zeroth section.  */
186 	  Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
187 
188 	  update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size,
189 			     shnum, scn0->shdr_flags);
190 	}
191 
192       /* Go over all sections and find out how large they are.  */
193       list = &elf->state.ELFW(elf,LIBELFBITS).scns;
194 
195       /* Find the first section. */
196       if (list->cnt > 1)
197 	scn1 = &list->data[1];
198       else if (list->next != NULL)
199 	scn1 = &list->next->data[0];
200 
201       /* Load the section headers if necessary.  This loads the
202 	 headers for all sections.  */
203       if (scn1 != NULL && scn1->shdr.ELFW(e,LIBELFBITS) == NULL)
204 	(void) __elfw2(LIBELFBITS,getshdr_wrlock) (scn1);
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 	      int64_t offset = 0;
213 
214 	      assert (shdr != NULL);
215 	      ElfW2(LIBELFBITS,SizeWord) sh_entsize = shdr->sh_entsize;
216 	      ElfW2(LIBELFBITS,SizeWord) 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 	      /* Likewise for the alignment of a compressed section.
271 	         For a SHF_COMPRESSED section set the correct
272 	         sh_addralign value, which must match the d_align of
273 	         the data (see __libelf_set_rawdata in elf_getdata.c).  */
274 	      if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
275 		{
276 		  sh_align = __libelf_type_align (ELFW(ELFCLASS,LIBELFBITS),
277 						  ELF_T_CHDR);
278 		  update_if_changed (shdr->sh_addralign, sh_align,
279 				     scn->shdr_flags);
280 		}
281 
282 	      if (scn->data_read == 0
283 		  && __libelf_set_rawdata_wrlock (scn) != 0)
284 		/* Something went wrong.  The error value is already set.  */
285 		return -1;
286 
287 	      /* Iterate over all data blocks.  */
288 	      if (list->data[cnt].data_list_rear != NULL)
289 		{
290 		  Elf_Data_List *dl = &scn->data_list;
291 
292 		  while (dl != NULL)
293 		    {
294 		      Elf_Data *data = &dl->data.d;
295 		      if (dl == &scn->data_list && data->d_buf == NULL
296 			  && scn->rawdata.d.d_buf != NULL)
297 			data = &scn->rawdata.d;
298 
299 		      if (unlikely (data->d_version != EV_CURRENT))
300 			{
301 			  __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
302 			  return -1;
303 			}
304 
305 		      if (unlikely (! powerof2 (data->d_align)))
306 			{
307 			  __libelf_seterrno (ELF_E_INVALID_ALIGN);
308 			  return -1;
309 			}
310 
311 		      sh_align = MAX (sh_align, data->d_align);
312 
313 		      if (elf->flags & ELF_F_LAYOUT)
314 			{
315 			  /* The user specified the offset and the size.
316 			     All we have to do is check whether this block
317 			     fits in the size specified for the section.  */
318 			  if (unlikely ((ElfW2(LIBELFBITS,SizeWord))
319 					(data->d_off + data->d_size)
320 					> shdr->sh_size))
321 			    {
322 			      __libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
323 			      return -1;
324 			    }
325 			}
326 		      else
327 			{
328 			  /* Determine the padding.  */
329 			  offset = ((offset + data->d_align - 1)
330 				    & ~(data->d_align - 1));
331 
332 			  update_if_changed (data->d_off, offset, changed);
333 
334 			  offset += data->d_size;
335 			}
336 
337 		      /* Next data block.  */
338 		      dl = dl->next;
339 		    }
340 		}
341 	      else
342 		/* Get the size of the section from the raw data.  If
343 		   none is available the value is zero.  */
344 		offset += scn->rawdata.d.d_size;
345 
346 	      if (elf->flags & ELF_F_LAYOUT)
347 		{
348 		  size = MAX (size,
349 			      (shdr->sh_type != SHT_NOBITS
350 			       ? shdr->sh_offset + shdr->sh_size : 0));
351 
352 		  /* The alignment must be a power of two.  This is a
353 		     requirement from the ELF specification.  Additionally
354 		     we test for the alignment of the section being large
355 		     enough for the largest alignment required by a data
356 		     block.  */
357 		  if (unlikely (! powerof2 (shdr->sh_addralign))
358 		      || unlikely ((shdr->sh_addralign ?: 1) < sh_align))
359 		    {
360 		      __libelf_seterrno (ELF_E_INVALID_ALIGN);
361 		      return -1;
362 		    }
363 		}
364 	      else
365 		{
366 		  /* How much alignment do we need for this section.  */
367 		  update_if_changed (shdr->sh_addralign, sh_align,
368 				     scn->shdr_flags);
369 
370 		  size = (size + sh_align - 1) & ~(sh_align - 1);
371 		  int offset_changed = 0;
372 		  update_if_changed (shdr->sh_offset, size, offset_changed);
373 		  changed |= offset_changed;
374 
375 		  if (offset_changed && scn->data_list_rear == NULL)
376 		    {
377 		      /* The position of the section in the file
378 			 changed.  Create the section data list.  */
379 		      if (__elf_getdata_rdlock (scn, NULL) == NULL)
380 			return -1;
381 		    }
382 
383 		  /* See whether the section size is correct.  */
384 		  int size_changed = 0;
385 		  update_if_changed (shdr->sh_size,
386 				     (ElfW2(LIBELFBITS,SizeWord)) offset,
387 				     size_changed);
388 		  changed |= size_changed;
389 
390 		  if (shdr->sh_type != SHT_NOBITS)
391 		    size += offset;
392 
393 		  scn->shdr_flags |= (offset_changed | size_changed);
394 		  scn->flags |= changed;
395 		}
396 
397 	      /* Check that the section size is actually a multiple of
398 		 the entry size.  */
399 	      if (shdr->sh_entsize != 0 && shdr->sh_entsize != 1
400 		  && (elf->flags & ELF_F_PERMISSIVE) == 0)
401 		{
402 		  /* For compressed sections check the uncompressed size.  */
403 		  ElfW2(LIBELFBITS,SizeWord) sh_size;
404 		  if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
405 		    sh_size = shdr->sh_size;
406 		  else
407 		    {
408 		      ElfW2(LIBELFBITS,Chdr) *chdr;
409 		      chdr = elfw2(LIBELFBITS,getchdr) (scn);
410 		      if (unlikely (chdr == NULL))
411 			return -1;
412 		      sh_size = chdr->ch_size;
413 		    }
414 
415 		  if (unlikely (sh_size % shdr->sh_entsize != 0))
416 		    {
417 		      __libelf_seterrno (ELF_E_INVALID_SHENTSIZE);
418 		      return -1;
419 		    }
420 		}
421 	    }
422 
423 	  assert (list->next == NULL || list->cnt == list->max);
424 
425 	  first = false;
426 	}
427       while ((list = list->next) != NULL);
428 
429       /* Store section information.  */
430       update_if_changed (ehdr->e_shentsize,
431 			 elf_typesize (LIBELFBITS, ELF_T_SHDR, 1), ehdr_flags);
432       if (elf->flags & ELF_F_LAYOUT)
433 	{
434 	  /* The user is supposed to fill out e_shoff.  Use it and
435 	     e_shnum (or sh_size of the dummy, first section header)
436 	     to determine the maximum extend.  */
437 	  size = MAX (size,
438 		      (ehdr->e_shoff
439 		       + (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
440 	}
441       else
442 	{
443 	  /* Align for section header table.
444 
445 	     Yes, we use `sizeof' and not `__alignof__' since we do not
446 	     want to be surprised by architectures with less strict
447 	     alignment rules.  */
448 #define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
449 	  size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
450 
451 	  update_if_changed (ehdr->e_shoff, size, elf->flags);
452 
453 	  /* Account for the section header size.  */
454 	  size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
455 	}
456     }
457 
458   elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags;
459 
460   return size;
461 }
462