コード例 #1
0
ファイル: vm_segment.c プロジェクト: akat1/impala
/**
 * Rezerwuje ciągły obszar w danym segmencie.
 * @param vseg deskryptor segmentu.
 * @param size rozmiar ciągłego obszaru.
 * @param _res adres zmiennej, do uzupełnienia przydzielonym adresem.
 */
int
vm_seg_reserve(vm_seg_t *vseg, vm_size_t size, void *_res)
{
    int expand = EXPAND_UP;
    vm_addr_t *res = _res;
    size = PAGE_ROUND(size);
    vm_region_t *region = list_head(&vseg->regions);
    if (region == NULL) {
        if (do_first_region(vseg, &region)) return -1;
    }

    // sprawdzamy czy istnieje dziura pomiędzy początkiem segmentu
    // a pierwszym regionem
    if (size < region->begin - vseg->base) {
        *res = region->begin - size;
        return expand_region(vseg, region, size, EXPAND_DOWN, _res);
    }

    // Ok, no to szukamy dziury za regionem
    region = list_find(&vseg->regions, has_hole_after_reg, size);
    if (region == NULL) {
        if (vseg->flags & VM_SEG_EXPDOWN) {
            expand = EXPAND_DOWN;
            region = list_head(&vseg->regions);
            *res = region->begin - size;
        } else {
            region = list_tail(&vseg->regions);
            *res = region->end;
        }
    } else {
        *res = region->end;
    }
    return expand_region(vseg, region, size, expand, _res);
}
コード例 #2
0
ファイル: vm_space.c プロジェクト: akat1/impala
int
set_stack(vm_space_t *vs, vm_seg_t *STACK, vm_seg_t *DATA,
    vm_addr_t *res, vm_size_t s)
{
    KASSERT(s > 0);
    s = PAGE_ROUND(s);

    vm_size_t stackspace = STACK->end - (DATA->base + DATA->limit) + PAGE_SIZE;
    if (stackspace < s) {
        if ((DATA->limit - DATA->size) < s) return -1;
        DATA->limit -= (s-stackspace);
    }
    STACK->limit += s;
    return vm_seg_alloc(STACK, s, res);
}
コード例 #3
0
ファイル: svr3.c プロジェクト: shattered/linux-m68k
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 = ... )   */