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@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
ELFW(default_ehdr,LIBELFBITS)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
__elfw2(LIBELFBITS,updatenull_wrlock)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