int makedir(char *pathname) { char path[255]; int i = 0, p; int ret = opendir(pathname); if(ret != INVALID_INODENO || pathname[0] != '/') return -1; while(pathname[i]) { if(pathname[i ++] == '/') p = i; } for(i = 0; i < p; i++) path[i] = pathname[i]; path[i] = '\0'; int inodeno = opendir(path); if(inodeno != INVALID_INODENO) { INODE *pdirinode = open_inode(inodeno); uint32_t finode = apply_inode(); INODE *pfinode = open_inode(finode); pfinode->filesz = 0; pfinode->filetype = 'd'; addto_dir(pdirinode, pfinode, &pathname[p]); close_inode(pfinode); close_inode(pdirinode); return 0; } return -1; }
int list(TrapFrame *tf) { int i, j, total_size = 0, count = 0; char name[255]; DIR_ATTR da = {0}; FILE_ATTR fa[32] = {{0}}; char *path = (char *)tf->ebx; uint32_t inodeno = opendir(path); if(inodeno == INVALID_INODENO) return -1; printk("directory %s:\n\n", path); INODE *pinode = open_inode(inodeno); if(tf->edx == 1) { if(tf->ecx == 1) printk("%c %d\t%s\n", 'd', pinode->filesz, "."); else printk("%s \t", "."); } fs_read(pinode, 0, sizeof(DIR_ATTR), &da); for(i = 0; i < da.nr_index; i += 32) { int left = min(sizeof(fa), (da.nr_index - i) * sizeof(FILE_ATTR)); fs_read(pinode, sizeof(DIR_ATTR) + i * sizeof(FILE_ATTR), left, fa); for(j = 0; j < left / sizeof(FILE_ATTR); j++) { if(fa[j].dirty == 1) { fs_read(pinode, fa[j].filename_st, fa[j].len + 1, name); INODE *pfinode = open_inode(fa[j].inode); if(name[0] != '.' || tf->edx == 1) { if(tf->ecx == 1) printk("%c %d\t%s\n", pfinode->filetype, pfinode->filesz, name); else printk("%s \t", name); } total_size += pfinode->filesz; count ++; close_inode(pfinode); } } } if(tf->ecx == 1) printk("total:%d, size:%d\n", count, total_size); printk("\n"); close_inode(pinode); return 0; }
ino_t read_log_online(ino_t inode) { char buffer[BUFFER_LENGTH]; struct stat sbuf; time_t time; FILE *fp = open_inode(inode); if(fp == NULL) { fprintf(stderr, "file open error 1: inode %ld\n", inode); return -1; } do{ while (TRUE) { memset(&buffer, 0, BUFFER_LENGTH); while(fgets(& buffer[0], BUFFER_LENGTH, fp) == NULL) { if(fstat(fileno(fp), &sbuf) == -1) { fprintf(stderr, "stat fails: inode %ld\n", inode); continue; } time = sbuf.st_mtime; ino_t next_inode = find_next_file(time, sbuf.st_ino); if(next_inode > 0) { while(fgets(& buffer[0], BUFFER_LENGTH, fp) != NULL) { // check the log again. UBSI_buffer(buffer); } // At this point, the next log is available and the current log does not have any new event. //Safe to close the current one and process the next log fclose(fp); return next_inode; } } UBSI_buffer(buffer); } } while (FALSE); }
uint32_t opendir(char *filename) { int i, j; DIR_ATTR da = {0}; FILE_ATTR fa[32] = {{0}}; char name[255], path[255]; int is_dir = 0, p = 1, len = strlen(filename); INODE *pinode = open_inode(0); if(filename[0] != '/') { close_inode(pinode); return INVALID_INODENO; } if(len == 1) { int t = pinode->inodeno; close_inode(pinode); return t; } while(p < len) { int find_sub = 0; is_dir = 0; for(i = p; i <= len; i++) { if(filename[i] == '/') { is_dir = 1; path[i - p] = '\0'; break; } path[i - p] = filename[i]; } p = i + 1; /* read directory attribute */ fs_read(pinode, 0, sizeof(DIR_ATTR), &da); for(i = 0; i < da.nr_index; i += 32) { int left = min(sizeof(fa), (da.nr_index - i) * sizeof(FILE_ATTR)); fs_read(pinode, sizeof(DIR_ATTR) + i * sizeof(FILE_ATTR), left, fa); for(j = 0; j < left / sizeof(FILE_ATTR); j++) { if(fa[j].dirty == 1) { fs_read(pinode, fa[j].filename_st, fa[j].len + 1, name); /* find file with the same name of path */ if(strcmp(name, path) == 0) { close_inode(pinode); pinode = open_inode(fa[j].inode); if(is_dir && pinode->filetype == 'd') { find_sub = 1; if(p >= len) { int tmp = pinode->inodeno; close_inode(pinode); return tmp; } break; } if(!is_dir && pinode->filetype == '-') { close_inode(pinode); return fa[j].inode; } } } } if(find_sub) break; } close_inode(pinode); if(!find_sub) break; } return INVALID_INODENO; }
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) { struct elfhdr elf_ex; struct elfhdr interp_elf_ex; struct file * file; struct exec interp_ex; struct inode *interpreter_inode; unsigned int load_addr; unsigned int interpreter_type = INTERPRETER_NONE; int i; int old_fs; int error; struct elf_phdr * elf_ppnt, *elf_phdata; int elf_exec_fileno; unsigned int elf_bss, k, elf_brk; int retval; char * elf_interpreter; unsigned int elf_entry; int status; unsigned int start_code, end_code, end_data; unsigned int elf_stack; char passed_fileno[6]; status = 0; load_addr = 0; elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ if (elf_ex.e_ident[0] != 0x7f || strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) return -ENOEXEC; /* First of all, some simple consistency checks */ if(elf_ex.e_type != ET_EXEC || (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) || (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops || !bprm->inode->i_op->default_file_ops->mmap)){ return -ENOEXEC; }; /* Now read in all of the header information */ elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * elf_ex.e_phnum, GFP_KERNEL); old_fs = get_fs(); set_fs(get_ds()); retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata, elf_ex.e_phentsize * elf_ex.e_phnum); set_fs(old_fs); if (retval < 0) { kfree (elf_phdata); return retval; } elf_ppnt = elf_phdata; elf_bss = 0; elf_brk = 0; elf_exec_fileno = open_inode(bprm->inode, O_RDONLY); if (elf_exec_fileno < 0) { kfree (elf_phdata); return elf_exec_fileno; } file = current->files->fd[elf_exec_fileno]; elf_stack = 0xffffffff; elf_interpreter = NULL; start_code = 0; end_code = 0; end_data = 0; old_fs = get_fs(); set_fs(get_ds()); for(i=0;i < elf_ex.e_phnum; i++){ if(elf_ppnt->p_type == PT_INTERP) { /* This is the program interpreter used for shared libraries - for now assume that this is an a.out format binary */ elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, GFP_KERNEL); retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter, elf_ppnt->p_filesz); #if 0 printk("Using ELF interpreter %s\n", elf_interpreter); #endif if(retval >= 0) retval = namei(elf_interpreter, &interpreter_inode); if(retval >= 0) retval = read_exec(interpreter_inode,0,bprm->buf,128); if(retval >= 0){ interp_ex = *((struct exec *) bprm->buf); /* exec-header */ interp_elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ }; if(retval < 0) { kfree (elf_phdata); kfree(elf_interpreter); return retval; }; }; elf_ppnt++; }; set_fs(old_fs); /* Some simple consistency checks for the interpreter */ if(elf_interpreter){ interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; if(retval < 0) { kfree(elf_interpreter); kfree(elf_phdata); return -ELIBACC; }; /* Now figure out which format our binary is */ if((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) && (N_MAGIC(interp_ex) != QMAGIC)) interpreter_type = INTERPRETER_ELF; if (interp_elf_ex.e_ident[0] != 0x7f || strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0) interpreter_type &= ~INTERPRETER_ELF; if(!interpreter_type) { kfree(elf_interpreter); kfree(elf_phdata); return -ELIBBAD; }; } /* OK, we are done with that, now set up the arg stuff, and then start this sucker up */ if (!bprm->sh_bang) { char * passed_p; if(interpreter_type == INTERPRETER_AOUT) { sprintf(passed_fileno, "%d", elf_exec_fileno); passed_p = passed_fileno; if(elf_interpreter) { bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2); bprm->argc++; }; }; if (!bprm->p) { if(elf_interpreter) { kfree(elf_interpreter); } kfree (elf_phdata); return -E2BIG; } } /* OK, This is the point of no return */ flush_old_exec(bprm); current->mm->end_data = 0; current->mm->end_code = 0; current->mm->start_mmap = ELF_START_MMAP; current->mm->mmap = NULL; elf_entry = (unsigned int) elf_ex.e_entry; /* Do this so that we can load the interpreter, if need be. We will change some of these later */ current->mm->rss = 0; bprm->p += change_ldt(0, bprm->page); current->mm->start_stack = bprm->p; /* Now we do a little grungy work by mmaping the ELF image into the correct location in memory. At this point, we assume that the image should be loaded at fixed address, not at a variable address. */ old_fs = get_fs(); set_fs(get_ds()); elf_ppnt = elf_phdata; for(i=0;i < elf_ex.e_phnum; i++){ if(elf_ppnt->p_type == PT_INTERP) { /* Set these up so that we are able to load the interpreter */ /* Now load the interpreter into user address space */ set_fs(old_fs); if(interpreter_type & 1) elf_entry = load_aout_interp(&interp_ex, interpreter_inode); if(interpreter_type & 2) elf_entry = load_elf_interp(&interp_elf_ex, interpreter_inode); old_fs = get_fs(); set_fs(get_ds()); iput(interpreter_inode); kfree(elf_interpreter); if(elf_entry == 0xffffffff) { printk("Unable to load interpreter\n"); kfree(elf_phdata); send_sig(SIGSEGV, current, 0); return 0; }; }; if(elf_ppnt->p_type == PT_LOAD) { error = do_mmap(file, elf_ppnt->p_vaddr & 0xfffff000, elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, elf_ppnt->p_offset & 0xfffff000); #ifdef LOW_ELF_STACK if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack) elf_stack = elf_ppnt->p_vaddr & 0xfffff000; #endif if(!load_addr) load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; k = elf_ppnt->p_vaddr; if(k > start_code) start_code = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; if(k > elf_bss) elf_bss = k; if((elf_ppnt->p_flags | PROT_WRITE) && end_code < k) end_code = k; if(end_data < k) end_data = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; if(k > elf_brk) elf_brk = k; }; elf_ppnt++; }; set_fs(old_fs); kfree(elf_phdata); if(interpreter_type != INTERPRETER_AOUT) sys_close(elf_exec_fileno); /* The following 3 lines need a little bit of work if we are loading an iBCS2 binary. We should initially load it this way, and if we get a lcall7, then we should look to see if the iBCS2 execution profile is present. If it is, then switch to that, otherwise bomb. */ current->personality = PER_LINUX; current->lcall7 = no_lcall7; current->signal_map = current->signal_invmap = ident_map; current->executable = bprm->inode; bprm->inode->i_count++; #ifdef LOW_ELF_STACK current->start_stack = p = elf_stack - 4; #endif bprm->p -= MAX_ARG_PAGES*PAGE_SIZE; bprm->p = (unsigned long) create_elf_tables((char *)bprm->p, bprm->argc, bprm->envc, (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL), load_addr, (interpreter_type == INTERPRETER_AOUT ? 0 : 1)); if(interpreter_type == INTERPRETER_AOUT) current->mm->arg_start += strlen(passed_fileno) + 1; current->mm->start_brk = current->mm->brk = elf_brk; current->mm->end_code = end_code; current->mm->start_code = start_code; current->mm->end_data = end_data; current->mm->start_stack = bprm->p; current->suid = current->euid = bprm->e_uid; current->sgid = current->egid = bprm->e_gid; /* Calling sys_brk effectively mmaps the pages that we need for the bss and break sections */ current->mm->brk = (elf_bss + 0xfff) & 0xfffff000; sys_brk((elf_brk + 0xfff) & 0xfffff000); padzero(elf_bss); /* Why this, you ask??? Well SVr4 maps page 0 as read-only, and some applications "depend" upon this behavior. Since we do not have the power to recompile these, we emulate the SVr4 behavior. Sigh. */ error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); regs->eip = elf_entry; /* eip, magic happens :-) */ regs->esp = bprm->p; /* stack pointer */ if (current->flags & PF_PTRACED) send_sig(SIGTRAP, current, 0); return 0; }
static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex, struct inode * interpreter_inode) { struct file * file; struct elf_phdr *elf_phdata = NULL; struct elf_phdr *eppnt; unsigned int len; unsigned int load_addr; int elf_exec_fileno; int elf_bss; int old_fs, retval; unsigned int last_bss; int error; int i, k; elf_bss = 0; last_bss = 0; error = load_addr = 0; /* First of all, some simple consistency checks */ if((interp_elf_ex->e_type != ET_EXEC && interp_elf_ex->e_type != ET_DYN) || (interp_elf_ex->e_machine != EM_386 && interp_elf_ex->e_machine != EM_486) || (!interpreter_inode->i_op || !interpreter_inode->i_op->default_file_ops->mmap)){ return 0xffffffff; }; /* Now read in all of the header information */ if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) return 0xffffffff; elf_phdata = (struct elf_phdr *) kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL); if(!elf_phdata) return 0xffffffff; old_fs = get_fs(); set_fs(get_ds()); retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, (char *) elf_phdata, sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); set_fs(old_fs); elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY); if (elf_exec_fileno < 0) return 0xffffffff; file = current->files->fd[elf_exec_fileno]; eppnt = elf_phdata; for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) if(eppnt->p_type == PT_LOAD) { error = do_mmap(file, eppnt->p_vaddr & 0xfffff000, eppnt->p_filesz + (eppnt->p_vaddr & 0xfff), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | (interp_elf_ex->e_type == ET_EXEC ? MAP_FIXED : 0), eppnt->p_offset & 0xfffff000); if(!load_addr && interp_elf_ex->e_type == ET_DYN) load_addr = error; k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; if(k > elf_bss) elf_bss = k; if(error < 0 && error > -1024) break; /* Real error */ k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; if(k > last_bss) last_bss = k; } /* Now use mmap to map the library into memory. */ sys_close(elf_exec_fileno); if(error < 0 && error > -1024) { kfree(elf_phdata); return 0xffffffff; } padzero(elf_bss); len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */ /* Map the last of the bss segment */ if (last_bss > len) do_mmap(NULL, len, last_bss-len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); kfree(elf_phdata); return ((unsigned int) interp_elf_ex->e_entry) + load_addr; }
static int load_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok) { COFF_FILHDR *coff_hdr = (COFF_FILHDR *) bprm->buf; /* COFF Header */ COFF_SCNHDR *sect_bufr; /* Pointer to section table */ COFF_SCNHDR *text_sect; /* Pointer to the text section */ COFF_SCNHDR *data_sect; /* Pointer to the data section */ COFF_SCNHDR *bss_sect; /* Pointer to the bss section */ int text_count; /* Number of text sections */ int data_count; /* Number of data sections */ int bss_count; /* Number of bss sections */ int lib_count; /* Number of lib sections */ unsigned int start_addr = 0;/* Starting location for program */ int status = 0; /* Result status register */ int fd = -1; /* Open file descriptor */ struct file *fp = NULL; /* Pointer to the file at "fd" */ short int sections = 0; /* Number of sections in the file */ short int aout_size = 0; /* Size of the a.out header area */ short int flags; /* Flag bits from the COFF header */ #ifdef COFF_DEBUG printk ("binfmt_coff entry: %s\n", bprm->filename); #endif /* * Validate the magic value for the object file. */ do { if (COFF_I386BADMAG (*coff_hdr)) { #ifdef COFF_DEBUG printk ("bad filehdr magic\n"); #endif status = -ENOEXEC; break; } /* * The object file should have 32 BIT little endian format. Do not allow * it to have the 16 bit object file flag set as Linux is not able to run * on the 80286/80186/8086. */ flags = COFF_SHORT (coff_hdr->f_flags); if ((flags & (COFF_F_AR32WR | COFF_F_AR16WR)) != COFF_F_AR32WR) { #ifdef COFF_DEBUG printk ("invalid f_flags bits\n"); #endif status = -ENOEXEC; break; } /* * Extract the header information which we need. */ sections = COFF_SHORT (coff_hdr->f_nscns); /* Number of sections */ aout_size = COFF_SHORT (coff_hdr->f_opthdr); /* Size of opt. headr */ /* * If the file is not executable then reject the execution. This means * that there must not be external references. */ if ((flags & COFF_F_EXEC) == 0) { #ifdef COFF_DEBUG printk ("not executable bit\n"); #endif status = -ENOEXEC; break; } /* * There must be at least one section. */ if (sections == 0) { #ifdef COFF_DEBUG printk ("no sections\n"); #endif status = -ENOEXEC; break; } /* * Do some additional consistency checks. * The system requires mapping for this loader. If you try * to use a file system with no mapping, the format is not valid. */ if (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops->mmap) { #ifdef COFF_DEBUG printk ("no mmap in fs\n"); #endif status = -ENOEXEC; } } while (0); /* * Allocate a buffer to hold the entire coff section list. */ if (status >= 0) { int nbytes = sections * COFF_SCNHSZ; sect_bufr = (COFF_SCNHDR *) kmalloc (nbytes, GFP_KERNEL); if (0 == sect_bufr) { #ifdef COFF_DEBUG printk ("kmalloc failed\n"); #endif status = -ENOEXEC; } /* * Read the section list from the disk file. */ else { int old_fs = get_fs (); set_fs (get_ds ()); /* Make it point to the proper location */ status = read_exec (bprm->inode, /* INODE for file */ aout_size + COFF_FILHSZ, /* Offset in the file */ (char *) sect_bufr, /* Buffer for read */ nbytes); /* Byte count reqd. */ set_fs (old_fs); /* Restore the selector */ #ifdef COFF_DEBUG if (status < 0) printk ("read aout hdr, status = %d\n", status); #endif } } else sect_bufr = NULL; /* Errors do not have a section buffer */ /* * Count the number of sections for the required types and store the location * of the last section for the three primary types. */ text_count = 0; data_count = 0; bss_count = 0; lib_count = 0; text_sect = NULL; data_sect = NULL; bss_sect = NULL; /* * Loop through the sections and find the various types */ if (status >= 0) { int nIndex; COFF_SCNHDR *sect_ptr = sect_bufr; for (nIndex = 0; nIndex < sections; ++nIndex) { long int sect_flags = COFF_LONG (sect_ptr->s_flags); switch (sect_flags) { case COFF_STYP_TEXT: text_sect = sect_ptr; ++text_count; status = is_properly_aligned (sect_ptr); break; case COFF_STYP_DATA: data_sect = sect_ptr; ++data_count; status = is_properly_aligned (sect_ptr); break; case COFF_STYP_BSS: bss_sect = sect_ptr; ++bss_count; break; case COFF_STYP_LIB: #ifdef COFF_DEBUG printk (".lib section found\n"); #endif ++lib_count; break; default: break; } sect_ptr = (COFF_SCNHDR *) & ((char *) sect_ptr)[COFF_SCNHSZ]; } /* * Ensure that there are the required sections. There must be one text * sections and one each of the data and bss sections for an executable. * A library may or may not have a data / bss section. */ if (text_count != 1) { status = -ENOEXEC; #ifdef COFF_DEBUG printk ("no text sections\n"); #endif } else { if (lib_ok) { if (data_count != 1 || bss_count != 1) { status = -ENOEXEC; #ifdef COFF_DEBUG printk ("no .data nor .bss sections\n"); #endif } } } } /* * If there is no additional header then assume the file starts at * the first byte of the text section. This may not be the proper place, * so the best solution is to include the optional header. A shared library * __MUST__ have an optional header to indicate that it is a shared library. */ if (status >= 0) { if (aout_size == 0) { if (!lib_ok) { status = -ENOEXEC; #ifdef COFF_DEBUG printk ("no header in library\n"); #endif } start_addr = COFF_LONG (text_sect->s_vaddr); } /* * There is some header. Ensure that it is sufficient. */ else { if (aout_size < COFF_AOUTSZ) { status = -ENOEXEC; #ifdef COFF_DEBUG printk ("header too small\n"); #endif } else { COFF_AOUTHDR *aout_hdr = /* Pointer to a.out header */ (COFF_AOUTHDR *) & ((char *) coff_hdr)[COFF_FILHSZ]; short int aout_magic = COFF_SHORT (aout_hdr->magic); /* id */ /* * Validate the magic number in the a.out header. If it is valid then * update the starting symbol location. Do not accept these file formats * when loading a shared library. */ switch (aout_magic) { case COFF_OMAGIC: case COFF_ZMAGIC: case COFF_STMAGIC: if (!lib_ok) { status = -ENOEXEC; #ifdef COFF_DEBUG printk ("wrong a.out header magic\n"); #endif } start_addr = (unsigned int) COFF_LONG (aout_hdr->entry); break; /* * Magic value for a shared library. This is valid only when loading a * shared library. (There is no need for a start_addr. It won't be used.) */ case COFF_SHMAGIC: if (lib_ok) { #ifdef COFF_DEBUG printk ("wrong a.out header magic\n"); #endif status = -ENOEXEC; } break; default: #ifdef COFF_DEBUG printk ("wrong a.out header magic\n"); #endif status = -ENOEXEC; break; } } } } /* * Fetch a file pointer to the executable. */ if (status >= 0) { fd = open_inode (bprm->inode, O_RDONLY); if (fd < 0) { #ifdef COFF_DEBUG printk ("can not open inode, result = %d\n", fd); #endif status = fd; } else fp = current->files->fd[fd]; } else fd = -1; /* Invalidate the open file descriptor */ /* * Generate the proper values for the text fields * * THIS IS THE POINT OF NO RETURN. THE NEW PROCESS WILL TRAP OUT SHOULD * SOMETHING FAIL IN THE LOAD SEQUENCE FROM THIS POINT ONWARD. */ if (status >= 0) { long text_scnptr = COFF_LONG (text_sect->s_scnptr); long text_size = COFF_LONG (text_sect->s_size); long text_vaddr = COFF_LONG (text_sect->s_vaddr); long data_scnptr; long data_size; long data_vaddr; long bss_size; long bss_vaddr; /* * Generate the proper values for the data fields */ if (data_sect != NULL) { data_scnptr = COFF_LONG (data_sect->s_scnptr); data_size = COFF_LONG (data_sect->s_size); data_vaddr = COFF_LONG (data_sect->s_vaddr); } else { data_scnptr = 0; data_size = 0; data_vaddr = 0; } /* * Generate the proper values for the bss fields */ if (bss_sect != NULL) { bss_size = COFF_LONG (bss_sect->s_size); bss_vaddr = COFF_LONG (bss_sect->s_vaddr); } else { bss_size = 0; bss_vaddr = 0; } /* * Flush the executable from memory. At this point the executable is * committed to being defined or a segmentation violation will occur. */ if (lib_ok) { #ifdef COFF_DEBUG printk ("flushing executable\n"); #endif flush_old_exec (bprm); /* * Define the initial locations for the various items in the new process */ current->mm->mmap = NULL; current->mm->rss = 0; /* * Construct the parameter and environment string table entries. */ bprm->p += change_ldt (0, bprm->page); bprm->p -= MAX_ARG_PAGES*PAGE_SIZE; bprm->p = (unsigned long) create_tables ((char *) bprm->p, bprm->argc, bprm->envc, 1); /* * Do the end processing once the stack has been constructed */ current->mm->start_code = text_vaddr & PAGE_MASK; current->mm->end_code = text_vaddr + text_size; current->mm->end_data = data_vaddr + data_size; current->mm->start_brk = current->mm->brk = bss_vaddr + bss_size; current->suid = current->euid = bprm->e_uid; current->sgid = current->egid = bprm->e_gid; current->executable = bprm->inode; /* Store inode for file */ ++bprm->inode->i_count; /* Count the open inode */ regs->eip = start_addr; /* Current EIP register */ regs->esp = current->mm->start_stack = bprm->p; } /* * Map the text pages */ #ifdef COFF_DEBUG printk (".text: vaddr = %d, size = %d, scnptr = %d\n", text_vaddr, text_size, text_scnptr); #endif status = do_mmap (fp, text_vaddr & PAGE_MASK, text_size + (text_vaddr & ~PAGE_MASK), PROT_READ | PROT_EXEC, MAP_FIXED | MAP_SHARED, text_scnptr & PAGE_MASK); status = (status == (text_vaddr & PAGE_MASK)) ? 0 : -ENOEXEC; /* * Map the data pages */ if (status >= 0 && data_size != 0) { #ifdef COFF_DEBUG printk (".data: vaddr = %d, size = %d, scnptr = %d\n", data_vaddr, data_size, data_scnptr); #endif status = do_mmap (fp, data_vaddr & PAGE_MASK, data_size + (data_vaddr & ~PAGE_MASK), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, data_scnptr & PAGE_MASK); status = (status == (data_vaddr & PAGE_MASK)) ? 0 : -ENOEXEC; } /* * Construct the bss data for the process. The bss ranges from the * end of the data (which may not be on a page boundary) to the end * of the bss section. Allocate any necessary pages for the data. */ if (status >= 0 && bss_size != 0) { #ifdef COFF_DEBUG printk (".bss: vaddr = %d, size = %d\n", bss_vaddr, bss_size); #endif zeromap_page_range (PAGE_ALIGN (bss_vaddr), PAGE_ALIGN (bss_size), PAGE_COPY); status = clear_memory (bss_vaddr, bss_size); } /* * Load any shared library for the executable. */ if (status >= 0 && lib_ok && lib_count != 0) { int nIndex; COFF_SCNHDR *sect_ptr = sect_bufr; /* * Find the library sections. (There should be at least one. It was counted * earlier.) This will eventually recurse to our code and load the shared * library with our own procedures. */ for (nIndex = 0; nIndex < sections; ++nIndex) { long int sect_flags = COFF_LONG (sect_ptr->s_flags); if (sect_flags == COFF_STYP_LIB) { status = preload_library (bprm, sect_ptr, fp); if (status != 0) break; } sect_ptr = (COFF_SCNHDR *) &((char *) sect_ptr) [COFF_SCNHSZ]; } } /* * Generate any needed trap for this process. If an error occurred then * generate a segmentation violation. If the process is being debugged * then generate the load trap. (Note: If this is a library load then * do not generate the trap here. Pass the error to the caller who * will do it for the process in the outer lay of this procedure call.) */ if (lib_ok) { if (status < 0) send_sig (SIGSEGV, current, 0); /* Generate the error trap */ else { if (current->flags & PF_PTRACED) send_sig (SIGTRAP, current, 0); } status = 0; /* We are committed. It can't fail */ } } /* * Do any cleanup processing */ if (fd >= 0) sys_close (fd); /* Close unused code file */ if (sect_bufr != NULL) kfree (sect_bufr); /* Release section list buffer */ /* * Return the completion status. */ #ifdef COFF_DEBUG printk ("binfmt_coff: result = %d\n", status); #endif return (status); }
static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) { struct exec ex; struct file * file; int fd; unsigned long error; unsigned long p = bprm->p; unsigned long fd_offset; unsigned long rlim; ex = *((struct exec *) bprm->buf); /* exec-header */ if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) || N_DRSIZE(ex) || bprm->inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { return -ENOEXEC; } current->personality = PER_LINUX; fd_offset = N_TXTOFF(ex); #if defined (__i386__) || defined (CONFIG_ARM) if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) { printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n"); return -ENOEXEC; } if (N_MAGIC(ex) == ZMAGIC && ex.a_text && (fd_offset < bprm->inode->i_sb->s_blocksize)) { printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n"); return -ENOEXEC; } #endif #if defined(CONFIG_ARM) if (N_MACHTYPE(ex) != M_ARM) { printk(KERN_NOTICE "Binary != ARM. Please recompile binary.\n"); return -ENOEXEC; } #endif /* Check initial limits. This avoids letting people circumvent * size limits imposed on them by creating programs with large * arrays in the data or bss. */ rlim = current->rlim[RLIMIT_DATA].rlim_cur; if (rlim >= RLIM_INFINITY) rlim = ~0; if (ex.a_data + ex.a_bss > rlim) return -ENOMEM; if (flush_old_exec(bprm)) return -ENOMEM; /* OK, This is the point of no return */ current->mm->end_code = ex.a_text + (current->mm->start_code = N_TXTADDR(ex)); current->mm->end_data = ex.a_data + (current->mm->start_data = N_DATADDR(ex)); current->mm->brk = ex.a_bss + (current->mm->start_brk = N_BSSADDR(ex)); current->mm->rss = 0; current->mm->mmap = NULL; current->suid = current->euid = current->fsuid = bprm->e_uid; current->sgid = current->egid = current->fsgid = bprm->e_gid; current->flags &= ~PF_FORKNOEXEC; if (N_MAGIC(ex) == OMAGIC) { #if defined(__alpha__) || defined(CONFIG_ARM) #ifndef CONFIG_ARM do_mmap(NULL, N_TXTADDR(ex) & PAGE_MASK, ex.a_text+ex.a_data + PAGE_SIZE - 1, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); #else do_mmap(NULL, N_TXTADDR(ex), ex.a_text+ex.a_data, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); #endif read_exec(bprm->inode, fd_offset, (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0); #else do_mmap(NULL, 0, ex.a_text+ex.a_data, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data, 0); #endif } else { if (ex.a_text & 0xfff || ex.a_data & 0xfff) printk(KERN_NOTICE "executable not page aligned\n"); fd = open_inode(bprm->inode, O_RDONLY); if (fd < 0) { send_sig(SIGKILL, current, 0); return fd; } file = current->files->fd[fd]; if (!file->f_op || !file->f_op->mmap) { sys_close(fd); do_mmap(NULL, 0, ex.a_text+ex.a_data, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); read_exec(bprm->inode, fd_offset, (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0); goto beyond_if; } error = do_mmap(file, N_TXTADDR(ex), ex.a_text, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset); if (error != N_TXTADDR(ex)) { sys_close(fd); send_sig(SIGKILL, current, 0); return error; } error = do_mmap(file, N_DATADDR(ex), ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset + ex.a_text); sys_close(fd); if (error != N_DATADDR(ex)) { send_sig(SIGKILL, current, 0); return error; } } beyond_if: if (current->exec_domain && current->exec_domain->use_count) (*current->exec_domain->use_count)--; if (current->binfmt && current->binfmt->use_count) (*current->binfmt->use_count)--; current->exec_domain = lookup_exec_domain(current->personality); current->binfmt = &aout_format; if (current->exec_domain && current->exec_domain->use_count) (*current->exec_domain->use_count)++; if (current->binfmt && current->binfmt->use_count) (*current->binfmt->use_count)++; set_brk(current->mm->start_brk, current->mm->brk); p = setup_arg_pages(p, bprm); p = (unsigned long) create_aout_tables((char *)p, bprm); current->mm->start_stack = p; #ifdef __alpha__ regs->gp = ex.a_gpvalue; #endif start_thread(regs, ex.a_entry, p); if (current->flags & PF_PTRACED) send_sig(SIGTRAP, current, 0); #ifndef CONFIG_ARM return 0; #else return regs->ARM_r0; #endif }
static int load_svr3_binary (struct linux_binprm *bprm, struct pt_regs *regs) { struct file *file; int error, retval, i, j, shlibs; int fd[1+SHLIB_MAX]; long entry; unsigned long rlim; unsigned long p = bprm->p; struct filehdr *fh; struct aouthdr *ah; struct scnhdr *sh; char *buf, *libs_buf; /* Main binary + SHLIB_MAX */ struct bin_info bin_info[SHLIB_MAX + 1]; /* Cheking accessable headers by bprm->buf (128 bytes). */ fh = (struct filehdr *) bprm->buf; if (fh->f_magic != MC68MAGIC || fh->f_opthdr < AOUTSZ || fh->f_nscns < 3 || !(fh->f_flags & F_AR32W) || !(fh->f_flags & F_EXEC) ) return -ENOEXEC; ah = (struct aouthdr *) ((char *) bprm->buf + FILHSZ); if (ah->magic == SHMAGIC) return -ELIBEXEC; if ((ah->magic != DMAGIC && ah->magic != ZMAGIC) || !ah->tsize || ah->tsize + ah->dsize + FILHSZ + fh->f_opthdr + SCNHSZ * fh->f_nscns > bprm->inode->i_size || ah->text_start + ah->tsize > ah->data_start ) return -ENOEXEC; if (fh->f_nscns > 24) { printk ("Too many sections in svr3 binary file\n"); return -ENOEXEC; } /* Touch main binary file (which has # 0). */ fd[0] = open_inode (bprm->inode, O_RDONLY); if (fd[0] < 0) return fd[0]; buf = (char *) kmalloc (2*1024, GFP_KERNEL); if (!buf) { sys_close (fd[0]); return -ENOMEM; } libs_buf = buf + 1024; retval = touch_svr3_binary (fd[0], buf, &bin_info[0], 0); if (retval < 0) { sys_close(fd[0]); kfree (buf); return retval; } /* Looking for STYP_LIB section for shared libraries. */ sh = (struct scnhdr *) (buf + FILHSZ + fh->f_opthdr); for (i = 0; i < fh->f_nscns; i++) if (sh[i].s_flags == STYP_LIB) break; if (i == fh->f_nscns) shlibs = 0; else shlibs = sh[i].s_nlib; /* Touch target shared library binary files (## 1--SHLIB_MAX). */ if (shlibs) { void *p; int slib_size = sh[i].s_size; if (shlibs > SHLIB_MAX) { retval = -ELIBMAX; goto error_close; } file = bin_info[0].file; retval = sys_lseek (fd[0], sh[i].s_scnptr, 0); if (retval < 0) goto error_close; if (retval != sh[i].s_scnptr) { retval = -EACCES; goto error_close; } set_fs (KERNEL_DS); retval = file->f_op->read (file->f_inode, file, libs_buf, 1024); set_fs (USER_DS); if (retval < 0) goto error_close; if (retval < slib_size) { retval = -ELIBSCN; goto error_close; } for (p = libs_buf, j = 1; j <= shlibs; j++) { int len; char *name; struct slib *slibh = (struct slib *) p; p += slibh->sl_pathndx * 4; len = (slibh->sl_entsz - slibh->sl_pathndx) * 4; if (len <= 0 || p + len > (void *) libs_buf + slib_size) { retval = -ELIBSCN; goto error_close; } /* Target shared library path name. Must be followed by one or more zeroes. */ name = (char *) p; /* Try to access this library. */ set_fs (KERNEL_DS); fd[j] = sys_open (name, 0, 0); set_fs (USER_DS); if (fd[j] < 0) { retval = fd[j]; goto error_close; } retval = touch_svr3_binary (fd[j],buf,&bin_info[j],SHMAGIC); if (retval < 0) { /* Renumbering for shared library context. */ if (retval == -ENOEXEC) retval = -ELIBBAD; else if (retval == -EACCES) retval = -ELIBACC; goto error_close; } p += len; } } /* if (shlibs) .... */ /* Check initial limits. This avoids letting people circumvent * size limits imposed on them by creating programs with large * arrays in the data or bss. */ rlim = current->rlim[RLIMIT_DATA].rlim_cur; if (rlim >= RLIM_INFINITY) rlim = ~0; if (ah->dsize + ah->bsize > rlim) { /* XXX: but in shlibs too */ retval = -ENOMEM; goto error_close; } kfree (buf); /* OK, this is the point of noreturn. */ entry = ah->entry & ~0x1; /* Avoids possibly hult after `rte' ??? */ flush_old_exec (bprm); current->personality = PER_SVR3; current->mm->end_code = bin_info[0].text_len + (current->mm->start_code = bin_info[0].text_addr); current->mm->end_data = bin_info[0].data_len + (current->mm->start_data = bin_info[0].data_addr); current->mm->brk = bin_info[0].bss_len + (current->mm->start_brk = current->mm->end_data); current->mm->rss = 0; current->mm->mmap = NULL; current->suid = current->euid = current->fsuid = bprm->e_uid; current->sgid = current->egid = current->fsgid = bprm->e_gid; current->flags &= ~PF_FORKNOEXEC; /* mmap all binaries */ for (i = 0; i < 1 + shlibs; i++) { struct bin_info *binf = &bin_info[i]; unsigned int blocksize = binf->file->f_inode->i_sb->s_blocksize; unsigned int start_bss, end_bss; if (binf->text_addr & (PAGE_SIZE - 1) || binf->data_addr & (PAGE_SIZE - 1) || binf->text_offs & (blocksize - 1) || binf->data_offs & (blocksize - 1) || !binf->file->f_op->mmap ) { /* cannot mmap immediatly */ do_mmap (NULL, PAGE_ROUND(binf->text_addr), binf->text_len + (binf->text_addr - PAGE_ROUND(binf->text_addr)), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); read_exec (binf->file->f_inode, binf->text_offs, (char *) binf->text_addr, binf->text_len, 0); do_mmap (NULL, PAGE_ROUND(binf->data_addr), binf->data_len + (binf->data_addr - PAGE_ROUND(binf->data_addr)), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); read_exec (binf->file->f_inode, binf->data_offs, (char *) binf->data_addr, binf->data_len, 0); /* there's no nice way of flushing a number of user pages to ram 8*( */ flush_cache_all(); } else { error = do_mmap (binf->file, binf->text_addr, binf->text_len, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, binf->text_offs); if (error != binf->text_addr) goto error_kill_close; error = do_mmap (binf->file, binf->data_addr, binf->data_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, binf->data_offs); if (error != binf->data_addr) goto error_kill_close; #ifdef DMAGIC_NODEMAND /* DMAGIC is for pure executable (not demand loading). But let the shared libraries be demand load ??? */ if (i == 0 && ah->magic == DMAGIC) { volatile char c; unsigned long addr; /* Touch all pages in .text and .data segments. */ for (addr = binf->text_addr; addr < binf->text_addr + binf->text_len; addr += PAGE_SIZE ) c = get_fs_byte ((char *) addr); for (addr = binf->data_addr; addr < binf->data_addr + binf->data_len; addr += PAGE_SIZE ) c = get_fs_byte ((char *) addr); } #endif } sys_close (fd[i]); start_bss = PAGE_ALIGN(binf->data_addr + binf->data_len); end_bss = PAGE_ALIGN(binf->data_addr + binf->data_len + binf->bss_len); /* svr3 binaries very hope that .bss section had been initialized by zeroes. Oh... */ if (binf->bss_len != 0) { /* Because there may be skipped heap by alignment. */ int addr = binf->data_addr + binf->data_len; int i = start_bss - addr; /* start_bss is aligned, addr may be no */ while (i & 0x3) { put_fs_byte (0, (char *) addr); addr++; i--; } i >>= 2; while (i--) { put_fs_long (0, (long *) addr); addr += sizeof (long); } } if (end_bss >= start_bss) do_mmap (NULL, start_bss, end_bss - start_bss, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); #ifdef DMAGIC_NODEMAND /* The same reason as above. */ if (i == 0 && ah->magic == DMAGIC) { volatile char c; unsigned long addr; for (addr = start_bss; addr < end_bss; addr += PAGE_SIZE) c = get_fs_byte ((char *) addr); } #endif /* OK, now all is mmapped for binary # i */ } /* for (i = ... ) */