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