static SCM load_thunk_from_fd_using_mmap (int fd) #define FUNC_NAME "load-thunk-from-disk" { Elf_Ehdr header; Elf_Phdr *ph; const char *err_msg = 0; char *base = 0; size_t n; int i; int start_segment = -1; int prev_segment = -1; int dynamic_segment = -1; SCM init = SCM_BOOL_F, entry = SCM_BOOL_F; if (full_read (fd, &header, sizeof header) != sizeof header) ABORT ("object file too small"); if ((err_msg = check_elf_header (&header))) goto cleanup; if (lseek (fd, header.e_phoff, SEEK_SET) == (off_t) -1) goto cleanup; n = header.e_phnum; ph = scm_gc_malloc_pointerless (n * sizeof (Elf_Phdr), "segment headers"); if (full_read (fd, ph, n * sizeof (Elf_Phdr)) != n * sizeof (Elf_Phdr)) ABORT ("failed to read program headers"); for (i = 0; i < n; i++) { if (!ph[i].p_memsz) continue; if (ph[i].p_filesz != ph[i].p_memsz) ABORT ("expected p_filesz == p_memsz"); if (!ph[i].p_flags) ABORT ("expected nonzero segment flags"); if (ph[i].p_type == PT_DYNAMIC) { if (dynamic_segment >= 0) ABORT ("expected only one PT_DYNAMIC segment"); dynamic_segment = i; } if (start_segment < 0) { if (!base && ph[i].p_vaddr) ABORT ("first loadable vaddr is not 0"); start_segment = prev_segment = i; continue; } if (ph[i].p_flags == ph[start_segment].p_flags) { if (ph[i].p_vaddr - ph[prev_segment].p_vaddr != ph[i].p_offset - ph[prev_segment].p_offset) ABORT ("coalesced segments not contiguous"); prev_segment = i; continue; } /* Otherwise we have a new kind of segment. Map previous segments. */ if (map_segments (fd, &base, &ph[start_segment], &ph[prev_segment])) goto cleanup; /* Open a new set of segments. */ start_segment = prev_segment = i; } /* Map last segments. */ if (start_segment < 0) ABORT ("no loadable segments"); if (map_segments (fd, &base, &ph[start_segment], &ph[prev_segment])) goto cleanup; if (dynamic_segment < 0) ABORT ("no PT_DYNAMIC segment"); if ((err_msg = process_dynamic_segment (base, &ph[dynamic_segment], &init, &entry))) goto cleanup; if (scm_is_true (init)) scm_call_0 (init); /* Finally! Return the thunk. */ return entry; /* FIXME: munmap on error? */ cleanup: { int errno_save = errno; (void) close (fd); errno = errno_save; if (errno) SCM_SYSERROR; scm_misc_error (FUNC_NAME, err_msg ? err_msg : "error loading ELF file", SCM_EOL); } }
int main(int argc, char **argv) { try { TCLAP::CmdLine cmd("Maps/Renames segments", ' ', "1.0"); TCLAP::ValueArg<std::string> log_filename("l","logfile", "Log file name (default is convert.log)", false, "convert.log", "string"); cmd.add( log_filename ); TCLAP::ValueArg<std::string> input_filetype("","inputtype", "Input file type. Can be\nauto - ViennaMesh automatically detects the file format (default)\nvtk - for VTK files\nmesh - for Netgen .mesh files\npoly - for Tetgen .poly files\ndeva - for GTS deva files", false, "auto", "string"); cmd.add( input_filetype ); TCLAP::ValueArg<std::string> output_filetype("","outputtype", "Output file type. Can be\nauto - ViennaMesh automatically detects the file format (default)\nvtk - for VTK files\nvmesh - for Vienna vmesh files", false, "auto", "string"); cmd.add( output_filetype ); TCLAP::ValueArg<std::string> segment_mapping_string("m","segment-mapping", "Segment mapping. Syntax: \"src_id,dst_id;src_id,dst_id\"", true, "", "string"); cmd.add( segment_mapping_string ); TCLAP::UnlabeledValueArg<std::string> input_filename( "input-filename", "Input file name", true, "", "InputFile" ); cmd.add( input_filename ); TCLAP::UnlabeledValueArg<std::string> output_filename( "output-filename", "Output file name", true, "", "OutputFile" ); cmd.add( output_filename ); cmd.parse( argc, argv ); viennamesh::logger().register_callback( new viennamesh::FileStreamCallback<viennamesh::FileStreamFormater>( log_filename.getValue() ) ); viennamesh::algorithm_handle reader( new viennamesh::io::mesh_reader() ); reader->set_input( "filename", input_filename.getValue() ); if (input_filetype.isSet() && (input_filetype.getValue() != "auto")) reader->set_input( "file_type", input_filetype.getValue() ); reader->run(); std::map<int, int> segment_mapping; std::list<std::string> split_mappings = stringtools::split_string( segment_mapping_string.getValue(), ";" ); for (std::list<std::string>::const_iterator mit = split_mappings.begin(); mit != split_mappings.end(); ++mit) { std::list<std::string> from_to = stringtools::split_string( *mit, "," ); std::list<std::string>::const_iterator it = from_to.begin(); if (it == from_to.end()) continue; int src_segment_id = lexical_cast<int>(*it); ++it; if (it == from_to.end()) continue; int dst_segment_id = lexical_cast<int>(*it); segment_mapping[src_segment_id] = dst_segment_id; } viennamesh::algorithm_handle map_segments( new viennamesh::map_segments() ); map_segments->set_input( "mesh", reader->get_output("mesh") ); map_segments->set_input( "segment_mapping", segment_mapping ); map_segments->run(); viennamesh::algorithm_handle writer( new viennamesh::io::mesh_writer() ); writer->set_input( "mesh", map_segments->get_output("mesh") ); writer->set_input( "quantities", reader->get_output("quantities") ); writer->set_input( "filename", output_filename.getValue() ); if (output_filetype.isSet() && (output_filetype.getValue() != "auto")) writer->set_input( "file_type", output_filetype.getValue() ); writer->run(); } catch (TCLAP::ArgException &e) // catch any exceptions { std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; } return 0; }
dso *load_elf(dso *loader, const char *name, const char *path, long fd, unsigned char rt_load, unsigned int rtld_mode, Elf32_auxv_t *auxv) { #ifdef D_LOAD sl_printf("\nLoading elf file: %s (%s)\n", path, name); #endif #ifdef SL_STATISTIC /* Some statistics */ loaded_dsos++; curr_loaded_dsos++; max_loaded_dsos = MAX(max_loaded_dsos, curr_loaded_dsos); #endif /* Get file information */ struct kernel_stat file_info; if(sl_fstat(fd, &file_info) == -1) { /* Close file */ sl_close(fd); /* Signal error (longjmp) if we load at runtime */ if(rt_load) signal_error(0, name, 0, "fstat failed"); /* Not at runtime -> fail */ sl_printf("Error load_elf: fstat failed while loading %s.\n", name); sl_exit(1); } /* Map entire file in memory */ void *file_map = sl_mmap(0, file_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if ((long)file_map == -1) { /* Close file */ sl_close(fd); /* Signal error (longjmp) if we load at runtime */ if(rt_load) signal_error(0, name, 0, "mmap failed"); /* Not at runtime -> fail */ sl_printf("Error load_elf: mmap of file %s failed.\n", name); sl_exit(1); } /* Get ELF header and check file */ Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *) file_map; long valid = check_elf(elf_hdr); if (valid != 0) { /* Invalid elf file */ sl_close(fd); /* Signal error (longjmp) if we load at runtime */ if(rt_load) signal_error(0, name, 0, "invalid ELF file"); /* Not at runtime -> fail */ sl_printf("Error load_elf: %s is not a valid ELF file (error: %d).\n", name, valid); sl_exit(1); } /* Get program and section header */ Elf32_Phdr *program_hdr = (Elf32_Phdr *) (file_map + elf_hdr->e_phoff); Elf32_Shdr *shdr = (Elf32_Shdr *) (file_map + elf_hdr->e_shoff); /* Segments (text and data) which we have to map in memory */ Elf32_Phdr *load_segments[2]; long num_load = 0; /* Create new shared object */ dso *so = sl_calloc(sizeof(dso), 1); /* Iterate over program headers */ unsigned long i = 0; for(i = 0; i < elf_hdr->e_phnum; ++i) { switch (program_hdr[i].p_type) { case PT_DYNAMIC: /* Dynamic Header */ so->dynamic_section = (Elf32_Dyn *)(program_hdr[i].p_vaddr); break; case PT_LOAD: /* Section must be mapped in memory */ if (num_load >= 2) { sl_printf("Error load_elf: more than two PT_LOAD segments!"); sl_exit(1); } load_segments[num_load++] = program_hdr+i; break; case PT_TLS: /* Thread Local Storage information*/ if (program_hdr[i].p_memsz == 0) break; /* Initialize TLS information */ so->tls_blocksize = program_hdr[i].p_memsz; so->tls_align = program_hdr[i].p_align; so->tls_initimage_size = program_hdr[i].p_filesz; /* TLS image (addr later adjusted) */ so->tls_initimage = (void *) program_hdr[i].p_vaddr; /* Assign next module ID */ so->tls_modid = ++GL(_dl_tls_max_dtv_idx); break; /* case PT_GNU_STACK: if (program_hdr[i].p_flags & PF_X) { sl_printf("Warning: executable stack\n"); sl_exit(1); } break; */ case PT_GNU_RELRO: /* Sections to set readonly after relocation */ /* Address is later adjusted */ so->relro = program_hdr[i].p_vaddr; so->relro_size = program_hdr[i].p_memsz; break; } } /* Map segments into memory and intitialize dso struct */ if(rtld_mode == 1 && auxv != NULL) { Elf32_Phdr *program_hdr_auxv; Elf32_Phdr *load_segments_auxv[2]; program_hdr_auxv = (Elf32_Phdr *)get_aux_value(auxv, AT_PHDR); uint32_t auxv_e_phnum = (uint32_t)get_aux_value(auxv, AT_PHNUM); unsigned long j = 0; unsigned int nr_load = 0; for(j = 0; j < auxv_e_phnum; j++) { switch (program_hdr_auxv[j].p_type) { case PT_LOAD: /* Section must be mapped in memory */ if (nr_load >= 2) { sl_exit(1); } load_segments_auxv[nr_load++] = program_hdr_auxv+j; break; } } map_segments_RTLD(fd, load_segments, elf_hdr->e_type, so, load_segments_auxv); } else { map_segments(fd, load_segments, elf_hdr->e_type, so); } so->ref_count = 1; so->deps_count = 0; so->name = name; so->path = path; so->type = elf_hdr->e_type; so->entry = (void*) elf_hdr->e_entry; so->loader = loader; so->dynamic_section = (Elf32_Dyn *) BYTE_STEP(so->dynamic_section, so->base_addr); so->program_header = (Elf32_Phdr *) BYTE_STEP(elf_hdr->e_phoff, so->text_addr); so->program_header_num = elf_hdr->e_phnum; so->l_real = so; /* Adjust address of TLS init image and relro address */ if (so->tls_initimage) { so->tls_initimage = (char *)so->tls_initimage + (long)so->base_addr; } if (so->relro) { so->relro = (Elf32_Addr) BYTE_STEP(so->relro, so->base_addr); } /* Iterate over section headers */ char *strtab = (char *)file_map + shdr[elf_hdr->e_shstrndx].sh_offset; char *sname=0; for (i=0; i<elf_hdr->e_shnum; ++i) { sname = strtab + shdr[i].sh_name; /* Save important sections */ if (sl_strncmp(sname, ".got", 5) == 0) { so->got = (char *) (so->base_addr + shdr[i].sh_addr); so->got_size = shdr[i].sh_size; } if (sl_strncmp(sname, ".plt", 5) == 0) { so->plt = (char *) (so->base_addr + shdr[i].sh_addr); so->plt_size = shdr[i].sh_size; } if (sl_strncmp(sname, ".got.plt", 9) == 0) { so->gotplt = (char *) (so->base_addr + shdr[i].sh_addr); so->gotplt_size = shdr[i].sh_size; } } /* Resolve */ Elf32_Dyn *dyn; long rpath=-1; for (dyn = so->dynamic_section; dyn->d_tag != DT_NULL; ++dyn) { switch (dyn->d_tag) { case DT_INIT: /* Initialization function */ so->init = (void (*)(int, char**, char**)) BYTE_STEP(dyn->d_un.d_ptr, so->base_addr); break; case DT_INIT_ARRAY: /* Array of initialization functions */ so->init_array = (Elf32_Addr *)BYTE_STEP(dyn->d_un.d_ptr, so->base_addr); break; case DT_INIT_ARRAYSZ: /* Size of init array */ so->init_array_sz = (long)dyn->d_un.d_val / sizeof(Elf32_Addr); break; case DT_FINI: /* Finalization function */ so->fini = (void (*)()) BYTE_STEP(dyn->d_un.d_ptr, so->base_addr); break; case DT_FINI_ARRAY: /* Array of finalization functions */ so->fini_array = (Elf32_Addr *)BYTE_STEP(dyn->d_un.d_ptr, so->base_addr); break; case DT_FINI_ARRAYSZ: /* Size of fini array */ so->fini_array_sz = (long)dyn->d_un.d_val / sizeof(Elf32_Addr); break; case DT_RUNPATH: /* String with library search paths */ rpath = dyn->d_un.d_val; break; case DT_RPATH: /* String with library search paths */ if (rpath == -1) rpath = dyn->d_un.d_val; break; case DT_PLTGOT: /* Plt part of the global offset table */ so->gotplt = (char *) BYTE_STEP(dyn->d_un.d_ptr, so->base_addr); break; case DT_REL: /* Relocation table */ so->rel = (Elf32_Rel *) BYTE_STEP(dyn->d_un.d_ptr, so->base_addr); break; case DT_RELSZ: /* Size of the relocation table */ so->relsz = (long)dyn->d_un.d_val / sizeof(Elf32_Rel); break; case DT_JMPREL: /* Plt relocations part of relocation table */ so->pltrel = (Elf32_Rel *) BYTE_STEP(dyn->d_un.d_ptr, so->base_addr); break; case DT_PLTRELSZ: /* Size of plt relocations part of relocation table */ so->pltrelsz = (long)dyn->d_un.d_val / sizeof(Elf32_Rel); break; case DT_HASH: /* ELF hash table */ so->hash_table = (Elf32_Word *) BYTE_STEP(dyn->d_un.d_ptr, so->base_addr); break; case DT_GNU_HASH: /* GNU hash table */ so->gnu_hash_table = (Elf32_Word *) BYTE_STEP(dyn->d_un.d_ptr, so->base_addr); break; case DT_SYMTAB: /* Dynamic symbol table */ so->symbol_table = (Elf32_Sym *) BYTE_STEP(dyn->d_un.d_ptr, so->base_addr); break; case DT_VERDEF: /* Versions defined in this DSO */ so->verdef = (Elf32_Verdef *) BYTE_STEP(dyn->d_un.d_ptr, so->base_addr); break; case DT_VERDEFNUM: /* Number of versions defined in this DSO */ so->verdef_num = (unsigned long) dyn->d_un.d_val; break; case DT_VERNEED: /* Versions needed by this DSO */ so->verneed = (Elf32_Verneed *) BYTE_STEP(dyn->d_un.d_ptr, so->base_addr); break; case DT_VERNEEDNUM: /* Number of versions needed by this DSO */ so->verneed_num = (unsigned long) dyn->d_un.d_val; break; case DT_VERSYM: /* Version symbol table */ so->versym = (Elf32_Half *) BYTE_STEP(dyn->d_un.d_ptr, so->base_addr); break; case DT_STRTAB: /* Dynamic string table */ so->string_table = (char *) so->base_addr + dyn->d_un.d_ptr; break; case DT_NEEDED: /* Dependencies on other DSOs */ /* Count the number of direct dependencies */ so->deps_count++; break; case DT_FLAGS: /* Flags */ so->flags = dyn->d_un.d_val; if ((so->flags & DF_SYMBOLIC) || (so->flags & DF_TEXTREL)) { sl_printf("Error load_elf: not supported flag 0x%x in %s.\n", so->flags, so->name); sl_exit(1); } break; case DT_FLAGS_1: /* Flags */ so->flags_1 = dyn->d_un.d_val; if ((so->flags_1 & DF_1_GROUP) || (so->flags_1 & DF_1_LOADFLTR) || (so->flags_1 & DF_1_DIRECT) || (so->flags_1 & DF_1_INTERPOSE) || (so->flags_1 & DF_1_NODEFLIB) // || (so->flags_1 & DF_1_NODUMP) || (so->flags_1 & DF_1_CONFALT) || (so->flags_1 & DF_1_ENDFILTEE) || (so->flags_1 & DF_1_DISPRELDNE) || (so->flags_1 & DF_1_DISPRELPND)) { sl_printf("Error load_elf: not supported flag_1 0x%x in %s.\n", so->flags_1, so->name); sl_exit(1); } break; } } /* Initialize the versioning data */ init_versions(so); /* Set library search paths */ if (rpath != -1) so->search_path = decompose_path(so->string_table+rpath,so->name, "RPATH"); /* Allocate memory for deps */ if (so->deps_count != 0) so->deps = sl_malloc(so->deps_count * sizeof(dso *)); /* Add shared object to chain */ chain_add(so); /* Now that we have the stringtable, iterate a second time over dynamic section to get the names of the needed libraries. */ char *lib_name = 0; long num = 0; for (dyn = so->dynamic_section; dyn->d_tag != DT_NULL; dyn++) { switch (dyn->d_tag) { case DT_NEEDED: /* Get name of needed lib */ lib_name = (char *)so->string_table + dyn->d_un.d_val; #ifdef D_LOAD sl_printf("Found dependency in %s: %s\n", so->name, lib_name); #endif /* Do not load the linux dynamic loader, because we replace it */ if (sl_strncmp(lib_name, LINUX_LOADER, sl_strnlen(LINUX_LOADER, MAX_LIB_NAME))==0) { so->deps_count--; continue; } /* Check if we already loaded it */ dso *so_search = chain_search(lib_name); if (so_search == 0) { /* Not already loaded, search for it */ char *lib_path; long fd = search_lib(so, lib_name, &lib_path); if (fd == -1) { /* Not found, signal error (longjmp) if we load at runtime */ if(rt_load) signal_error(0, lib_name, 0, "cannot open shared object file"); /* Not at runtime -> fail */ sl_printf("Error load_elf: lib %s not found.\n", lib_name); sl_exit(1); } /* Copy name */ char *lname = sl_malloc(MAX_LIB_NAME); sl_strncpy(lname, lib_name, MAX_LIB_NAME); PROT_DATA(lname, MAX_LIB_NAME); /* Load it */ dso *so_loaded = load_elf(so, lname, lib_path, fd, rt_load, 0, NULL); /* Increment local scope counter and add to direct deps */ so->lscope_num += so_loaded->lscope_num; so->deps[num] = so_loaded; } else { /* Increment reference counter */ UNPROT(so_search); so_search->ref_count++; PROT(so_search); /* Increment local scope counter and add to direct deps */ so->lscope_num += so_search->lscope_num; so->deps[num] = so_search; } num++; so->lscope_num++; break; } } so->lscope_num++; /* Create local scope list. This has to be done in breadth-first order! */ so->lscope = sl_malloc(so->lscope_num * sizeof(dso *)); long j,k,l; i = 0; /* Add object itself */ so->lscope[i++] = so; /* First add direct dependencies */ for (l=0; l<so->deps_count; ++l) { so->lscope[i] = so->deps[l]; ++i; } /* Now add deps recursively */ for (l=0; l<so->deps_count; ++l) { for (k=0; k<so->deps[l]->lscope_num; ++k) { dso *dep = so->deps[l]->lscope[k]; /* Check if already added */ long found = 0; for (j=0; j<i; ++j) { if (so->lscope[j] == dep) found = 1; } if (found || !dep) continue; so->lscope[i] = dep; ++i; } } /* Initialize Global Offset Table */ init_got(so); #if defined(VERIFY_CFTX) /* Add object to dso chain if libdetox wants to check the control flow transfers */ add_dso(so, (char *)file_map); #if defined(CALLBACK_MAIN_DETECTION) || defined(CALLBACK_DATA_SECTION_SEARCH) /* Right after loading the dso we need to detect the libc callbacks to main/__libc_csu_init */ if(so->loader == NULL && dso_chain->next != 0) { /* This is the main executable. Get the immediate values pushed on the stack right before __libc_start_main is called. */ #if defined(CALLBACK_MAIN_DETECTION) /* This is the main function callback detection hack! * - it tries to find the callback pointers passed to libc * - and it adds them to the callback table so CFTX checks will pass */ long count = 0; unsigned char *iptr; unsigned long ptr; if(so->type == ET_EXEC) iptr = (unsigned char *)so->entry; else /* PIE executable */ iptr = (unsigned char *)((unsigned long)so->base_addr + (unsigned long)so->entry); /* TODO: 48? Remove hardcoded value. */ while(count<48) { /* is it a push instruction with a 32bit immediate value? */ if(*iptr == 0x68) { /* add the immediate value pushed to the stack */ ptr = *((unsigned long*)(++iptr)); fbt_add_callback(dso_chain->next, (void*)ptr); iptr+=4; count+=5; } else { iptr++; count++; } /* in case we reached NOPs we can just stop looking for the pushes */ if(*iptr == 0x90) break; } #endif /* CALLBACK_MAIN_DETECTION */ #if defined(CALLBACK_DATA_SECTION_SEARCH) /* Some x* applications have global function pointers in their .data section. * This are probably widget class objects and their members. It seems that there is no other * way to detect these potential callbacks than scanning through the .data section. This has * only to be done for prelinked executables as we will detect the other callbacks during relocation. */ unsigned long *dptr = so->data_addr; if(dptr) { while((unsigned long)dptr < ((unsigned long)so->data_addr+(unsigned long)so->data_size)) { /* check if the obtained address points to executable memory (potential callback target) */ if (PTR_IN_REGION(*dptr, so->text_addr, so->text_size) || PTR_IN_REGION(*dptr, so->dso->init, so->dso->init_size) || PTR_IN_REGION(*dptr, so->dso->fini, so->dso->fini_size)) { fbt_add_callback(so->dso, (void*)*dptr); } dptr++; /* increase by sizeof(unsigned long) = bytes */ } } /* go through GOT */ dptr = (unsigned long*)(so->got); if(dptr) { while((unsigned long)dptr < ((unsigned long)so->got+(unsigned long)so->got_size)) { /* check if the obtained address points to executable memory (potential callback target) */ if (PTR_IN_REGION(*dptr, so->text_addr, so->text_size) || PTR_IN_REGION(*dptr, so->dso->init, so->dso->init_size) || PTR_IN_REGION(*dptr, so->dso->fini, so->dso->fini_size)) { fbt_add_callback(so->dso, (void*)*dptr); } dptr++; /* increase by sizeof(unsigned long) = bytes */ } } /* go through GOT.PLT */ dptr = (unsigned long*)(so->gotplt); if(dptr) { while((unsigned long)dptr < ((unsigned long)so->gotplt+(unsigned long)so->gotplt_size)) { /* check if the obtained address points to executable memory (potential callback target) */ if (PTR_IN_REGION(*dptr, so->text_addr, so->text_size) || PTR_IN_REGION(*dptr, so->dso->init, so->dso->init_size) || PTR_IN_REGION(*dptr, so->dso->fini, so->dso->fini_size)) { fbt_add_callback(so->dso, (void*)*dptr); } dptr++; /* increase by sizeof(unsigned long) = bytes */ } } /* go through rodata */ dptr = (unsigned long*)(so->dso->rodata); if(dptr) { while((unsigned long)dptr < ((unsigned long)so->dso->rodata+(unsigned long)so->dso->rodata_size)) { /* check if the obtained address points to executable memory (potential callback target) */ if (PTR_IN_REGION(*dptr, so->text_addr, so->text_size) || PTR_IN_REGION(*dptr, so->dso->init, so->dso->init_size) || PTR_IN_REGION(*dptr, so->dso->fini, so->dso->fini_size)) { fbt_add_callback(so->dso, (void*)*dptr); } dptr++; /* increase by sizeof(unsigned long) = bytes */ } } /* go through reldyn */ dptr = (unsigned long*)(so->dso->reldyn); if(dptr) { while((unsigned long)dptr < ((unsigned long)so->dso->reldyn+(unsigned long)so->dso->reldyn_size)) { /* check if the obtained address points to executable memory (potential callback target) */ if (PTR_IN_REGION(*dptr, so->text_addr, so->text_size) || PTR_IN_REGION(*dptr, so->dso->init, so->dso->init_size) || PTR_IN_REGION(*dptr, so->dso->fini, so->dso->fini_size)) { fbt_add_callback(so->dso, (void*)*dptr); } dptr++; /* increase by sizeof(unsigned long) = bytes */ } } /* go through relplt */ dptr = (unsigned long*)(so->dso->relplt); if(dptr) { while((unsigned long)dptr < ((unsigned long)so->dso->relplt+(unsigned long)so->dso->relplt_size)) { /* check if the obtained address points to executable memory (potential callback target) */ if (PTR_IN_REGION(*dptr, so->text_addr, so->text_size) || PTR_IN_REGION(*dptr, so->dso->init, so->dso->init_size) || PTR_IN_REGION(*dptr, so->dso->fini, so->dso->fini_size)) { fbt_add_callback(so->dso, (void*)*dptr); } dptr++; /* increase by sizeof(unsigned long) = bytes */ } } #endif /* CALLBACK_DATA_SECTION_SEARCH */ } #endif /* defined(CALLBACK_MAIN_DETECTION) || defined(CALLBACK_DATA_SECTION_SEARCH) */ #if defined(CALLBACK_LIBRARIES_DATA_SECTION_SEARCH) if(so->loader != NULL) { /* it's a library! */ unsigned long *dptr = so->data_addr; if(dptr) { while((unsigned long)dptr < ((unsigned long)so->data_addr+(unsigned long)so->data_size)) { /* check if the obtained address points to executable memory (potential callback target) */ if (PTR_IN_REGION(*dptr, so->text_addr, so->text_size) || PTR_IN_REGION(*dptr, so->dso->init, so->dso->init_size) || PTR_IN_REGION(*dptr, so->dso->fini, so->dso->fini_size)) { fbt_add_callback(so->dso, (void*)*dptr); } dptr++; /* increase by sizeof(unsigned long) = bytes */ } } /* go through GOT */ dptr = (unsigned long*)(so->got); if(dptr) { while((unsigned long)dptr < ((unsigned long)so->got+(unsigned long)so->got_size)) { /* check if the obtained address points to executable memory (potential callback target) */ if (PTR_IN_REGION(*dptr, so->text_addr, so->text_size) || PTR_IN_REGION(*dptr, so->dso->init, so->dso->init_size) || PTR_IN_REGION(*dptr, so->dso->fini, so->dso->fini_size)) { fbt_add_callback(so->dso, (void*)*dptr); } dptr++; /* increase by sizeof(unsigned long) = bytes */ } } /* go through GOT.PLT */ dptr = (unsigned long*)(so->gotplt); if(dptr) { while((unsigned long)dptr < ((unsigned long)so->gotplt+(unsigned long)so->gotplt_size)) { /* check if the obtained address points to executable memory (potential callback target) */ if (PTR_IN_REGION(*dptr, so->text_addr, so->text_size) || PTR_IN_REGION(*dptr, so->dso->init, so->dso->init_size) || PTR_IN_REGION(*dptr, so->dso->fini, so->dso->fini_size)) { fbt_add_callback(so->dso, (void*)*dptr); } dptr++; /* increase by sizeof(unsigned long) = bytes */ } } /* go through rodata */ dptr = (unsigned long*)(so->dso->rodata); if(dptr) { while((unsigned long)dptr < ((unsigned long)so->dso->rodata+(unsigned long)so->dso->rodata_size)) { /* check if the obtained address points to executable memory (potential callback target) */ if (PTR_IN_REGION(*dptr, so->text_addr, so->text_size) || PTR_IN_REGION(*dptr, so->dso->init, so->dso->init_size) || PTR_IN_REGION(*dptr, so->dso->fini, so->dso->fini_size)) { fbt_add_callback(so->dso, (void*)*dptr); } dptr++; /* increase by sizeof(unsigned long) = bytes */ } } /* go through reldyn */ dptr = (unsigned long*)(so->dso->reldyn); if(dptr) { while((unsigned long)dptr < ((unsigned long)so->dso->reldyn+(unsigned long)so->dso->reldyn_size)) { /* check if the obtained address points to executable memory (potential callback target) */ if (PTR_IN_REGION(*dptr, so->text_addr, so->text_size) || PTR_IN_REGION(*dptr, so->dso->init, so->dso->init_size) || PTR_IN_REGION(*dptr, so->dso->fini, so->dso->fini_size)) { fbt_add_callback(so->dso, (void*)*dptr); } dptr++; /* increase by sizeof(unsigned long) = bytes */ } } /* go through relplt */ dptr = (unsigned long*)(so->dso->relplt); if(dptr) { while((unsigned long)dptr < ((unsigned long)so->dso->relplt+(unsigned long)so->dso->relplt_size)) { /* check if the obtained address points to executable memory (potential callback target) */ if (PTR_IN_REGION(*dptr, so->text_addr, so->text_size) || PTR_IN_REGION(*dptr, so->dso->init, so->dso->init_size) || PTR_IN_REGION(*dptr, so->dso->fini, so->dso->fini_size)) { fbt_add_callback(so->dso, (void*)*dptr); } dptr++; /* increase by sizeof(unsigned long) = bytes */ } } } #endif /* CALLBACK_LIBRARIES_DATA_SECTION_SEARCH */ #endif /* VERIFY_CFTX */ /* All necessary information in memory -> unmap file */ sl_munmap(file_map, file_info.st_size); sl_close(fd); /* Protect dependencies and local search scope */ PROT_DATA(so->deps, so->deps_count*sizeof(dso *)); PROT_DATA(so->lscope, so->lscope_num*sizeof(dso *)); return so; }