xref: /trueos/lib/libelf/elf_update.c (revision 2ad8e10333f151d4744c8dfc21f28ed627d114f5)
1 /*-
2  * Copyright (c) 2006-2008 Joseph Koshy
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/mman.h>
31 #include <sys/param.h>
32 
33 #include <assert.h>
34 #include <errno.h>
35 #include <gelf.h>
36 #include <libelf.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 
41 #include "_libelf.h"
42 
43 /*
44  * Layout strategy:
45  *
46  * - Case 1: ELF_F_LAYOUT is asserted
47  *     In this case the application has full control over where the
48  *     section header table, program header table, and section data
49  *     will reside.   The library only perform error checks.
50  *
51  * - Case 2: ELF_F_LAYOUT is not asserted
52  *
53  *     The library will do the object layout using the following
54  *     ordering:
55  *     - The executable header is placed first, are required by the
56  *     	 ELF specification.
57  *     - The program header table is placed immediately following the
58  *       executable header.
59  *     - Section data, if any, is placed after the program header
60  *       table, aligned appropriately.
61  *     - The section header table, if needed, is placed last.
62  *
63  *     There are two sub-cases to be taken care of:
64  *
65  *     - Case 2a: e->e_cmd == ELF_C_READ or ELF_C_RDWR
66  *
67  *       In this sub-case, the underlying ELF object may already have
68  *       content in it, which the application may have modified.  The
69  *       library will retrieve content from the existing object as
70  *       needed.
71  *
72  *     - Case 2b: e->e_cmd == ELF_C_WRITE
73  *
74  *       The ELF object is being created afresh in this sub-case;
75  *       there is no pre-existing content in the underlying ELF
76  *       object.
77  */
78 
79 /*
80  * Compute the extents of a section, by looking at the data
81  * descriptors associated with it.  The function returns 1 if
82  * successful, or zero if an error was detected.
83  */
84 static int
_libelf_compute_section_extents(Elf * e,Elf_Scn * s,off_t rc)85 _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc)
86 {
87 	int ec;
88 	size_t fsz, msz;
89 	Elf_Data *d;
90 	Elf32_Shdr *shdr32;
91 	Elf64_Shdr *shdr64;
92 	unsigned int elftype;
93 	uint32_t sh_type;
94 	uint64_t d_align;
95 	uint64_t sh_align, sh_entsize, sh_offset, sh_size;
96 	uint64_t scn_size, scn_alignment;
97 
98 	ec = e->e_class;
99 
100 	shdr32 = &s->s_shdr.s_shdr32;
101 	shdr64 = &s->s_shdr.s_shdr64;
102 	if (ec == ELFCLASS32) {
103 		sh_type    = shdr32->sh_type;
104 		sh_align   = (uint64_t) shdr32->sh_addralign;
105 		sh_entsize = (uint64_t) shdr32->sh_entsize;
106 		sh_offset  = (uint64_t) shdr32->sh_offset;
107 		sh_size    = (uint64_t) shdr32->sh_size;
108 	} else {
109 		sh_type    = shdr64->sh_type;
110 		sh_align   = shdr64->sh_addralign;
111 		sh_entsize = shdr64->sh_entsize;
112 		sh_offset  = shdr64->sh_offset;
113 		sh_size    = shdr64->sh_size;
114 	}
115 
116 	assert(sh_type != SHT_NULL && sh_type != SHT_NOBITS);
117 
118 	elftype = _libelf_xlate_shtype(sh_type);
119 	if (elftype > ELF_T_LAST) {
120 		LIBELF_SET_ERROR(SECTION, 0);
121 		return (0);
122 	}
123 
124 	if (sh_align == 0)
125 		sh_align = _libelf_falign(elftype, ec);
126 
127 	/*
128 	 * Check the section's data buffers for sanity and compute the
129 	 * section's alignment.
130 	 * Compute the section's size and alignment using the data
131 	 * descriptors associated with the section.
132 	 */
133 	if (STAILQ_EMPTY(&s->s_data)) {
134 		/*
135 		 * The section's content (if any) has not been read in
136 		 * yet.  If section is not dirty marked dirty, we can
137 		 * reuse the values in the 'sh_size' and 'sh_offset'
138 		 * fields of the section header.
139 		 */
140 		if ((s->s_flags & ELF_F_DIRTY) == 0) {
141 			/*
142 			 * If the library is doing the layout, then we
143 			 * compute the new start offset for the
144 			 * section based on the current offset and the
145 			 * section's alignment needs.
146 			 *
147 			 * If the application is doing the layout, we
148 			 * can use the value in the 'sh_offset' field
149 			 * in the section header directly.
150 			 */
151 			if (e->e_flags & ELF_F_LAYOUT)
152 				goto updatedescriptor;
153 			else
154 				goto computeoffset;
155 		}
156 
157 		/*
158 		 * Otherwise, we need to bring in the section's data
159 		 * from the underlying ELF object.
160 		 */
161 		if (e->e_cmd != ELF_C_WRITE && elf_getdata(s, NULL) == NULL)
162 			return (0);
163 	}
164 
165 	/*
166 	 * Loop through the section's data descriptors.
167 	 */
168 	scn_size = 0L;
169 	scn_alignment = 0L;
170 	STAILQ_FOREACH(d, &s->s_data, d_next)  {
171 		if (d->d_type > ELF_T_LAST) {
172 			LIBELF_SET_ERROR(DATA, 0);
173 			return (0);
174 		}
175 		if (d->d_version != e->e_version) {
176 			LIBELF_SET_ERROR(VERSION, 0);
177 			return (0);
178 		}
179 		if ((d_align = d->d_align) == 0 || (d_align & (d_align - 1))) {
180 			LIBELF_SET_ERROR(DATA, 0);
181 			return (0);
182 		}
183 
184 		/*
185 		 * The buffer's size should be a multiple of the
186 		 * memory size of the underlying type.
187 		 */
188 		msz = _libelf_msize(d->d_type, ec, e->e_version);
189 		if (d->d_size % msz) {
190 			LIBELF_SET_ERROR(DATA, 0);
191 			return (0);
192 		}
193 
194 		/*
195 		 * Compute the section's size.
196 		 */
197 		if (e->e_flags & ELF_F_LAYOUT) {
198 			if ((uint64_t) d->d_off + d->d_size > scn_size)
199 				scn_size = d->d_off + d->d_size;
200 		} else {
201 			scn_size = roundup2(scn_size, d->d_align);
202 			d->d_off = scn_size;
203 			fsz = _libelf_fsize(d->d_type, ec, d->d_version,
204 			    d->d_size / msz);
205 			scn_size += fsz;
206 		}
207 
208 		/*
209 		 * The section's alignment is the maximum alignment
210 		 * needed for its data buffers.
211 		 */
212 		if (d_align > scn_alignment)
213 			scn_alignment = d_align;
214 	}
215 
216 
217 	/*
218 	 * If the application is requesting full control over the layout
219 	 * of the section, check its values for sanity.
220 	 */
221 	if (e->e_flags & ELF_F_LAYOUT) {
222 		if (scn_alignment > sh_align || sh_offset % sh_align ||
223 		    sh_size < scn_size) {
224 			LIBELF_SET_ERROR(LAYOUT, 0);
225 			return (0);
226 		}
227 		goto updatedescriptor;
228 	}
229 
230 	/*
231 	 * Otherwise compute the values in the section header.
232 	 *
233 	 * The section alignment is the maximum alignment for any of
234 	 * its contained data descriptors.
235 	 */
236 	if (scn_alignment > sh_align)
237 		sh_align = scn_alignment;
238 
239 	/*
240 	 * If the section entry size is zero, try and fill in an
241 	 * appropriate entry size.  Per the elf(5) manual page
242 	 * sections without fixed-size entries should have their
243 	 * 'sh_entsize' field set to zero.
244 	 */
245 	if (sh_entsize == 0 &&
246 	    (sh_entsize = _libelf_fsize(elftype, ec, e->e_version,
247 	    (size_t) 1)) == 1)
248 		sh_entsize = 0;
249 
250 	sh_size = scn_size;
251 
252 computeoffset:
253 	/*
254 	 * Compute the new offset for the section based on
255 	 * the section's alignment needs.
256 	 */
257 	sh_offset = roundup(rc, sh_align);
258 
259 	/*
260 	 * Update the section header.
261 	 */
262 	if (ec == ELFCLASS32) {
263 		shdr32->sh_addralign = (uint32_t) sh_align;
264 		shdr32->sh_entsize   = (uint32_t) sh_entsize;
265 		shdr32->sh_offset    = (uint32_t) sh_offset;
266 		shdr32->sh_size      = (uint32_t) sh_size;
267 	} else {
268 		shdr64->sh_addralign = sh_align;
269 		shdr64->sh_entsize   = sh_entsize;
270 		shdr64->sh_offset    = sh_offset;
271 		shdr64->sh_size      = sh_size;
272 	}
273 
274 updatedescriptor:
275 	/*
276 	 * Update the section descriptor.
277 	 */
278 	s->s_size = sh_size;
279 	s->s_offset = sh_offset;
280 
281 	return (1);
282 }
283 
284 
285 /*
286  * Insert a section in ascending order in the list
287  */
288 
289 static int
_libelf_insert_section(Elf * e,Elf_Scn * s)290 _libelf_insert_section(Elf *e, Elf_Scn *s)
291 {
292 	Elf_Scn *t, *prevt;
293 	uint64_t smax, smin, tmax, tmin;
294 
295 	smin = s->s_offset;
296 	smax = smin + s->s_size;
297 
298 	prevt = NULL;
299 	STAILQ_FOREACH(t, &e->e_u.e_elf.e_scn, s_next) {
300 		tmin = t->s_offset;
301 		tmax = tmin + t->s_size;
302 
303 		if (tmax <= smin) {
304 			/*
305 			 * 't' lies entirely before 's': ...| t |...| s |...
306 			 */
307 			prevt = t;
308 			continue;
309 		} else if (smax <= tmin)
310 			/*
311 			 * 's' lies entirely before 't', and after 'prevt':
312 			 *      ...| prevt |...| s |...| t |...
313 			 */
314 			break;
315 		else {	/* 's' and 't' overlap. */
316 			LIBELF_SET_ERROR(LAYOUT, 0);
317 			return (0);
318 		}
319 	}
320 
321 	if (prevt)
322 		STAILQ_INSERT_AFTER(&e->e_u.e_elf.e_scn, prevt, s, s_next);
323 	else
324 		STAILQ_INSERT_HEAD(&e->e_u.e_elf.e_scn, s, s_next);
325 	return (1);
326 }
327 
328 /*
329  * Recompute section layout.
330  */
331 
332 static off_t
_libelf_resync_sections(Elf * e,off_t rc)333 _libelf_resync_sections(Elf *e, off_t rc)
334 {
335 	int ec;
336 	Elf_Scn *s;
337 	size_t sh_type, shdr_start, shdr_end;
338 
339 	ec = e->e_class;
340 
341 	/*
342 	 * Make a pass through sections, computing the extent of each
343 	 * section. Order in increasing order of addresses.
344 	 */
345 	STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) {
346 		if (ec == ELFCLASS32)
347 			sh_type = s->s_shdr.s_shdr32.sh_type;
348 		else
349 			sh_type = s->s_shdr.s_shdr64.sh_type;
350 
351 		if (sh_type == SHT_NOBITS || sh_type == SHT_NULL)
352 			continue;
353 
354 		if (_libelf_compute_section_extents(e, s, rc) == 0)
355 			return ((off_t) -1);
356 
357 		if (s->s_size == 0)
358 			continue;
359 
360 		if (s->s_offset + s->s_size < (size_t) rc) {
361 			/*
362 			 * Try insert this section in the
363 			 * correct place in the list,
364 			 * detecting overlaps if any.
365 			 */
366 			STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn,
367 			    s_next);
368 			if (_libelf_insert_section(e, s) == 0)
369 				return ((off_t) -1);
370 		} else
371 			rc = s->s_offset + s->s_size;
372 	}
373 
374 	/*
375 	 * If the application is controlling file layout, check for an
376 	 * overlap between this section's extents and the SHDR table.
377 	 */
378 	if (e->e_flags & ELF_F_LAYOUT) {
379 
380 		if (e->e_class == ELFCLASS32)
381 			shdr_start = e->e_u.e_elf.e_ehdr.e_ehdr32->e_shoff;
382 		else
383 			shdr_start = e->e_u.e_elf.e_ehdr.e_ehdr64->e_shoff;
384 
385 		shdr_end = shdr_start + _libelf_fsize(ELF_T_SHDR, e->e_class,
386 		    e->e_version, e->e_u.e_elf.e_nscn);
387 
388 		STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) {
389 			if (s->s_offset >= shdr_end ||
390 			    s->s_offset + s->s_size <= shdr_start)
391 				continue;
392 			LIBELF_SET_ERROR(LAYOUT, 0);
393 			return ((off_t) -1);
394 		}
395 	}
396 
397 	return (rc);
398 }
399 
400 static off_t
_libelf_resync_elf(Elf * e)401 _libelf_resync_elf(Elf *e)
402 {
403 	int ec, eh_class, eh_type;
404 	unsigned int eh_byteorder, eh_version;
405 	size_t align, fsz;
406 	size_t phnum, shnum;
407 	off_t rc, phoff, shoff;
408 	void *ehdr;
409 	Elf32_Ehdr *eh32;
410 	Elf64_Ehdr *eh64;
411 
412 	rc = 0;
413 
414 	ec = e->e_class;
415 
416 	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
417 
418 	/*
419 	 * Prepare the EHDR.
420 	 */
421 	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
422 		return ((off_t) -1);
423 
424 	eh32 = ehdr;
425 	eh64 = ehdr;
426 
427 	if (ec == ELFCLASS32) {
428 		eh_byteorder = eh32->e_ident[EI_DATA];
429 		eh_class     = eh32->e_ident[EI_CLASS];
430 		phoff        = (uint64_t) eh32->e_phoff;
431 		shoff        = (uint64_t) eh32->e_shoff;
432 		eh_type      = eh32->e_type;
433 		eh_version   = eh32->e_version;
434 	} else {
435 		eh_byteorder = eh64->e_ident[EI_DATA];
436 		eh_class     = eh64->e_ident[EI_CLASS];
437 		phoff        = eh64->e_phoff;
438 		shoff        = eh64->e_shoff;
439 		eh_type      = eh64->e_type;
440 		eh_version   = eh64->e_version;
441 	}
442 
443 	if (eh_version == EV_NONE)
444 		eh_version = EV_CURRENT;
445 
446 	if (eh_version != e->e_version) {	/* always EV_CURRENT */
447 		LIBELF_SET_ERROR(VERSION, 0);
448 		return ((off_t) -1);
449 	}
450 
451 	if (eh_class != e->e_class) {
452 		LIBELF_SET_ERROR(CLASS, 0);
453 		return ((off_t) -1);
454 	}
455 
456 	if (e->e_cmd != ELF_C_WRITE && eh_byteorder != e->e_byteorder) {
457 		LIBELF_SET_ERROR(HEADER, 0);
458 		return ((off_t) -1);
459 	}
460 
461 	shnum = e->e_u.e_elf.e_nscn;
462 	phnum = e->e_u.e_elf.e_nphdr;
463 
464 	e->e_byteorder = eh_byteorder;
465 
466 #define	INITIALIZE_EHDR(E,EC,V)	do {					\
467 		(E)->e_ident[EI_MAG0] = ELFMAG0;			\
468 		(E)->e_ident[EI_MAG1] = ELFMAG1;			\
469 		(E)->e_ident[EI_MAG2] = ELFMAG2;			\
470 		(E)->e_ident[EI_MAG3] = ELFMAG3;			\
471 		(E)->e_ident[EI_CLASS] = (EC);				\
472 		(E)->e_ident[EI_VERSION] = (V);				\
473 		(E)->e_ehsize = _libelf_fsize(ELF_T_EHDR, (EC), (V),	\
474 		    (size_t) 1);					\
475 		(E)->e_phentsize = (phnum == 0) ? 0 : _libelf_fsize(	\
476 		    ELF_T_PHDR, (EC), (V), (size_t) 1);			\
477 		(E)->e_shentsize = _libelf_fsize(ELF_T_SHDR, (EC), (V),	\
478 		    (size_t) 1);					\
479 	} while (0)
480 
481 	if (ec == ELFCLASS32)
482 		INITIALIZE_EHDR(eh32, ec, eh_version);
483 	else
484 		INITIALIZE_EHDR(eh64, ec, eh_version);
485 
486 	(void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY);
487 
488 	rc += _libelf_fsize(ELF_T_EHDR, ec, eh_version, (size_t) 1);
489 
490 	/*
491 	 * Compute the layout the program header table, if one is
492 	 * present.  The program header table needs to be aligned to a
493 	 * `natural' boundary.
494 	 */
495 	if (phnum) {
496 		fsz = _libelf_fsize(ELF_T_PHDR, ec, eh_version, phnum);
497 		align = _libelf_falign(ELF_T_PHDR, ec);
498 
499 		if (e->e_flags & ELF_F_LAYOUT) {
500 			/*
501 			 * Check offsets for sanity.
502 			 */
503 			if (rc > phoff) {
504 				LIBELF_SET_ERROR(HEADER, 0);
505 				return ((off_t) -1);
506 			}
507 
508 			if (phoff % align) {
509 				LIBELF_SET_ERROR(LAYOUT, 0);
510 				return ((off_t) -1);
511 			}
512 
513 		} else
514 			phoff = roundup(rc, align);
515 
516 		rc = phoff + fsz;
517 	} else
518 		phoff = 0;
519 
520 	/*
521 	 * Compute the layout of the sections associated with the
522 	 * file.
523 	 */
524 
525 	if (e->e_cmd != ELF_C_WRITE &&
526 	    (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 &&
527 	    _libelf_load_scn(e, ehdr) == 0)
528 		return ((off_t) -1);
529 
530 	if ((rc = _libelf_resync_sections(e, rc)) < 0)
531 		return ((off_t) -1);
532 
533 	/*
534 	 * Compute the space taken up by the section header table, if
535 	 * one is needed.  If ELF_F_LAYOUT is asserted, the
536 	 * application may have placed the section header table in
537 	 * between existing sections, so the net size of the file need
538 	 * not increase due to the presence of the section header
539 	 * table.
540 	 */
541 	if (shnum) {
542 		fsz = _libelf_fsize(ELF_T_SHDR, ec, eh_version, (size_t) 1);
543 		align = _libelf_falign(ELF_T_SHDR, ec);
544 
545 		if (e->e_flags & ELF_F_LAYOUT) {
546 			if (shoff % align) {
547 				LIBELF_SET_ERROR(LAYOUT, 0);
548 				return ((off_t) -1);
549 			}
550 		} else
551 			shoff = roundup(rc, align);
552 
553 		if (shoff + fsz * shnum > (size_t) rc)
554 			rc = shoff + fsz * shnum;
555 	} else
556 		shoff = 0;
557 
558 	/*
559 	 * Set the fields of the Executable Header that could potentially use
560 	 * extended numbering.
561 	 */
562 	_libelf_setphnum(e, ehdr, ec, phnum);
563 	_libelf_setshnum(e, ehdr, ec, shnum);
564 
565 	/*
566 	 * Update the `e_phoff' and `e_shoff' fields if the library is
567 	 * doing the layout.
568 	 */
569 	if ((e->e_flags & ELF_F_LAYOUT) == 0) {
570 		if (ec == ELFCLASS32) {
571 			eh32->e_phoff = (uint32_t) phoff;
572 			eh32->e_shoff = (uint32_t) shoff;
573 		} else {
574 			eh64->e_phoff = (uint64_t) phoff;
575 			eh64->e_shoff = (uint64_t) shoff;
576 		}
577 	}
578 
579 	return (rc);
580 }
581 
582 /*
583  * Write out the contents of a section.
584  */
585 
586 static off_t
_libelf_write_scn(Elf * e,char * nf,Elf_Scn * s,off_t rc)587 _libelf_write_scn(Elf *e, char *nf, Elf_Scn *s, off_t rc)
588 {
589 	int ec;
590 	size_t fsz, msz, nobjects;
591 	uint32_t sh_type;
592 	uint64_t sh_off, sh_size;
593 	int elftype;
594 	Elf_Data *d, dst;
595 
596 	if ((ec = e->e_class) == ELFCLASS32) {
597 		sh_type = s->s_shdr.s_shdr32.sh_type;
598 		sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;
599 	} else {
600 		sh_type = s->s_shdr.s_shdr64.sh_type;
601 		sh_size = s->s_shdr.s_shdr64.sh_size;
602 	}
603 
604 	/*
605 	 * Ignore sections that do not allocate space in the file.
606 	 */
607 	if (sh_type == SHT_NOBITS || sh_type == SHT_NULL || sh_size == 0)
608 		return (rc);
609 
610 	elftype = _libelf_xlate_shtype(sh_type);
611 	assert(elftype >= ELF_T_FIRST && elftype <= ELF_T_LAST);
612 
613 	sh_off = s->s_offset;
614 	assert(sh_off % _libelf_falign(elftype, ec) == 0);
615 
616 	/*
617 	 * If the section has a `rawdata' descriptor, and the section
618 	 * contents have not been modified, use its contents directly.
619 	 * The `s_rawoff' member contains the offset into the original
620 	 * file, while `s_offset' contains its new location in the
621 	 * destination.
622 	 */
623 
624 	if (STAILQ_EMPTY(&s->s_data)) {
625 
626 		if ((d = elf_rawdata(s, NULL)) == NULL)
627 			return ((off_t) -1);
628 
629 		STAILQ_FOREACH(d, &s->s_rawdata, d_next) {
630 			if ((uint64_t) rc < sh_off + d->d_off)
631 				(void) memset(nf + rc,
632 				    LIBELF_PRIVATE(fillchar), sh_off +
633 				    d->d_off - rc);
634 			rc = sh_off + d->d_off;
635 
636 			assert(d->d_buf != NULL);
637 			assert(d->d_type == ELF_T_BYTE);
638 			assert(d->d_version == e->e_version);
639 
640 			(void) memcpy(nf + rc,
641 			    e->e_rawfile + s->s_rawoff + d->d_off, d->d_size);
642 
643 			rc += d->d_size;
644 		}
645 
646 		return (rc);
647 	}
648 
649 	/*
650 	 * Iterate over the set of data descriptors for this section.
651 	 * The prior call to _libelf_resync_elf() would have setup the
652 	 * descriptors for this step.
653 	 */
654 
655 	dst.d_version = e->e_version;
656 
657 	STAILQ_FOREACH(d, &s->s_data, d_next) {
658 
659 		msz = _libelf_msize(d->d_type, ec, e->e_version);
660 
661 		if ((uint64_t) rc < sh_off + d->d_off)
662 			(void) memset(nf + rc,
663 			    LIBELF_PRIVATE(fillchar), sh_off + d->d_off - rc);
664 
665 		rc = sh_off + d->d_off;
666 
667 		assert(d->d_buf != NULL);
668 		assert(d->d_version == e->e_version);
669 		assert(d->d_size % msz == 0);
670 
671 		nobjects = d->d_size / msz;
672 
673 		fsz = _libelf_fsize(d->d_type, ec, e->e_version, nobjects);
674 
675 		dst.d_buf    = nf + rc;
676 		dst.d_size   = fsz;
677 
678 		if (_libelf_xlate(&dst, d, e->e_byteorder, ec, ELF_TOFILE) ==
679 		    NULL)
680 			return ((off_t) -1);
681 
682 		rc += fsz;
683 	}
684 
685 	return ((off_t) rc);
686 }
687 
688 /*
689  * Write out the file image.
690  *
691  * The original file could have been mapped in with an ELF_C_RDWR
692  * command and the application could have added new content or
693  * re-arranged its sections before calling elf_update().  Consequently
694  * its not safe to work `in place' on the original file.  So we
695  * malloc() the required space for the updated ELF object and build
696  * the object there and write it out to the underlying file at the
697  * end.  Note that the application may have opened the underlying file
698  * in ELF_C_RDWR and only retrieved/modified a few sections.  We take
699  * care to avoid translating file sections unnecessarily.
700  *
701  * Gaps in the coverage of the file by the file's sections will be
702  * filled with the fill character set by elf_fill(3).
703  */
704 
705 static off_t
_libelf_write_elf(Elf * e,off_t newsize)706 _libelf_write_elf(Elf *e, off_t newsize)
707 {
708 	int ec;
709 	off_t maxrc, rc;
710 	size_t fsz, msz, phnum, shnum;
711 	uint64_t phoff, shoff;
712 	void *ehdr;
713 	char *newfile;
714 	Elf_Data dst, src;
715 	Elf_Scn *scn, *tscn;
716 	Elf32_Ehdr *eh32;
717 	Elf64_Ehdr *eh64;
718 
719 	assert(e->e_kind == ELF_K_ELF);
720 	assert(e->e_cmd != ELF_C_READ);
721 	assert(e->e_fd >= 0);
722 
723 	if ((newfile = malloc((size_t) newsize)) == NULL) {
724 		LIBELF_SET_ERROR(RESOURCE, errno);
725 		return ((off_t) -1);
726 	}
727 
728 	ec = e->e_class;
729 
730 	ehdr = _libelf_ehdr(e, ec, 0);
731 	assert(ehdr != NULL);
732 
733 	phnum = e->e_u.e_elf.e_nphdr;
734 
735 	if (ec == ELFCLASS32) {
736 		eh32 = (Elf32_Ehdr *) ehdr;
737 
738 		phoff = (uint64_t) eh32->e_phoff;
739 		shnum = eh32->e_shnum;
740 		shoff = (uint64_t) eh32->e_shoff;
741 	} else {
742 		eh64 = (Elf64_Ehdr *) ehdr;
743 
744 		phoff = eh64->e_phoff;
745 		shnum = eh64->e_shnum;
746 		shoff = eh64->e_shoff;
747 	}
748 
749 	fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
750 	msz = _libelf_msize(ELF_T_EHDR, ec, e->e_version);
751 
752 	(void) memset(&dst, 0, sizeof(dst));
753 	(void) memset(&src, 0, sizeof(src));
754 
755 	src.d_buf     = ehdr;
756 	src.d_size    = msz;
757 	src.d_type    = ELF_T_EHDR;
758 	src.d_version = dst.d_version = e->e_version;
759 
760 	rc = 0;
761 
762 	dst.d_buf     = newfile + rc;
763 	dst.d_size    = fsz;
764 
765 	if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) ==
766 	    NULL)
767 		goto error;
768 
769 	rc += fsz;
770 
771 	/*
772 	 * Write the program header table if present.
773 	 */
774 
775 	if (phnum != 0 && phoff != 0) {
776 		assert((unsigned) rc <= phoff);
777 
778 		fsz = _libelf_fsize(ELF_T_PHDR, ec, e->e_version, phnum);
779 
780 		assert(phoff % _libelf_falign(ELF_T_PHDR, ec) == 0);
781 		assert(fsz > 0);
782 
783 		src.d_buf = _libelf_getphdr(e, ec);
784 		src.d_version = dst.d_version = e->e_version;
785 		src.d_type = ELF_T_PHDR;
786 		src.d_size = phnum * _libelf_msize(ELF_T_PHDR, ec,
787 		    e->e_version);
788 
789 		dst.d_size = fsz;
790 
791 		if ((uint64_t) rc < phoff)
792 			(void) memset(newfile + rc,
793 			    LIBELF_PRIVATE(fillchar), phoff - rc);
794 
795 		dst.d_buf = newfile + rc;
796 
797 		if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) ==
798 		    NULL)
799 			goto error;
800 
801 		rc = phoff + fsz;
802 	}
803 
804 	/*
805 	 * Write out individual sections.
806 	 */
807 
808 	STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next)
809  		if ((rc = _libelf_write_scn(e, newfile, scn, rc)) < 0)
810 			goto error;
811 
812 	/*
813 	 * Write out the section header table, if required.  Note that
814 	 * if flag ELF_F_LAYOUT has been set the section header table
815 	 * could reside in between byte ranges mapped by section
816 	 * descriptors.
817 	 */
818 	if (shnum != 0 && shoff != 0) {
819 		if ((uint64_t) rc < shoff)
820 			(void) memset(newfile + rc,
821 			    LIBELF_PRIVATE(fillchar), shoff - rc);
822 
823 		maxrc = rc;
824 		rc = shoff;
825 
826 		assert(rc % _libelf_falign(ELF_T_SHDR, ec) == 0);
827 
828 		src.d_type = ELF_T_SHDR;
829 		src.d_size = _libelf_msize(ELF_T_SHDR, ec, e->e_version);
830 		src.d_version = dst.d_version = e->e_version;
831 
832 		fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1);
833 
834 		STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next) {
835 			if (ec == ELFCLASS32)
836 				src.d_buf = &scn->s_shdr.s_shdr32;
837 			else
838 				src.d_buf = &scn->s_shdr.s_shdr64;
839 
840 			dst.d_size = fsz;
841 			dst.d_buf = newfile + rc + scn->s_ndx * fsz;
842 
843 			if (_libelf_xlate(&dst, &src, e->e_byteorder, ec,
844 				ELF_TOFILE) != &dst)
845 				goto error;
846 		}
847 
848 		rc += e->e_u.e_elf.e_nscn * fsz;
849 		if (maxrc > rc)
850 			rc = maxrc;
851 	}
852 
853 	assert(rc == newsize);
854 
855 	/*
856 	 * Write out the constructed contents and remap the file in
857 	 * read-only.
858 	 */
859 
860 	if (e->e_rawfile && munmap(e->e_rawfile, e->e_rawsize) < 0) {
861 		LIBELF_SET_ERROR(IO, errno);
862 		goto error;
863 	}
864 
865 	if (write(e->e_fd, newfile, (size_t) newsize) != newsize ||
866 	    lseek(e->e_fd, (off_t) 0, SEEK_SET) < 0) {
867 		LIBELF_SET_ERROR(IO, errno);
868 		goto error;
869 	}
870 
871 	if (e->e_cmd != ELF_C_WRITE) {
872 		if ((e->e_rawfile = mmap(NULL, (size_t) newsize, PROT_READ,
873 		    MAP_PRIVATE, e->e_fd, (off_t) 0)) == MAP_FAILED) {
874 			LIBELF_SET_ERROR(IO, errno);
875 			goto error;
876 		}
877 		e->e_rawsize = newsize;
878 	}
879 
880 	/*
881 	 * Reset flags, remove existing section descriptors and
882 	 * {E,P}HDR pointers so that a subsequent elf_get{e,p}hdr()
883 	 * and elf_getscn() will function correctly.
884 	 */
885 
886 	e->e_flags &= ~ELF_F_DIRTY;
887 
888 	STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next, tscn)
889 		_libelf_release_scn(scn);
890 
891 	if (ec == ELFCLASS32) {
892 		free(e->e_u.e_elf.e_ehdr.e_ehdr32);
893 		if (e->e_u.e_elf.e_phdr.e_phdr32)
894 			free(e->e_u.e_elf.e_phdr.e_phdr32);
895 
896 		e->e_u.e_elf.e_ehdr.e_ehdr32 = NULL;
897 		e->e_u.e_elf.e_phdr.e_phdr32 = NULL;
898 	} else {
899 		free(e->e_u.e_elf.e_ehdr.e_ehdr64);
900 		if (e->e_u.e_elf.e_phdr.e_phdr64)
901 			free(e->e_u.e_elf.e_phdr.e_phdr64);
902 
903 		e->e_u.e_elf.e_ehdr.e_ehdr64 = NULL;
904 		e->e_u.e_elf.e_phdr.e_phdr64 = NULL;
905 	}
906 
907 	free(newfile);
908 
909 	return (rc);
910 
911  error:
912 	free(newfile);
913 
914 	return ((off_t) -1);
915 }
916 
917 off_t
elf_update(Elf * e,Elf_Cmd c)918 elf_update(Elf *e, Elf_Cmd c)
919 {
920 	int ec;
921 	off_t rc;
922 
923 	rc = (off_t) -1;
924 
925 	if (e == NULL || e->e_kind != ELF_K_ELF ||
926 	    (c != ELF_C_NULL && c != ELF_C_WRITE)) {
927 		LIBELF_SET_ERROR(ARGUMENT, 0);
928 		return (rc);
929 	}
930 
931 	if ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) {
932 		LIBELF_SET_ERROR(CLASS, 0);
933 		return (rc);
934 	}
935 
936 	if (e->e_version == EV_NONE)
937 		e->e_version = EV_CURRENT;
938 
939 	if (c == ELF_C_WRITE && e->e_cmd == ELF_C_READ) {
940 		LIBELF_SET_ERROR(MODE, 0);
941 		return (rc);
942 	}
943 
944 	if ((rc = _libelf_resync_elf(e)) < 0)
945 		return (rc);
946 
947 	if (c == ELF_C_NULL)
948 		return (rc);
949 
950 	if (e->e_cmd == ELF_C_READ) {
951 		/*
952 		 * This descriptor was opened in read-only mode or by
953 		 * elf_memory().
954 		 */
955 		if (e->e_fd)
956 			LIBELF_SET_ERROR(MODE, 0);
957 		else
958 			LIBELF_SET_ERROR(ARGUMENT, 0);
959 		return ((off_t) -1);
960 	}
961 
962 	if (e->e_fd < 0) {
963 		LIBELF_SET_ERROR(SEQUENCE, 0);
964 		return ((off_t) -1);
965 	}
966 
967 	return (_libelf_write_elf(e, rc));
968 }
969