• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * common.c
3  *
4  *  Created on: Aug 11, 2008
5  *      Author: Stefan Bucur <stefanb@zytor.com>
6  */
7 
8 #include <stdio.h>
9 #include <elf.h>
10 #include <string.h>
11 #include <fs.h>
12 
13 #include <linux/list.h>
14 #include <sys/module.h>
15 
16 #include "elfutils.h"
17 #include "common.h"
18 
19 /**
20  * The one and only list of loaded modules
21  */
22 LIST_HEAD(modules_head);
23 
24 // User-space debugging routines
25 #ifdef ELF_DEBUG
print_elf_ehdr(Elf_Ehdr * ehdr)26 void print_elf_ehdr(Elf_Ehdr *ehdr) {
27 	int i;
28 
29 	fprintf(stderr, "Identification:\t");
30 	for (i=0; i < EI_NIDENT; i++) {
31 		printf("%d ", ehdr->e_ident[i]);
32 	}
33 	fprintf(stderr, "\n");
34 	fprintf(stderr, "Type:\t\t%u\n", ehdr->e_type);
35 	fprintf(stderr, "Machine:\t%u\n", ehdr->e_machine);
36 	fprintf(stderr, "Version:\t%u\n", ehdr->e_version);
37 	fprintf(stderr, "Entry:\t\t0x%08x\n", ehdr->e_entry);
38 	fprintf(stderr, "PHT Offset:\t0x%08x\n", ehdr->e_phoff);
39 	fprintf(stderr, "SHT Offset:\t0x%08x\n", ehdr->e_shoff);
40 	//fprintf(stderr, "Flags:\t\t%u\n", ehdr->e_flags);
41 	//fprintf(stderr, "Header size:\t%u (Structure size: %u)\n", ehdr->e_ehsize,sizeof(Elf_Ehdr));
42 	fprintf(stderr, "phnum: %d shnum: %d\n", ehdr->e_phnum,
43 		ehdr->e_shnum);
44 }
45 
print_elf_symbols(struct elf_module * module)46 void print_elf_symbols(struct elf_module *module) {
47 	unsigned int i;
48 	Elf_Sym *crt_sym;
49 
50 	for (i = 1; i < module->symtable_size/module->syment_size; i++)
51 	{
52 		crt_sym = (Elf_Sym*)(module->sym_table + i*module->syment_size);
53 
54 		fprintf(stderr,"%s %d\n", module->str_table + crt_sym->st_name, crt_sym->st_value);
55 
56 	}
57 }
58 #endif //ELF_DEBUG
59 
findpath(char * name)60 FILE *findpath(char *name)
61 {
62 	struct path_entry *entry;
63 	char path[FILENAME_MAX];
64 	FILE *f;
65 
66 	f = fopen(name, "rb"); /* for full path */
67 	if (f)
68 		return f;
69 
70 	list_for_each_entry(entry, &PATH, list) {
71 		bool slash = false;
72 
73 		/* Ensure we have a '/' separator */
74 		if (entry->str[strlen(entry->str) - 1] != '/')
75 			slash = true;
76 
77 		snprintf(path, sizeof(path), "%s%s%s",
78 			 entry->str, slash ? "/" : "", name);
79 
80 		dprintf("findpath: trying \"%s\"\n", path);
81 		f = fopen(path, "rb");
82 		if (f)
83 			return f;
84 	}
85 
86 	return NULL;
87 }
88 
89 /*
90  * Image files manipulation routines
91  */
92 
image_load(struct elf_module * module)93 int image_load(struct elf_module *module)
94 {
95 	module->u.l._file = findpath(module->name);
96 
97 	if (module->u.l._file == NULL) {
98 		dprintf("Could not open object file '%s'\n", module->name);
99 		goto error;
100 	}
101 
102 	module->u.l._cr_offset = 0;
103 
104 	return 0;
105 
106 error:
107 	if (module->u.l._file != NULL) {
108 		fclose(module->u.l._file);
109 		module->u.l._file = NULL;
110 	}
111 
112 	return -1;
113 }
114 
115 
image_unload(struct elf_module * module)116 int image_unload(struct elf_module *module) {
117 	if (module->u.l._file != NULL) {
118 		fclose(module->u.l._file);
119 		module->u.l._file = NULL;
120 
121 	}
122 	module->u.l._cr_offset = 0;
123 
124 	return 0;
125 }
126 
image_read(void * buff,size_t size,struct elf_module * module)127 int image_read(void *buff, size_t size, struct elf_module *module) {
128 	size_t result = fread(buff, size, 1, module->u.l._file);
129 
130 	if (result < 1)
131 		return -1;
132 
133 	module->u.l._cr_offset += size;
134 	return 0;
135 }
136 
image_skip(size_t size,struct elf_module * module)137 int image_skip(size_t size, struct elf_module *module) {
138 	void *skip_buff = NULL;
139 	size_t result;
140 
141 	if (size == 0)
142 		return 0;
143 
144 	skip_buff = malloc(size);
145 	result = fread(skip_buff, size, 1, module->u.l._file);
146 	free(skip_buff);
147 
148 	if (result < 1)
149 		return -1;
150 
151 	module->u.l._cr_offset += size;
152 	return 0;
153 }
154 
image_seek(Elf_Off offset,struct elf_module * module)155 int image_seek(Elf_Off offset, struct elf_module *module) {
156 	if (offset < module->u.l._cr_offset) // Cannot seek backwards
157 		return -1;
158 
159 	return image_skip(offset - module->u.l._cr_offset, module);
160 }
161 
162 
163 // Initialization of the module subsystem
modules_init(void)164 int modules_init(void) {
165 	return 0;
166 }
167 
168 // Termination of the module subsystem
modules_term(void)169 void modules_term(void) {
170 
171 }
172 
173 // Allocates the structure for a new module
module_alloc(const char * name)174 struct elf_module *module_alloc(const char *name) {
175 	struct elf_module *result = malloc(sizeof(struct elf_module));
176 
177 	if (!result) {
178 	    dprintf("module: Failed to alloc elf_module\n");
179 	    return NULL;
180 	}
181 
182 	memset(result, 0, sizeof(struct elf_module));
183 
184 	INIT_LIST_HEAD(&result->list);
185 	INIT_LIST_HEAD(&result->required);
186 	INIT_LIST_HEAD(&result->dependants);
187 
188 	strncpy(result->name, name, MODULE_NAME_SIZE);
189 
190 	return result;
191 }
192 
module_dep_alloc(struct elf_module * module)193 struct module_dep *module_dep_alloc(struct elf_module *module) {
194 	struct module_dep *result = malloc(sizeof(struct module_dep));
195 
196 	INIT_LIST_HEAD (&result->list);
197 
198 	result->module = module;
199 
200 	return result;
201 }
202 
module_find(const char * name)203 struct elf_module *module_find(const char *name) {
204 	struct elf_module *cr_module;
205 
206 	for_each_module(cr_module) {
207 		if (strcmp(cr_module->name, name) == 0)
208 			return cr_module;
209 	}
210 
211 	return NULL;
212 }
213 
214 
215 // Mouli: This is checking the header for 32bit machine
216 // Support 64bit architecture as well.
217 // Parts of the ELF header checked are common to both ELF32 and ELF64
218 // Adding simple checks for both 32bit and 64bit should work (hopefully)
219 //
220 // Performs verifications on ELF header to assure that the open file is a
221 // valid SYSLINUX ELF module.
check_header_common(Elf_Ehdr * elf_hdr)222 int check_header_common(Elf_Ehdr *elf_hdr) {
223 	// Check the header magic
224 	if (elf_hdr->e_ident[EI_MAG0] != ELFMAG0 ||
225 		elf_hdr->e_ident[EI_MAG1] != ELFMAG1 ||
226 		elf_hdr->e_ident[EI_MAG2] != ELFMAG2 ||
227 		elf_hdr->e_ident[EI_MAG3] != ELFMAG3) {
228 
229 		dprintf("The file is not an ELF object\n");
230 		return -1;
231 	}
232 
233 	if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32 &&
234 	    elf_hdr->e_ident[EI_CLASS] != ELFCLASS64) {
235 		dprintf("Invalid ELF class code\n");
236 		return -1;
237 	}
238 
239 	if (elf_hdr->e_ident[EI_DATA] != MODULE_ELF_DATA) {
240 		dprintf("Invalid ELF data encoding\n");
241 		return -1;
242 	}
243 
244 	if (elf_hdr->e_ident[EI_VERSION] != MODULE_ELF_VERSION ||
245 			elf_hdr->e_version != MODULE_ELF_VERSION) {
246 		dprintf("Invalid ELF file version\n");
247 		return -1;
248 	}
249 
250 	if (elf_hdr->e_machine != EM_386 &&
251 		elf_hdr->e_machine != EM_X86_64) {
252 		dprintf("Invalid ELF architecture\n");
253 		return -1;
254 	}
255 
256 	return 0;
257 }
258 
259 
260 
enforce_dependency(struct elf_module * req,struct elf_module * dep)261 int enforce_dependency(struct elf_module *req, struct elf_module *dep) {
262 	struct module_dep *crt_dep;
263 	struct module_dep *new_dep;
264 
265 	list_for_each_entry(crt_dep, &req->dependants, list) {
266 		if (crt_dep->module == dep) {
267 			// The dependency is already enforced
268 			return 0;
269 		}
270 	}
271 
272 	new_dep = module_dep_alloc(req);
273 	list_add(&new_dep->list, &dep->required);
274 
275 	new_dep = module_dep_alloc(dep);
276 	list_add(&new_dep->list, &req->dependants);
277 
278 	return 0;
279 }
280 
clear_dependency(struct elf_module * req,struct elf_module * dep)281 int clear_dependency(struct elf_module *req, struct elf_module *dep) {
282 	struct module_dep *crt_dep = NULL;
283 	int found = 0;
284 
285 	list_for_each_entry(crt_dep, &req->dependants, list) {
286 		if (crt_dep->module == dep) {
287 			found = 1;
288 			break;
289 		}
290 	}
291 
292 	if (found) {
293 		list_del(&crt_dep->list);
294 		free(crt_dep);
295 	}
296 
297 	found = 0;
298 
299 	list_for_each_entry(crt_dep, &dep->required, list) {
300 		if (crt_dep->module == req) {
301 			found = 1;
302 			break;
303 		}
304 	}
305 
306 	if (found) {
307 		list_del(&crt_dep->list);
308 		free(crt_dep);
309 	}
310 
311 	return 0;
312 }
313 
check_symbols(struct elf_module * module)314 int check_symbols(struct elf_module *module)
315 {
316 	unsigned int i;
317 	Elf_Sym *crt_sym = NULL, *ref_sym = NULL;
318 	char *crt_name;
319 	struct elf_module *crt_module;
320 
321 	int strong_count;
322 	int weak_count;
323 
324 	for (i = 1; i < module->symtable_size/module->syment_size; i++)
325 	{
326 		crt_sym = symbol_get_entry(module, i);
327 		crt_name = module->str_table + crt_sym->st_name;
328 
329 		strong_count = 0;
330 		weak_count = (ELF32_ST_BIND(crt_sym->st_info) == STB_WEAK);
331 
332 		for_each_module(crt_module)
333 		{
334 			ref_sym = module_find_symbol(crt_name, crt_module);
335 
336 			// If we found a definition for our symbol...
337 			if (ref_sym != NULL && ref_sym->st_shndx != SHN_UNDEF)
338 			{
339 				switch (ELF32_ST_BIND(ref_sym->st_info))
340 				{
341 					case STB_GLOBAL:
342 						strong_count++;
343 						break;
344 					case STB_WEAK:
345 						weak_count++;
346 						break;
347 				}
348 			}
349 		}
350 
351 		if (crt_sym->st_shndx == SHN_UNDEF)
352 		{
353 			// We have an undefined symbol
354 			//
355 			// We use the weak_count to differentiate
356 			// between Syslinux-derivative-specific
357 			// functions. For example, unload_pxe() is
358 			// only provided by PXELINUX, so we mark it as
359 			// __weak and replace it with a reference to
360 			// undefined_symbol() on SYSLINUX, EXTLINUX,
361 			// and ISOLINUX. See perform_relocations().
362 			if (strong_count == 0 && weak_count == 0)
363 			{
364 				dprintf("Symbol %s is undefined\n", crt_name);
365 				printf("Undef symbol FAIL: %s\n",crt_name);
366 				return -1;
367 			}
368 		}
369 		else
370 		{
371 			if (strong_count > 0 && ELF32_ST_BIND(ref_sym->st_info) == STB_GLOBAL)
372 			{
373 				// It's not an error - at relocation, the most recent symbol
374 				// will be considered
375 				dprintf("Info: Symbol %s is defined more than once\n", crt_name);
376 			}
377 		}
378 		//printf("symbol %s laoded from %d\n",crt_name,crt_sym->st_value);
379 	}
380 
381 	return 0;
382 }
383 
module_unloadable(struct elf_module * module)384 int module_unloadable(struct elf_module *module) {
385 	if (!list_empty(&module->dependants))
386 		return 0;
387 
388 	return 1;
389 }
390 
391 
392 // Unloads the module from the system and releases all the associated memory
_module_unload(struct elf_module * module)393 int _module_unload(struct elf_module *module) {
394 	struct module_dep *crt_dep, *tmp;
395 	// Make sure nobody needs us
396 	if (!module_unloadable(module)) {
397 		dprintf("Module is required by other modules.\n");
398 		return -1;
399 	}
400 
401 	// Remove any dependency information
402 	list_for_each_entry_safe(crt_dep, tmp, &module->required, list) {
403 		clear_dependency(crt_dep->module, module);
404 	}
405 
406 	// Remove the module from the module list
407 	list_del_init(&module->list);
408 
409 	// Release the loaded segments or sections
410 	if (module->module_addr != NULL) {
411 		elf_free(module->module_addr);
412 
413 		dprintf("%s MODULE %s UNLOADED\n", module->shallow ? "SHALLOW" : "",
414 				module->name);
415 	}
416 
417 	dprintf("Unloading module %s\n", module->name);
418 	// Release the module structure
419 	free(module);
420 
421 	return 0;
422 }
423 
module_unload(struct elf_module * module)424 int module_unload(struct elf_module *module) {
425 	module_ctor_t *dtor;
426 
427 	for (dtor = module->dtors; dtor && *dtor; dtor++)
428 		(*dtor) ();
429 
430 	return _module_unload(module);
431 }
432 
unload_modules_since(const char * name)433 struct elf_module *unload_modules_since(const char *name) {
434 	struct elf_module *m, *mod, *begin = NULL;
435 
436 	for_each_module(mod) {
437 		if (!strcmp(mod->name, name)) {
438 			begin = mod;
439 			break;
440 		}
441 	}
442 
443 	if (!begin)
444 		return begin;
445 
446 	for_each_module_safe(mod, m) {
447 		if (mod == begin)
448 			break;
449 
450 		if (mod != begin)
451 			module_unload(mod);
452 	}
453 
454 	return begin;
455 }
456 
module_find_symbol_sysv(const char * name,struct elf_module * module)457 static Elf_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) {
458 	unsigned long h = elf_hash((const unsigned char*)name);
459 	Elf_Word *cr_word = module->hash_table;
460 
461 	Elf_Word nbucket = *cr_word++;
462 	cr_word++; // Skip nchain
463 
464 	Elf_Word *bkt = cr_word;
465 	Elf_Word *chn = cr_word + nbucket;
466 
467 	Elf_Word crt_index = bkt[h % module->hash_table[0]];
468 	Elf_Sym *crt_sym;
469 
470 
471 	while (crt_index != STN_UNDEF) {
472 		crt_sym = symbol_get_entry(module, crt_index);
473 
474 		if (strcmp(name, module->str_table + crt_sym->st_name) == 0)
475 			return crt_sym;
476 
477 		crt_index = chn[crt_index];
478 	}
479 
480 	return NULL;
481 }
482 
module_find_symbol_gnu(const char * name,struct elf_module * module)483 static Elf_Sym *module_find_symbol_gnu(const char *name, struct elf_module *module) {
484 	unsigned long h = elf_gnu_hash((const unsigned char*)name);
485 
486 	// Setup code (TODO: Optimize this by computing only once)
487 	Elf_Word *cr_word = module->ghash_table;
488 	Elf_Word nbucket = *cr_word++;
489 	Elf_Word symbias = *cr_word++;
490 	Elf_Word bitmask_nwords = *cr_word++;
491 
492 	if ((bitmask_nwords & (bitmask_nwords - 1)) != 0) {
493 		dprintf("Invalid GNU Hash structure\n");
494 		return NULL;
495 	}
496 
497 	Elf_Word gnu_shift = *cr_word++;
498 
499 	Elf_Addr *gnu_bitmask = (Elf_Addr*)cr_word;
500 	cr_word += MODULE_ELF_CLASS_SIZE / 32 * bitmask_nwords;
501 
502 	Elf_Word *gnu_buckets = cr_word;
503 	cr_word += nbucket;
504 
505 	Elf_Word *gnu_chain_zero = cr_word - symbias;
506 
507 	// Computations
508 	Elf_Bword bitmask_word = gnu_bitmask[(h / MODULE_ELF_CLASS_SIZE) &
509 	                                       (bitmask_nwords - 1)];
510 
511 	unsigned int hashbit1 = h & (MODULE_ELF_CLASS_SIZE - 1);
512 	unsigned int hashbit2 = (h >> gnu_shift) & (MODULE_ELF_CLASS_SIZE - 1);
513 
514 	if ((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1) {
515 		unsigned long rem;
516 		Elf_Word bucket;
517 
518 		rem = h % nbucket;
519 
520 		bucket = gnu_buckets[rem];
521 
522 		if (bucket != 0) {
523 			const Elf_Word* hasharr = &gnu_chain_zero[bucket];
524 
525 			do {
526 				if (((*hasharr ^ h ) >> 1) == 0) {
527 					Elf_Sym *crt_sym = symbol_get_entry(module, (hasharr - gnu_chain_zero));
528 
529 					if (strcmp(name, module->str_table + crt_sym->st_name) == 0) {
530 						return crt_sym;
531 					}
532 				}
533 			} while ((*hasharr++ & 1u) == 0);
534 		}
535 	}
536 
537 	return NULL;
538 }
539 
module_find_symbol_iterate(const char * name,struct elf_module * module)540 static Elf_Sym *module_find_symbol_iterate(const char *name,struct elf_module *module)
541 {
542 
543 	unsigned int i;
544 	Elf_Sym *crt_sym;
545 
546 	for (i = 1; i < module->symtable_size/module->syment_size; i++)
547 	{
548 		crt_sym = symbol_get_entry(module, i);
549 		if (strcmp(name, module->str_table + crt_sym->st_name) == 0)
550 		{
551 			return crt_sym;
552 		}
553 	}
554 
555 	return NULL;
556 }
557 
module_find_symbol(const char * name,struct elf_module * module)558 Elf_Sym *module_find_symbol(const char *name, struct elf_module *module) {
559 	Elf_Sym *result = NULL;
560 
561 	if (module->ghash_table != NULL)
562 		result = module_find_symbol_gnu(name, module);
563 
564 	if (result == NULL)
565 	{
566 		if (module->hash_table != NULL)
567 		{
568 			//printf("Attempting SYSV Symbol search\n");
569 			result = module_find_symbol_sysv(name, module);
570 		}
571 		else
572 		{
573 			//printf("Attempting Iterative Symbol search\n");
574 			result = module_find_symbol_iterate(name, module);
575 		}
576 	}
577 
578 	return result;
579 }
580 
global_find_symbol(const char * name,struct elf_module ** module)581 Elf_Sym *global_find_symbol(const char *name, struct elf_module **module) {
582 	struct elf_module *crt_module;
583 	Elf_Sym *crt_sym = NULL;
584 	Elf_Sym *result = NULL;
585 
586 	for_each_module(crt_module) {
587 		crt_sym = module_find_symbol(name, crt_module);
588 
589 		if (crt_sym != NULL && crt_sym->st_shndx != SHN_UNDEF) {
590 			switch (ELF32_ST_BIND(crt_sym->st_info)) {
591 			case STB_GLOBAL:
592 				if (module != NULL) {
593 					*module = crt_module;
594 				}
595 				return crt_sym;
596 			case STB_WEAK:
597 				// Consider only the first weak symbol
598 				if (result == NULL) {
599 					if (module != NULL) {
600 						*module = crt_module;
601 					}
602 					result = crt_sym;
603 				}
604 				break;
605 			}
606 		}
607 	}
608 
609 	return result;
610 }
611