IBNOS
elf.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Michael Müller
3  * Copyright (c) 2014, Sebastian Lackner
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #include <loader/elf.h>
29 #include <process/process.h>
30 #include <memory/paging.h>
31 #include <memory/allocator.h>
32 #include <util/util.h>
33 #include <util/list.h>
34 
36 {
37  struct linkedList entry;
38  uint32_t startIndex;
39  uint32_t stopIndex;
40 };
41 
42 void __insertRequiredPage(struct linkedList *pages, uint32_t startIndex, uint32_t stopIndex)
43 {
44  struct requiredPages *it = LL_ENTRY(pages->next, struct requiredPages, entry);
45  struct requiredPages *temp_it;
46 
47  if (stopIndex <= startIndex)
48  return;
49 
50  while (&it->entry != pages)
51  {
52  if (stopIndex < it->startIndex)
53  break;
54 
55  if (it->stopIndex < startIndex)
56  {
57  it = LL_ENTRY(it->entry.next, struct requiredPages, entry);
58  continue;
59  }
60 
61  if (startIndex >= it->startIndex && stopIndex <= it->stopIndex)
62  return;
63 
64  if (it->startIndex < startIndex)
65  startIndex = it->startIndex;
66 
67  if (it->stopIndex > stopIndex)
68  stopIndex = it->stopIndex;
69 
70  /* remove entry */
71  temp_it = LL_ENTRY(it->entry.next, struct requiredPages, entry);
72  ll_remove(&it->entry);
73  heapFree(it);
74  it = temp_it;
75  }
76 
77  /* insert entry */
78  temp_it = heapAlloc(sizeof(*temp_it));
79  assert(temp_it);
80 
81  temp_it->startIndex = startIndex;
82  temp_it->stopIndex = stopIndex;
83 
84  ll_add_before(&it->entry, &temp_it->entry);
85 }
86 
104 bool elfLoadBinary(struct process *p, void *addr, uint32_t length)
105 {
106  struct elfHeader *header = (struct elfHeader*) addr;
107  struct userMemory k;
108 
109  /* check whether this can be a vlid ELF file */
110  if (length < sizeof(*header))
111  return false;
112 
113  /* check file flags */
114  if (header->ident[0] != ELF_MAG0 || header->ident[1] != ELF_MAG1 ||
115  header->ident[2] != ELF_MAG2 || header->ident[3] != ELF_MAG3)
116  return false;
117 
118  struct elfSectionTable *section;
119  struct linkedList pages = LL_INIT( pages );
120  struct requiredPages *it, *__it;
121 
122  if (length < header->shoff)
123  return false;
124 
125  section = (struct elfSectionTable *)((void*)header + header->shoff);
126  for (uint32_t index = 0; index < header->shnum; index++)
127  {
128  section = (struct elfSectionTable *)((void*)section + header->shentsize);
129 
130  if ((uint32_t)section + sizeof(*section) - (uint32_t)addr > length)
131  return false;
132 
133  if (!section->addr)
134  continue;
135 
136  if (section->type != ELF_STYPE_NOBITS && length < ((uint64_t)section->offset + section->size))
137  return false;
138 
139  uint32_t startIndex = section->addr >> PAGE_BITS;
140  uint32_t stopIndex = ((uint64_t)section->addr + section->size + PAGE_MASK) >> PAGE_BITS;
141 
142  if (stopIndex >= PAGE_COUNT)
143  stopIndex = PAGE_COUNT - 1;
144 
145  assert(startIndex <= stopIndex);
146 
147  __insertRequiredPage(&pages, startIndex, stopIndex);
148  }
149 
150  LL_FOR_EACH_SAFE( it, __it, &pages, struct requiredPages, entry )
151  {
152  pagingAllocatePhysMemFixed(p, (void *)(it->startIndex << PAGE_BITS), it->stopIndex - it->startIndex, true, true);
153  ll_remove(&it->entry);
154  heapFree(it);
155  }
156 
157  section = (struct elfSectionTable *)((void*)header + header->shoff);
158  for (uint32_t index = 0; index < header->shnum; index++)
159  {
160  section = (struct elfSectionTable *)((void*)section + header->shentsize);
161 
162  if ((uint32_t)section + sizeof(*section) - (uint32_t)addr > length)
163  return false;
164 
165  if (!section->addr)
166  continue;
167 
168  if (!ACCESS_USER_MEMORY(&k, p, (void *)section->addr, section->size, true))
169  return false;
170 
171  if (section->type == ELF_STYPE_NOBITS)
172  memset(k.addr, 0, section->size);
173  else
174  memcpy(k.addr, addr + section->offset, section->size);
175 
176  RELEASE_USER_MEMORY(&k);
177  }
178 
179  p->entryPoint = (void*)header->entry;
180  return true;
181 }
182 
void * entryPoint
Definition: process.h:79
#define ELF_MAG3
Definition: elf.h:49
uint32_t type
Definition: elf.h:153
void * heapAlloc(uint32_t length)
Allocates a block of kernel memory.
Definition: allocator.c:363
#define PAGE_MASK
Definition: physmem.h:36
#define assert(ex)
Definition: util.h:61
void * memset(void *ptr, int value, size_t num)
Fills a memory region with some specific byte value.
Definition: util.c:123
void * pagingAllocatePhysMemFixed(struct process *p, void *addr, uint32_t length, bool rw, bool user)
Allocates several pages of physical memory at a fixed virtual address in a process.
Definition: paging.c:778
#define ELF_MAG0
Definition: elf.h:46
uint32_t addr
Definition: elf.h:155
void heapFree(void *addr)
Deallocates a block of kernel memory.
Definition: allocator.c:385
#define PAGE_BITS
Definition: physmem.h:37
#define LL_INIT(list)
Initializes a linkedList.
Definition: list.h:124
#define LL_ENTRY(element, type, field)
Definition: list.h:127
struct linkedList entry
Definition: elf.c:37
void __insertRequiredPage(struct linkedList *pages, uint32_t startIndex, uint32_t stopIndex)
Definition: elf.c:42
#define ELF_MAG1
Definition: elf.h:47
uint32_t size
Definition: elf.h:157
Definition: elf.h:131
bool elfLoadBinary(struct process *p, void *addr, uint32_t length)
Loads an ELF executable stored in the memory into a process.
Definition: elf.c:104
struct linkedList * next
Definition: list.h:36
#define ELF_MAG2
Definition: elf.h:48
uint32_t shoff
Definition: elf.h:139
void * memcpy(void *destination, const void *source, size_t num)
Copies a block of memory from source to destination.
Definition: util.c:141
#define PAGE_COUNT
Definition: physmem.h:38
void * addr
Definition: paging.h:112
uint16_t shentsize
Definition: elf.h:144
uint32_t offset
Definition: elf.h:156
uint8_t ident[ELF_NIDENT]
Definition: elf.h:133
#define LL_FOR_EACH_SAFE(element, next_element, list, type, field)
Allows to iterate a linkedList similar to a for-loop (safe when deleting elements).
Definition: list.h:148
uint32_t startIndex
Definition: elf.c:38
uint16_t shnum
Definition: elf.h:145
uint32_t stopIndex
Definition: elf.c:39
#define ELF_STYPE_NOBITS
Definition: elf.h:91
uint32_t entry
Definition: elf.h:137