1 /* Update data structures for changes.
2    Copyright (C) 2000-2010 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       || unlikely (ehdr->e_version >= EV_NUM))
89     {
90       __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
91       return 1;
92     }
93 
94   if (unlikely (shnum >= SHN_LORESERVE))
95     {
96       update_if_changed (ehdr->e_shnum, 0,
97 			 elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
98     }
99   else
100     update_if_changed (ehdr->e_shnum, shnum,
101 		       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
102 
103   if (unlikely (ehdr->e_ehsize != elf_typesize (LIBELFBITS, ELF_T_EHDR, 1)))
104     {
105       ehdr->e_ehsize = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
106       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
107     }
108 
109   return 0;
110 }
111 
112 
113 off_t
114 internal_function
__elfw2(LIBELFBITS,updatenull_wrlock)115 __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
116 {
117   ElfW2(LIBELFBITS,Ehdr) *ehdr;
118   int changed = 0;
119   int ehdr_flags = 0;
120 
121   ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf);
122 
123   /* Set the default values.  */
124   if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
125     return -1;
126 
127   /* At least the ELF header is there.  */
128   off_t size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
129 
130   /* Set the program header position.  */
131   if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL
132       && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN
133 	  || ehdr->e_type == ET_CORE))
134     (void) __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
135   if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
136     {
137       /* Only executables, shared objects, and core files have a program
138 	 header.  */
139       if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
140 	  && unlikely (ehdr->e_type != ET_CORE))
141 	{
142 	  __libelf_seterrno (ELF_E_INVALID_PHDR);
143 	  return -1;
144 	}
145 
146       size_t phnum;
147       if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
148 	return -1;
149 
150       if (elf->flags & ELF_F_LAYOUT)
151 	{
152 	  /* The user is supposed to fill out e_phoff.  Use it and
153 	     e_phnum to determine the maximum extend.  */
154 	  size = MAX ((size_t) size,
155 		      ehdr->e_phoff
156 		      + elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum));
157 	}
158       else
159 	{
160 	  update_if_changed (ehdr->e_phoff,
161 			     elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
162 			     ehdr_flags);
163 
164 	  /* We need no alignment here.  */
165 	  size += elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum);
166 	}
167     }
168 
169   if (shnum > 0)
170     {
171       Elf_ScnList *list;
172       bool first = true;
173 
174       assert (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0);
175 
176       if (shnum >= SHN_LORESERVE)
177 	{
178 	  /* We have to  fill in the number of sections in the header
179 	     of the zeroth section.  */
180 	  Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
181 
182 	  update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size,
183 			     shnum, scn0->shdr_flags);
184 	}
185 
186       /* Go over all sections and find out how large they are.  */
187       list = &elf->state.ELFW(elf,LIBELFBITS).scns;
188 
189       /* Load the section headers if necessary.  This loads the
190 	 headers for all sections.  */
191       if (list->data[1].shdr.ELFW(e,LIBELFBITS) == NULL)
192 	(void) __elfw2(LIBELFBITS,getshdr_wrlock) (&list->data[1]);
193 
194       do
195 	{
196 	  for (size_t cnt = first == true; cnt < list->cnt; ++cnt)
197 	    {
198 	      Elf_Scn *scn = &list->data[cnt];
199 	      ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
200 	      off_t offset = 0;
201 
202 	      assert (shdr != NULL);
203 	      ElfW2(LIBELFBITS,Word) sh_entsize = shdr->sh_entsize;
204 	      ElfW2(LIBELFBITS,Word) sh_align = shdr->sh_addralign ?: 1;
205 
206 	      /* Set the sh_entsize value if we can reliably detect it.  */
207 	      switch (shdr->sh_type)
208 		{
209 		case SHT_SYMTAB:
210 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
211 		  break;
212 		case SHT_RELA:
213 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELA, 1);
214 		  break;
215 		case SHT_GROUP:
216 		  /* Only relocatable files can contain section groups.  */
217 		  if (ehdr->e_type != ET_REL)
218 		    {
219 		      __libelf_seterrno (ELF_E_GROUP_NOT_REL);
220 		      return -1;
221 		    }
222 		  /* FALLTHROUGH */
223 		case SHT_SYMTAB_SHNDX:
224 		  sh_entsize = elf_typesize (32, ELF_T_WORD, 1);
225 		  break;
226 		case SHT_HASH:
227 		  sh_entsize = SH_ENTSIZE_HASH (ehdr);
228 		  break;
229 		case SHT_DYNAMIC:
230 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_DYN, 1);
231 		  break;
232 		case SHT_REL:
233 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_REL, 1);
234 		  break;
235 		case SHT_DYNSYM:
236 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
237 		  break;
238 		case SHT_SUNW_move:
239 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_MOVE, 1);
240 		  break;
241 		case SHT_SUNW_syminfo:
242 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYMINFO, 1);
243 		  break;
244 		default:
245 		  break;
246 		}
247 
248 	      /* If the section header contained the wrong entry size
249 		 correct it and mark the header as modified.  */
250 	      update_if_changed (shdr->sh_entsize, sh_entsize,
251 				 scn->shdr_flags);
252 
253 	      if (scn->data_read == 0
254 		  && __libelf_set_rawdata_wrlock (scn) != 0)
255 		/* Something went wrong.  The error value is already set.  */
256 		return -1;
257 
258 	      /* Iterate over all data blocks.  */
259 	      if (list->data[cnt].data_list_rear != NULL)
260 		{
261 		  Elf_Data_List *dl = &scn->data_list;
262 
263 		  while (dl != NULL)
264 		    {
265 		      Elf_Data *data = &dl->data.d;
266 		      if (dl == &scn->data_list && data->d_buf == NULL
267 			  && scn->rawdata.d.d_buf != NULL)
268 			data = &scn->rawdata.d;
269 
270 		      if (unlikely (data->d_version == EV_NONE)
271 			  || unlikely (data->d_version >= EV_NUM))
272 			{
273 			  __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
274 			  return -1;
275 			}
276 
277 		      if (unlikely (! powerof2 (data->d_align)))
278 			{
279 			  __libelf_seterrno (ELF_E_INVALID_ALIGN);
280 			  return -1;
281 			}
282 
283 		      sh_align = MAX (sh_align, data->d_align);
284 
285 		      if (elf->flags & ELF_F_LAYOUT)
286 			{
287 			  /* The user specified the offset and the size.
288 			     All we have to do is check whether this block
289 			     fits in the size specified for the section.  */
290 			  if (unlikely ((GElf_Word) (data->d_off
291 						     + data->d_size)
292 					> shdr->sh_size))
293 			    {
294 			      __libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
295 			      return -1;
296 			    }
297 			}
298 		      else
299 			{
300 			  /* Determine the padding.  */
301 			  offset = ((offset + data->d_align - 1)
302 				    & ~(data->d_align - 1));
303 
304 			  update_if_changed (data->d_off, offset, changed);
305 
306 			  offset += data->d_size;
307 			}
308 
309 		      /* Next data block.  */
310 		      dl = dl->next;
311 		    }
312 		}
313 	      else
314 		/* Get the size of the section from the raw data.  If
315 		   none is available the value is zero.  */
316 		offset += scn->rawdata.d.d_size;
317 
318 	      if (elf->flags & ELF_F_LAYOUT)
319 		{
320 		  size = MAX ((GElf_Word) size,
321 			      shdr->sh_offset
322 			      + (shdr->sh_type != SHT_NOBITS
323 				 ? shdr->sh_size : 0));
324 
325 		  /* The alignment must be a power of two.  This is a
326 		     requirement from the ELF specification.  Additionally
327 		     we test for the alignment of the section being large
328 		     enough for the largest alignment required by a data
329 		     block.  */
330 		  if (unlikely (! powerof2 (shdr->sh_addralign))
331 		      || unlikely (shdr->sh_addralign < sh_align))
332 		    {
333 		      __libelf_seterrno (ELF_E_INVALID_ALIGN);
334 		      return -1;
335 		    }
336 		}
337 	      else
338 		{
339 		  /* How much alignment do we need for this section.  */
340 		  update_if_changed (shdr->sh_addralign, sh_align,
341 				     scn->shdr_flags);
342 
343 		  size = (size + sh_align - 1) & ~(sh_align - 1);
344 		  int offset_changed = 0;
345 		  update_if_changed (shdr->sh_offset, (GElf_Word) size,
346 				     offset_changed);
347 		  changed |= offset_changed;
348 
349 		  if (offset_changed && scn->data_list_rear == NULL)
350 		    {
351 		      /* The position of the section in the file
352 			 changed.  Create the section data list.  */
353 		      if (__elf_getdata_rdlock (scn, NULL) == NULL)
354 			return -1;
355 		    }
356 
357 		  /* See whether the section size is correct.  */
358 		  update_if_changed (shdr->sh_size, (GElf_Word) offset,
359 				     changed);
360 
361 		  if (shdr->sh_type != SHT_NOBITS)
362 		    size += offset;
363 
364 		  scn->flags |= changed;
365 		}
366 
367 	      /* Check that the section size is actually a multiple of
368 		 the entry size.  */
369 	      if (shdr->sh_entsize != 0
370 		  && unlikely (shdr->sh_size % shdr->sh_entsize != 0)
371 		  && (elf->flags & ELF_F_PERMISSIVE) == 0)
372 		{
373 		  __libelf_seterrno (ELF_E_INVALID_SHENTSIZE);
374 		  return -1;
375 		}
376 	    }
377 
378 	  assert (list->next == NULL || list->cnt == list->max);
379 
380 	  first = false;
381 	}
382       while ((list = list->next) != NULL);
383 
384       /* Store section information.  */
385       if (elf->flags & ELF_F_LAYOUT)
386 	{
387 	  /* The user is supposed to fill out e_shoff.  Use it and
388 	     e_shnum (or sh_size of the dummy, first section header)
389 	     to determine the maximum extend.  */
390 	  size = MAX ((GElf_Word) size,
391 		      (ehdr->e_shoff
392 		       + (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
393 	}
394       else
395 	{
396 	  /* Align for section header table.
397 
398 	     Yes, we use `sizeof' and not `__alignof__' since we do not
399 	     want to be surprised by architectures with less strict
400 	     alignment rules.  */
401 #define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
402 	  size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
403 
404 	  update_if_changed (ehdr->e_shoff, (GElf_Word) size, elf->flags);
405 	  update_if_changed (ehdr->e_shentsize,
406 			     elf_typesize (LIBELFBITS, ELF_T_SHDR, 1),
407 			     ehdr_flags);
408 
409 	  /* Account for the section header size.  */
410 	  size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
411 	}
412     }
413 
414   elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags;
415 
416   return size;
417 }
418