Module loading

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
WinExperements
Member
Member
Posts: 97
Joined: Thu Jul 14, 2022 9:45 am
Contact:

Module loading

Post by WinExperements »

Hello! I have problem with the kernel module loading.
So after the module loaded, i got #UD and the problem is: the kernel symbols not resolving(address of functions didn't setted)
What i am doing wrong?
There are function for module symbols resolving:

Code: Select all

bool module_resolve_symbols(module_t *mod,Elf32_Ehdr *e) {
	unsigned i;
	Elf32_Shdr *s;
	Elf32_Sym *sym;
	const char *str;
	Elf32_Word size,entsize;
	for (i = 0, s = (Elf32_Shdr *)((char *)e + e->e_shoff); i < e->e_shnum;
		i++,s = (Elf32_Shdr *)((char *)s + e->e_shentsize)) {
		if (s->sh_type == SHT_SYMTAB) break;
	}
	if (i == e->e_shnum) {
		printf("%s: failed to find symbol table in module!\n");
		return false;
	}
	mod->symtab = (Elf32_Sym *)((char *)e + s->sh_offset);
	sym = mod->symtab;
	size = s->sh_size;
	entsize = s->sh_entsize;
	s = (Elf32_Shdr *)((char *)e + e->e_shoff + e->e_shentsize * s->sh_link);
	str = (char *)e+ s->sh_offset;
	for (i = 0; i < size/entsize; i++,sym = (Elf32_Sym *)((char *)sym + entsize)) {
		uint8_t type = ELF32_ST_TYPE(sym->st_info);
		uint8_t bind = ELF32_ST_BIND(sym->st_info);
		const char *name = str + sym->st_name;
		switch (type) {
			case STT_NOTYPE:
			case STT_OBJECT:
			if (sym->st_name != 0 && sym->st_shndx == 0) {
				sym->st_value = (Elf32_Addr)symbols_findValue(name);
				printf("Symbol %s founded in kernel: %x\n",name,sym->st_value);
				if (!sym->st_value) {
					printf("Cannot find symbol %s in kernel, abort\n",name);
					return false;
				}
			} else {
				sym->st_value += (Elf32_Addr) module_get_section_addr(mod,sym->st_shndx);
				if (bind != STB_LOCAL) {
					printf("TODO: add this to global symbol table: %s\n",name);
				}
			} break;
			case STT_FUNC:
			sym->st_value += (Elf32_Addr) module_get_section_addr(mod,sym->st_shndx);
			if (bind != STB_LOCAL) {
				printf("TODO: This function %s also need to be added to global symbols table\n",name);
			}
			if (strcmp(name,"module_main")) {
				printf("Module init found\n");
				mod->init = (void (*)(module_t *))sym->st_value;
			}
			break;
			case STT_SECTION:
			sym->st_value += (Elf32_Addr) module_get_section_addr(mod,sym->st_shndx);
			break;
			case STT_FILE:
			sym->st_value = 0;
			break;
			default:
			printf("Unknown symbol type: %d,%s\n",type,name);
			return false;
			break;
		}
	}
	return true;
}
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Module loading

Post by nullplan »

OK, yes, that does resolve the symbols. But do you at any point process the relocations? After assigning values to all the symbols, you must look through all the section headers again, looking for all sections of type SHT_REL and SHT_RELA. Each of those says in the section header's link field what symbol table they are referring to (the section index of that), and in the info field, what section they are relocations for. The offsets in the relocation structures are relative to the start of the referred-to section. And then you only have to actually process the relocations by type.
Carpe diem!
WinExperements
Member
Member
Posts: 97
Joined: Thu Jul 14, 2022 9:45 am
Contact:

Re: Module loading

Post by WinExperements »

nullplan wrote:But do you at any point process the relocations?
Yeah i do it here:

Code: Select all

bool arch_relocSymbols(module_t *mod,void *ehdr) {
	Elf32_Ehdr *e = (Elf32_Ehdr *)ehdr;
	Elf32_Shdr *s;
	Elf32_Word entsize;
	unsigned i;
	// Find symbol table
	for (i = 0,s = (Elf32_Shdr *)((char *) e + e->e_shoff); i < e->e_shnum;
		i++,s = (Elf32_Shdr *)((char *) s + e->e_shentsize)) {
		if (s->sh_type == SHT_SYMTAB) {
			break;
		}
	}
	if (i == e->e_shnum) {
		printf("relloc: no symbol table to relocate!\n");
		return false;
	}
	entsize = s->sh_entsize;
	for (i = 0,s = (Elf32_Shdr *)((char *)e + e->e_shoff); i < e->e_shnum;
		i++,s = (Elf32_Shdr *)((char *)s + e->e_shentsize)) {
			if (s->sh_type == SHT_REL) {
				printf("Relocation segment\n");
				module_segment_t *seg;
				for (seg = mod->seg; seg; seg = seg->next) {
					if (seg->section == s->sh_info) break;
				}
				if (seg) {
					Elf32_Rel *rel,*max;
					for (rel = (Elf32_Rel *)((char *) e + s->sh_offset),
						max = rel + s->sh_size / s->sh_entsize;
						rel < max;
						rel++) {
						Elf32_Word *addr;
						Elf32_Sym *sym;
						if (seg->size < rel->r_offset) {
							printf("Relloc offset is out of segment\n");
							return false;
						}
						addr = (Elf32_Word *)((char *)seg->addr + rel->r_offset);
						sym = (Elf32_Sym *)((char *)mod->symtab + entsize * ELF32_R_SYM(rel->r_info));
						switch (ELF32_R_TYPE(rel->r_info)) {
							case R_386_32:
								*addr += sym->st_value;
								break;
							case R_386_PC32:
								*addr += (sym->st_value - (Elf32_Word)seg->addr - rel->r_offset);
								break;
						}
					}
				}
			}
	}
	return true;
}
Does i do it wrong?
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Module loading

Post by nullplan »

WinExperements wrote:Does i do it wrong?
Well, you are looking up the symbol table in a weird way. As I said, the section index of the symbol table you need is given in the link field of the relocation table's section header. There might be multiple symbol tables. Also, you should give an error for unknown relocation types so you know if the compiler generated something you didn't handle. Other than that, looks good so far.
Carpe diem!
WinExperements
Member
Member
Posts: 97
Joined: Thu Jul 14, 2022 9:45 am
Contact:

Re: Module loading

Post by WinExperements »

So why the address of kernel symbol didn't setted after loading the module, just i got #UD because the address invalid?
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Module loading

Post by iansjack »

It might help to single-step through the relevant code in a debugger. Once you see what’s actually happening you have a better chance of determining the cause.
WinExperements
Member
Member
Posts: 97
Joined: Thu Jul 14, 2022 9:45 am
Contact:

Re: Module loading

Post by WinExperements »

One thing that i found while i debug this: address of kernel symbols when loading it, setted correctly but the address didn't changed in the code(i disassemble the module entry point with GDB). Why?
devc1
Member
Member
Posts: 439
Joined: Fri Feb 11, 2022 4:55 am
Location: behind the keyboard

Re: Module loading

Post by devc1 »

That means that the address of kernel symbols isn't set correctly.


For my drivers, I create a buffer which contains the kernel mode address space (address space buffer), you should change the values in the address space buffer not in the file buffer, when you finish you just free the file buffer from memory.

The size of the virtual buffer is equal to the highest (relative) virtual address, then you copy the content of each section in that buffer using AddressSpaceBuffer + section.virtualaddress

for e.g. if RelocSection.virtualaddress = 0x5000, you should set the values in ProgramAddressSpace + 0x5000.
Post Reply