Exemple #1
0
static unsigned long get_mmap_base(elf_bin_t *elf)
{
	unsigned long addr, pg_start, pg_end, mmap_min = ULONG_MAX, mmap_max = 0;
	int i;

	for (i=0; i<elf->hdr.e_phnum; i++) 
		if ( elf->phdr[i].p_type == PT_LOAD)
		{
			pg_start = PAGE_BASE(elf->phdr[i].p_vaddr);
			pg_end   = PAGE_NEXT(elf->phdr[i].p_vaddr + elf->phdr[i].p_memsz);

			if (pg_start < mmap_min)
				mmap_min = pg_start;

			if (pg_end > mmap_max)
				mmap_max = pg_end;
		}

	if (mmap_min > mmap_max)
		mmap_min = mmap_max;

	addr = do_mmap2(mmap_min, mmap_max-mmap_min, PROT_NONE,
	                MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

	if (addr & PG_MASK) /* not on page boundary -> error code */
		return addr;

	sys_munmap(addr, mmap_max-mmap_min);

	return addr-mmap_min;
}
static int
qcntl_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg, int minor)
{
	struct shmiqreq req;
	struct vm_area_struct *vma;
	int v;

	switch (cmd) {
		/*
		 * The address space is already mapped as a /dev/zero
		 * mapping.  FIXME: check that /dev/zero is what the user
		 * had mapped before :-)
		 */
		case QIOCATTACH: {
			unsigned long vaddr;
			int s;

			v = verify_area (VERIFY_READ, (void *) arg,
			                 sizeof (struct shmiqreq));
			if (v)
				return v;
			if (copy_from_user(&req, (void *) arg, sizeof (req)))
				return -EFAULT;
			/*
			 * Do not allow to attach to another region if it has
			 * already been attached
			 */
			if (shmiqs [minor].mapped) {
				printk("SHMIQ:The thingie is already mapped\n");
				return -EINVAL;
			}

			vaddr = (unsigned long) req.user_vaddr;
			vma = find_vma (current->mm, vaddr);
			if (!vma) {
				printk ("SHMIQ: could not find %lx the vma\n",
				        vaddr);
				return -EINVAL;
			}
			s = req.arg * sizeof (struct shmqevent) +
			    sizeof (struct sharedMemoryInputQueue);
			v = sys_munmap (vaddr, s);
			down_write(&current->mm->mmap_sem);
			do_munmap(current->mm, vaddr, s);
			do_mmap(filp, vaddr, s, PROT_READ | PROT_WRITE,
			        MAP_PRIVATE|MAP_FIXED, 0);
			up_write(&current->mm->mmap_sem);
			shmiqs[minor].events = req.arg;
			shmiqs[minor].mapped = 1;

			return 0;
		}
	}

	return -EINVAL;
}
Exemple #3
0
static void rst_tcp_socks_all(struct rst_tcp_sock *arr, int size)
{
	int i;

	if (size == 0)
		return;

	for (i =0; arr[i].sk >= 0; i++)
		rst_tcp_repair_off(arr + i);

	sys_munmap(arr, size);
}
int process2()
{
	int* momo2 = (int*)sys_mmap(sizeof(int) * 10);
	int a2 = vmem_translate((uint32_t)momo2, current_process);
	sys_yield();
	
	sys_munmap(momo2, sizeof(int) * 10);
	a2 = vmem_translate((uint32_t)momo2, current_process);
	
	momo2++;
	return a2;
}
Exemple #5
0
static int fini(void)
{
	int ret;

	ret = fini_thread();

	sys_munmap(tid_state, TID_STATE_SIZE(nr_tid_state));
	log_set_fd(-1);
	sys_close(tsock);

	return ret;
}
Exemple #6
0
/*
 * This function unmaps all VMAs, which don't belong to
 * the restored process or the restorer.
 *
 * The restorer memory is two regions -- area with restorer, its stack
 * and arguments and the one with private vmas of the tasks we restore
 * (a.k.a. premmaped area):
 *
 * 0                       TASK_SIZE
 * +----+====+----+====+---+
 *
 * Thus to unmap old memory we have to do 3 unmaps:
 * [ 0 -- 1st area start ]
 * [ 1st end -- 2nd start ]
 * [ 2nd start -- TASK_SIZE ]
 */
static int unmap_old_vmas(void *premmapped_addr, unsigned long premmapped_len,
		      void *bootstrap_start, unsigned long bootstrap_len)
{
	unsigned long s1, s2;
	void *p1, *p2;
	int ret;

	if ((void *) premmapped_addr < bootstrap_start) {
		p1 = premmapped_addr;
		s1 = premmapped_len;
		p2 = bootstrap_start;
		s2 = bootstrap_len;
	} else {
		p2 = premmapped_addr;
		s2 = premmapped_len;
		p1 = bootstrap_start;
		s1 = bootstrap_len;
	}

	ret = sys_munmap(NULL, p1 - NULL);
	if (ret) {
		pr_err("Unable to unmap (%p-%p): %d\n", NULL, p1, ret);
		return -1;
	}

	ret = sys_munmap(p1 + s1, p2 - (p1 + s1));
	if (ret) {
		pr_err("Unable to unmap (%p-%p): %d\n", p1 + s1, p2, ret);
		return -1;
	}

	ret = sys_munmap(p2 + s2, (void *) TASK_SIZE - (p2 + s2));
	if (ret) {
		pr_err("Unable to unmap (%p-%p): %d\n",
				p2 + s2, (void *)TASK_SIZE, ret);
		return -1;
	}

	return 0;
}
int process1()
{
	int* momo1 = (int*)sys_mmap(sizeof(int) * 10);
	int a1 = vmem_translate((uint32_t)momo1, current_process);
	sys_yield();
	
	sys_munmap(momo1, sizeof(int) * 10);
	a1 = vmem_translate((uint32_t)momo1, current_process);
	
	momo1[40000] = 50; // error : data_handler
	momo1++;
	
	return a1;
}
void qbytes_free_munmap(qbytes_t* b) {
  err_t err;

  /* I don't believe this is required, but 
   * I've heard here and there it might be for NFS...
   *
  rc = msync(b->data, b->len, MS_ASYNC);
  if( rc ) fprintf(stderr, "Warning - in qbytes_free_munmap, msync failed with %i, errno %i\n", rc, errno);
  */

  err = sys_munmap(b->data, b->len);
  assert( !err );

  _qbytes_free_qbytes(b);
}
Exemple #9
0
/*
 * Like cr_sendfile_buffered(), but for HUGETLBFS destination file.
 * Uses temporary mmap()s of a chunk of len HPAGE_SIZE at a time.
 *
 * Note: Caller is responsible for checking count==0 or {dst,src}_ppos==NULL.
 */
static loff_t
cr_sendfile_hugedst(cr_errbuf_t *eb, struct file *dst_filp, struct file *src_filp, loff_t *src_ppos, loff_t count)
{
    loff_t bytes_left = count;
    loff_t retval;
    struct mm_struct *mm = current->mm;
    unsigned long map_addr = 0;
    unsigned long map_pgoff = 0;
    unsigned long map_flags = MAP_SHARED;

    CRI_ASSERT((count & (HPAGE_SIZE-1)) == 0);
    CRI_ASSERT(dst_filp->f_pos == 0);
    CRI_ASSERT(src_ppos = &src_filp->f_pos);

    for (bytes_left = count; bytes_left; bytes_left -= HPAGE_SIZE) {
	unsigned long tmp;
	down_write(&mm->mmap_sem);
	tmp = do_mmap_pgoff(dst_filp, map_addr, HPAGE_SIZE, PROT_READ|PROT_WRITE, map_flags, map_pgoff);
	up_write(&mm->mmap_sem);
	if (IS_ERR((void*)tmp)) {
	    CR_ERR_EB(eb, "do_mmap(HUGE dst file) returned %ld", (long)tmp);
	    retval = tmp;
	    goto out_err;
	}
	map_addr = tmp;
	map_pgoff += (HPAGE_SIZE >> PAGE_SHIFT);
	map_flags |= MAP_FIXED;
	retval = cr_uread(eb, src_filp, (void *)map_addr, HPAGE_SIZE);
        if (retval < 0) goto out_unmap;
    }
    retval = count;
    dst_filp->f_pos = count;
out_unmap:
    if (map_addr) {
	(void)sys_munmap(map_addr, HPAGE_SIZE); // XXX: check for error (unless on error path already)?
    }
out_err:
    return retval;
}
Exemple #10
0
uint32_t elf_load_fd(struct sys_state *sys, int fd, int flags, struct elf_load_info *info)
{
	uint32_t entry;
	stat_s stat;
	void *base;
	int err;

	err = sys_fstat(fd, &stat);
	if (err) {
		debug("Failed to stat ELF (%d)\n", err);
		sys_exit(1);
	}

	base = sys_mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
	if (IS_ERROR(base)) {
		debug("Failed to mmap ELF file\n");
		sys_exit(1);
	}

	entry = elf_load(sys, base, flags, info);
	sys_munmap(base, stat.st_size);
	return entry;
}
Exemple #11
0
/*
 * The main routine to restore task via sigreturn.
 * This one is very special, we never return there
 * but use sigreturn facility to restore core registers
 * and jump execution to some predefined ip read from
 * core file.
 */
long __export_restore_task(struct task_restore_args *args)
{
	long ret = -1;
	int i;
	VmaEntry *vma_entry;
	unsigned long va;

	struct rt_sigframe *rt_sigframe;
	unsigned long new_sp;
	k_rtsigset_t to_block;
	pid_t my_pid = sys_getpid();
	rt_sigaction_t act;

	bootstrap_start = args->bootstrap_start;
	bootstrap_len	= args->bootstrap_len;

#ifdef CONFIG_VDSO
	vdso_rt_size	= args->vdso_rt_size;
#endif

	task_entries = args->task_entries;
	helpers = args->helpers;
	n_helpers = args->n_helpers;
	*args->breakpoint = rst_sigreturn;

	ksigfillset(&act.rt_sa_mask);
	act.rt_sa_handler = sigchld_handler;
	act.rt_sa_flags = SA_SIGINFO | SA_RESTORER | SA_RESTART;
	act.rt_sa_restorer = cr_restore_rt;
	sys_sigaction(SIGCHLD, &act, NULL, sizeof(k_rtsigset_t));

	log_set_fd(args->logfd);
	log_set_loglevel(args->loglevel);

	cap_last_cap = args->cap_last_cap;

	pr_info("Switched to the restorer %d\n", my_pid);

#ifdef CONFIG_VDSO
	if (vdso_do_park(&args->vdso_sym_rt, args->vdso_rt_parked_at, vdso_rt_size))
		goto core_restore_end;
#endif

	if (unmap_old_vmas((void *)args->premmapped_addr, args->premmapped_len,
				bootstrap_start, bootstrap_len))
		goto core_restore_end;

	/* Shift private vma-s to the left */
	for (i = 0; i < args->nr_vmas; i++) {
		vma_entry = args->tgt_vmas + i;

		if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
			continue;

		if (!vma_priv(vma_entry))
			continue;

		if (vma_entry->end >= TASK_SIZE)
			continue;

		if (vma_entry->start > vma_entry->shmid)
			break;

		if (vma_remap(vma_premmaped_start(vma_entry),
				vma_entry->start, vma_entry_len(vma_entry)))
			goto core_restore_end;
	}

	/* Shift private vma-s to the right */
	for (i = args->nr_vmas - 1; i >= 0; i--) {
		vma_entry = args->tgt_vmas + i;

		if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
			continue;

		if (!vma_priv(vma_entry))
			continue;

		if (vma_entry->start > TASK_SIZE)
			continue;

		if (vma_entry->start < vma_entry->shmid)
			break;

		if (vma_remap(vma_premmaped_start(vma_entry),
				vma_entry->start, vma_entry_len(vma_entry)))
			goto core_restore_end;
	}

	/*
	 * OK, lets try to map new one.
	 */
	for (i = 0; i < args->nr_vmas; i++) {
		vma_entry = args->tgt_vmas + i;

		if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
			continue;

		if (vma_priv(vma_entry))
			continue;

		va = restore_mapping(vma_entry);

		if (va != vma_entry->start) {
			pr_err("Can't restore %"PRIx64" mapping with %lx\n", vma_entry->start, va);
			goto core_restore_end;
		}
	}

#ifdef CONFIG_VDSO
	/*
	 * Proxify vDSO.
	 */
	for (i = 0; i < args->nr_vmas; i++) {
		if (vma_entry_is(&args->tgt_vmas[i], VMA_AREA_VDSO) ||
		    vma_entry_is(&args->tgt_vmas[i], VMA_AREA_VVAR)) {
			if (vdso_proxify("dumpee", &args->vdso_sym_rt,
					 args->vdso_rt_parked_at,
					 i, args->tgt_vmas, args->nr_vmas))
				goto core_restore_end;
			break;
		}
	}
#endif

	/*
	 * Walk though all VMAs again to drop PROT_WRITE
	 * if it was not there.
	 */
	for (i = 0; i < args->nr_vmas; i++) {
		vma_entry = args->tgt_vmas + i;

		if (!(vma_entry_is(vma_entry, VMA_AREA_REGULAR)))
			continue;

		if (vma_entry_is(vma_entry, VMA_ANON_SHARED)) {
			struct shmem_info *entry;

			entry = find_shmem(args->shmems, args->nr_shmems,
						  vma_entry->shmid);
			if (entry && entry->pid == my_pid &&
			    entry->start == vma_entry->start)
				futex_set_and_wake(&entry->lock, 1);
		}

		if (vma_entry->prot & PROT_WRITE)
			continue;

		sys_mprotect(decode_pointer(vma_entry->start),
			     vma_entry_len(vma_entry),
			     vma_entry->prot);
	}

	/*
	 * Finally restore madivse() bits
	 */
	for (i = 0; i < args->nr_vmas; i++) {
		unsigned long m;

		vma_entry = args->tgt_vmas + i;
		if (!vma_entry->has_madv || !vma_entry->madv)
			continue;

		for (m = 0; m < sizeof(vma_entry->madv) * 8; m++) {
			if (vma_entry->madv & (1ul << m)) {
				ret = sys_madvise(vma_entry->start,
						  vma_entry_len(vma_entry),
						  m);
				if (ret) {
					pr_err("madvise(%"PRIx64", %"PRIu64", %ld) "
					       "failed with %ld\n",
						vma_entry->start,
						vma_entry_len(vma_entry),
						m, ret);
					goto core_restore_end;
				}
			}
		}
	}

	ret = 0;

	/*
	 * Tune up the task fields.
	 */
	ret |= sys_prctl_safe(PR_SET_NAME, (long)args->comm, 0, 0);

	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE,	(long)args->mm.mm_start_code, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE,	(long)args->mm.mm_end_code, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA,	(long)args->mm.mm_start_data, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA,	(long)args->mm.mm_end_data, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_STACK,	(long)args->mm.mm_start_stack, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_BRK,	(long)args->mm.mm_start_brk, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_BRK,		(long)args->mm.mm_brk, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_START,	(long)args->mm.mm_arg_start, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END,	(long)args->mm.mm_arg_end, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_START,	(long)args->mm.mm_env_start, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_END,	(long)args->mm.mm_env_end, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_AUXV,	(long)args->mm_saved_auxv, args->mm_saved_auxv_size);
	if (ret)
		goto core_restore_end;

	/*
	 * Because of requirements applied from kernel side
	 * we need to restore /proc/pid/exe symlink late,
	 * after old existing VMAs are superseded with
	 * new ones from image file.
	 */
	ret = restore_self_exe_late(args);
	if (ret)
		goto core_restore_end;

	/*
	 * We need to prepare a valid sigframe here, so
	 * after sigreturn the kernel will pick up the
	 * registers from the frame, set them up and
	 * finally pass execution to the new IP.
	 */
	rt_sigframe = (void *)args->t->mem_zone.rt_sigframe;

	if (restore_thread_common(rt_sigframe, args->t))
		goto core_restore_end;

	/*
	 * Threads restoration. This requires some more comments. This
	 * restorer routine and thread restorer routine has the following
	 * memory map, prepared by a caller code.
	 *
	 * | <-- low addresses                                          high addresses --> |
	 * +-------------------------------------------------------+-----------------------+
	 * | this proc body | own stack | rt_sigframe space | thread restore zone   |
	 * +-------------------------------------------------------+-----------------------+
	 *
	 * where each thread restore zone is the following
	 *
	 * | <-- low addresses                                     high addresses --> |
	 * +--------------------------------------------------------------------------+
	 * | thread restore proc | thread1 stack | thread1 rt_sigframe |
	 * +--------------------------------------------------------------------------+
	 */

	if (args->nr_threads > 1) {
		struct thread_restore_args *thread_args = args->thread_args;
		long clone_flags = CLONE_VM | CLONE_FILES | CLONE_SIGHAND	|
				   CLONE_THREAD | CLONE_SYSVSEM;
		long last_pid_len;
		long parent_tid;
		int i, fd;

		fd = args->fd_last_pid;
		ret = sys_flock(fd, LOCK_EX);
		if (ret) {
			pr_err("Can't lock last_pid %d\n", fd);
			goto core_restore_end;
		}

		for (i = 0; i < args->nr_threads; i++) {
			char last_pid_buf[16], *s;

			/* skip self */
			if (thread_args[i].pid == args->t->pid)
				continue;

			new_sp = restorer_stack(thread_args + i);
			last_pid_len = vprint_num(last_pid_buf, sizeof(last_pid_buf), thread_args[i].pid - 1, &s);
			sys_lseek(fd, 0, SEEK_SET);
			ret = sys_write(fd, s, last_pid_len);
			if (ret < 0) {
				pr_err("Can't set last_pid %ld/%s\n", ret, last_pid_buf);
				goto core_restore_end;
			}

			/*
			 * To achieve functionality like libc's clone()
			 * we need a pure assembly here, because clone()'ed
			 * thread will run with own stack and we must not
			 * have any additional instructions... oh, dear...
			 */

			RUN_CLONE_RESTORE_FN(ret, clone_flags, new_sp, parent_tid, thread_args, args->clone_restore_fn);
		}

		ret = sys_flock(fd, LOCK_UN);
		if (ret) {
			pr_err("Can't unlock last_pid %ld\n", ret);
			goto core_restore_end;
		}

	}

	sys_close(args->fd_last_pid);

	restore_rlims(args);

	ret = create_posix_timers(args);
	if (ret < 0) {
		pr_err("Can't restore posix timers %ld\n", ret);
		goto core_restore_end;
	}

	ret = timerfd_arm(args);
	if (ret < 0) {
		pr_err("Can't restore timerfd %ld\n", ret);
		goto core_restore_end;
	}

	pr_info("%ld: Restored\n", sys_getpid());

	futex_set(&zombies_inprogress, args->nr_zombies);

	restore_finish_stage(CR_STATE_RESTORE);

	futex_wait_while_gt(&zombies_inprogress, 0);

	if (wait_helpers(args) < 0)
		goto core_restore_end;

	ksigfillset(&to_block);
	ret = sys_sigprocmask(SIG_SETMASK, &to_block, NULL, sizeof(k_rtsigset_t));
	if (ret) {
		pr_err("Unable to block signals %ld", ret);
		goto core_restore_end;
	}

	sys_sigaction(SIGCHLD, &args->sigchld_act, NULL, sizeof(k_rtsigset_t));

	ret = restore_signals(args->siginfo, args->siginfo_nr, true);
	if (ret)
		goto core_restore_end;

	ret = restore_signals(args->t->siginfo, args->t->siginfo_nr, false);
	if (ret)
		goto core_restore_end;

	restore_finish_stage(CR_STATE_RESTORE_SIGCHLD);

	rst_tcp_socks_all(args);

	/*
	 * Writing to last-pid is CAP_SYS_ADMIN protected,
	 * turning off TCP repair is CAP_SYS_NED_ADMIN protected,
	 * thus restore* creds _after_ all of the above.
	 */

	ret = restore_creds(&args->creds);
	ret = ret || restore_dumpable_flag(&args->mm);
	ret = ret || restore_pdeath_sig(args->t);

	futex_set_and_wake(&thread_inprogress, args->nr_threads);

	restore_finish_stage(CR_STATE_RESTORE_CREDS);

	if (ret)
		BUG();

	/* Wait until children stop to use args->task_entries */
	futex_wait_while_gt(&thread_inprogress, 1);

	log_set_fd(-1);

	/*
	 * The code that prepared the itimers makes shure the
	 * code below doesn't fail due to bad timing values.
	 */

#define itimer_armed(args, i)				\
		(args->itimers[i].it_interval.tv_sec ||	\
		 args->itimers[i].it_interval.tv_usec)

	if (itimer_armed(args, 0))
		sys_setitimer(ITIMER_REAL, &args->itimers[0], NULL);
	if (itimer_armed(args, 1))
		sys_setitimer(ITIMER_VIRTUAL, &args->itimers[1], NULL);
	if (itimer_armed(args, 2))
		sys_setitimer(ITIMER_PROF, &args->itimers[2], NULL);

	restore_posix_timers(args);

	sys_munmap(args->rst_mem, args->rst_mem_size);

	/*
	 * Sigframe stack.
	 */
	new_sp = (long)rt_sigframe + SIGFRAME_OFFSET;

	/*
	 * Prepare the stack and call for sigreturn,
	 * pure assembly since we don't need any additional
	 * code insns from gcc.
	 */
	rst_sigreturn(new_sp);

core_restore_end:
	futex_abort_and_wake(&task_entries->nr_in_progress);
	pr_err("Restorer fail %ld\n", sys_getpid());
	sys_exit_group(1);
	return -1;
}
Exemple #12
0
static void
syscall_handler (struct intr_frame *f)
{
  int syscall_number;
  ASSERT( sizeof(syscall_number) == 4 ); // assuming x86

  // The system call number is in the 32-bit word at the caller's stack pointer.
  memread_user(f->esp, &syscall_number, sizeof(syscall_number));
  _DEBUG_PRINTF ("[DEBUG] system call, number = %d!\n", syscall_number);

  // Store the esp, which is needed in the page fault handler.
  // refer to exception.c:page_fault() (see manual 4.3.3)
  thread_current()->current_esp = f->esp;

  // Dispatch w.r.t system call number
  // SYS_*** constants are defined in syscall-nr.h
  switch (syscall_number) {
  case SYS_HALT: // 0
    {
      sys_halt();
      NOT_REACHED();
      break;
    }

  case SYS_EXIT: // 1
    {
      int exitcode;
      memread_user(f->esp + 4, &exitcode, sizeof(exitcode));

      sys_exit(exitcode);
      NOT_REACHED();
      break;
    }

  case SYS_EXEC: // 2
    {
      void* cmdline;
      memread_user(f->esp + 4, &cmdline, sizeof(cmdline));

      int return_code = sys_exec((const char*) cmdline);
      f->eax = (uint32_t) return_code;
      break;
    }

  case SYS_WAIT: // 3
    {
      pid_t pid;
      memread_user(f->esp + 4, &pid, sizeof(pid_t));

      int ret = sys_wait(pid);
      f->eax = (uint32_t) ret;
      break;
    }

  case SYS_CREATE: // 4
    {
      const char* filename;
      unsigned initial_size;
      bool return_code;

      memread_user(f->esp + 4, &filename, sizeof(filename));
      memread_user(f->esp + 8, &initial_size, sizeof(initial_size));

      return_code = sys_create(filename, initial_size);
      f->eax = return_code;
      break;
    }

  case SYS_REMOVE: // 5
    {
      const char* filename;
      bool return_code;

      memread_user(f->esp + 4, &filename, sizeof(filename));

      return_code = sys_remove(filename);
      f->eax = return_code;
      break;
    }

  case SYS_OPEN: // 6
    {
      const char* filename;
      int return_code;

      memread_user(f->esp + 4, &filename, sizeof(filename));

      return_code = sys_open(filename);
      f->eax = return_code;
      break;
    }

  case SYS_FILESIZE: // 7
    {
      int fd, return_code;
      memread_user(f->esp + 4, &fd, sizeof(fd));

      return_code = sys_filesize(fd);
      f->eax = return_code;
      break;
    }

  case SYS_READ: // 8
    {
      int fd, return_code;
      void *buffer;
      unsigned size;

      memread_user(f->esp + 4, &fd, sizeof(fd));
      memread_user(f->esp + 8, &buffer, sizeof(buffer));
      memread_user(f->esp + 12, &size, sizeof(size));

      return_code = sys_read(fd, buffer, size);
      f->eax = (uint32_t) return_code;
      break;
    }

  case SYS_WRITE: // 9
    {
      int fd, return_code;
      const void *buffer;
      unsigned size;

      memread_user(f->esp + 4, &fd, sizeof(fd));
      memread_user(f->esp + 8, &buffer, sizeof(buffer));
      memread_user(f->esp + 12, &size, sizeof(size));

      return_code = sys_write(fd, buffer, size);
      f->eax = (uint32_t) return_code;
      break;
    }

  case SYS_SEEK: // 10
    {
      int fd;
      unsigned position;

      memread_user(f->esp + 4, &fd, sizeof(fd));
      memread_user(f->esp + 8, &position, sizeof(position));

      sys_seek(fd, position);
      break;
    }

  case SYS_TELL: // 11
    {
      int fd;
      unsigned return_code;

      memread_user(f->esp + 4, &fd, sizeof(fd));

      return_code = sys_tell(fd);
      f->eax = (uint32_t) return_code;
      break;
    }

  case SYS_CLOSE: // 12
    {
      int fd;
      memread_user(f->esp + 4, &fd, sizeof(fd));

      sys_close(fd);
      break;
    }

#ifdef VM
  case SYS_MMAP: // 13
    {
      int fd;
      void *addr;
      memread_user(f->esp + 4, &fd, sizeof(fd));
      memread_user(f->esp + 8, &addr, sizeof(addr));

      mmapid_t ret = sys_mmap (fd, addr);
      f->eax = ret;
      break;
    }

  case SYS_MUNMAP: // 14
    {
      mmapid_t mid;
      memread_user(f->esp + 4, &mid, sizeof(mid));

      sys_munmap(mid);
      break;
    }
#endif
#ifdef FILESYS
  case SYS_CHDIR: // 15
    {
      const char* filename;
      int return_code;

      memread_user(f->esp + 4, &filename, sizeof(filename));

      return_code = sys_chdir(filename);
      f->eax = return_code;
      break;
    }

  case SYS_MKDIR: // 16
    {
      const char* filename;
      int return_code;

      memread_user(f->esp + 4, &filename, sizeof(filename));

      return_code = sys_mkdir(filename);
      f->eax = return_code;
      break;
    }

  case SYS_READDIR: // 17
    {
      int fd;
      char *name;
      int return_code;

      memread_user(f->esp + 4, &fd, sizeof(fd));
      memread_user(f->esp + 8, &name, sizeof(name));

      return_code = sys_readdir(fd, name);
      f->eax = return_code;
      break;
    }

  case SYS_ISDIR: // 18
    {
      int fd;
      int return_code;

      memread_user(f->esp + 4, &fd, sizeof(fd));
      return_code = sys_isdir(fd);
      f->eax = return_code;
      break;
    }

  case SYS_INUMBER: // 19
    {
      int fd;
      int return_code;

      memread_user(f->esp + 4, &fd, sizeof(fd));
      return_code = sys_inumber(fd);
      f->eax = return_code;
      break;
    }

#endif


  /* unhandled case */
  default:
    printf("[ERROR] system call %d is unimplemented!\n", syscall_number);

    // ensure that waiting (parent) process should wake up and terminate.
    sys_exit(-1);
    break;
  }

}
Exemple #13
0
/*
 * The main routine to restore task via sigreturn.
 * This one is very special, we never return there
 * but use sigreturn facility to restore core registers
 * and jump execution to some predefined ip read from
 * core file.
 */
long __export_restore_task(struct task_restore_core_args *args)
{
	long ret = -1;
	VmaEntry *vma_entry;
	u64 va;
	unsigned long premmapped_end = args->premmapped_addr + args->premmapped_len;

	struct rt_sigframe *rt_sigframe;
	unsigned long new_sp;
	pid_t my_pid = sys_getpid();
	rt_sigaction_t act;

	task_entries = args->task_entries;

	ksigfillset(&act.rt_sa_mask);
	act.rt_sa_handler = sigchld_handler;
	act.rt_sa_flags = SA_SIGINFO | SA_RESTORER | SA_RESTART;
	act.rt_sa_restorer = cr_restore_rt;
	sys_sigaction(SIGCHLD, &act, NULL, sizeof(k_rtsigset_t));

	log_set_fd(args->logfd);
	log_set_loglevel(args->loglevel);

	cap_last_cap = args->cap_last_cap;

	pr_info("Switched to the restorer %d\n", my_pid);

	for (vma_entry = args->self_vmas; vma_entry->start != 0; vma_entry++) {
		unsigned long addr = vma_entry->start;
		unsigned long len;

		if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
			continue;

		pr_debug("Examine %"PRIx64"-%"PRIx64"\n", vma_entry->start, vma_entry->end);

		if (addr < args->premmapped_addr) {
			if (vma_entry->end >= args->premmapped_addr)
				len = args->premmapped_addr - addr;
			else
				len = vma_entry->end - vma_entry->start;
			if (sys_munmap((void *) addr, len)) {
				pr_err("munmap fail for %lx - %lx\n", addr, addr + len);
				goto core_restore_end;
			}
		}

		if (vma_entry->end >= TASK_SIZE)
			continue;

		if (vma_entry->end > premmapped_end) {
			if (vma_entry->start < premmapped_end)
				addr = premmapped_end;
			len = vma_entry->end - addr;
			if (sys_munmap((void *) addr, len)) {
				pr_err("munmap fail for %lx - %lx\n", addr, addr + len);
				goto core_restore_end;
			}
		}
	}

	sys_munmap(args->self_vmas,
			((void *)(vma_entry + 1) - ((void *)args->self_vmas)));

	/* Shift private vma-s to the left */
	for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_entry++) {
		if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
			continue;

		if (!vma_priv(vma_entry))
			continue;

		if (vma_entry->end >= TASK_SIZE)
			continue;

		if (vma_entry->start > vma_entry->shmid)
			break;

		if (vma_remap(vma_premmaped_start(vma_entry),
				vma_entry->start, vma_entry_len(vma_entry)))
			goto core_restore_end;
	}

	/* Shift private vma-s to the right */
	for (vma_entry = args->tgt_vmas + args->nr_vmas -1;
				vma_entry >= args->tgt_vmas; vma_entry--) {
		if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
			continue;

		if (!vma_priv(vma_entry))
			continue;

		if (vma_entry->start > TASK_SIZE)
			continue;

		if (vma_entry->start < vma_entry->shmid)
			break;

		if (vma_remap(vma_premmaped_start(vma_entry),
				vma_entry->start, vma_entry_len(vma_entry)))
			goto core_restore_end;
	}

	/*
	 * OK, lets try to map new one.
	 */
	for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_entry++) {
		if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
			continue;

		if (vma_priv(vma_entry))
			continue;

		va = restore_mapping(vma_entry);

		if (va != vma_entry->start) {
			pr_err("Can't restore %"PRIx64" mapping with %"PRIx64"\n", vma_entry->start, va);
			goto core_restore_end;
		}
	}

	/*
	 * Walk though all VMAs again to drop PROT_WRITE
	 * if it was not there.
	 */
	for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_entry++) {
		if (!(vma_entry_is(vma_entry, VMA_AREA_REGULAR)))
			continue;

		if (vma_entry_is(vma_entry, VMA_ANON_SHARED)) {
			struct shmem_info *entry;

			entry = find_shmem(args->shmems,
						  vma_entry->shmid);
			if (entry && entry->pid == my_pid &&
			    entry->start == vma_entry->start)
				futex_set_and_wake(&entry->lock, 1);
		}

		if (vma_entry->prot & PROT_WRITE)
			continue;

		sys_mprotect(decode_pointer(vma_entry->start),
			     vma_entry_len(vma_entry),
			     vma_entry->prot);
	}

	/*
	 * Finally restore madivse() bits
	 */
	for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_entry++) {
		unsigned long i;

		if (!vma_entry->has_madv || !vma_entry->madv)
			continue;
		for (i = 0; i < sizeof(vma_entry->madv) * 8; i++) {
			if (vma_entry->madv & (1ul << i)) {
				ret = sys_madvise(vma_entry->start,
						  vma_entry_len(vma_entry),
						  i);
				if (ret) {
					pr_err("madvise(%"PRIx64", %"PRIu64", %ld) "
					       "failed with %ld\n",
						vma_entry->start,
						vma_entry_len(vma_entry),
						i, ret);
					goto core_restore_end;
				}
			}
		}
	}

	sys_munmap(args->tgt_vmas,
			((void *)(vma_entry + 1) - ((void *)args->tgt_vmas)));

	ret = sys_munmap(args->shmems, SHMEMS_SIZE);
	if (ret < 0) {
		pr_err("Can't unmap shmem %ld\n", ret);
		goto core_restore_end;
	}

	/*
	 * Tune up the task fields.
	 */
	ret |= sys_prctl_safe(PR_SET_NAME, (long)args->comm, 0, 0);

	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE,	(long)args->mm.mm_start_code, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE,	(long)args->mm.mm_end_code, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA,	(long)args->mm.mm_start_data, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA,	(long)args->mm.mm_end_data, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_STACK,	(long)args->mm.mm_start_stack, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_BRK,	(long)args->mm.mm_start_brk, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_BRK,		(long)args->mm.mm_brk, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_START,	(long)args->mm.mm_arg_start, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END,	(long)args->mm.mm_arg_end, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_START,	(long)args->mm.mm_env_start, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_END,	(long)args->mm.mm_env_end, 0);
	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_AUXV,	(long)args->mm_saved_auxv, args->mm_saved_auxv_size);
	if (ret)
		goto core_restore_end;

	/*
	 * Because of requirements applied from kernel side
	 * we need to restore /proc/pid/exe symlink late,
	 * after old existing VMAs are superseded with
	 * new ones from image file.
	 */
	ret = restore_self_exe_late(args);
	if (ret)
		goto core_restore_end;

	/*
	 * We need to prepare a valid sigframe here, so
	 * after sigreturn the kernel will pick up the
	 * registers from the frame, set them up and
	 * finally pass execution to the new IP.
	 */
	rt_sigframe = (void *)args->t->mem_zone.rt_sigframe + 8;

	if (restore_thread_common(rt_sigframe, args->t))
		goto core_restore_end;

	/*
	 * Threads restoration. This requires some more comments. This
	 * restorer routine and thread restorer routine has the following
	 * memory map, prepared by a caller code.
	 *
	 * | <-- low addresses                                          high addresses --> |
	 * +-------------------------------------------------------+-----------------------+
	 * | this proc body | own stack | heap | rt_sigframe space | thread restore zone   |
	 * +-------------------------------------------------------+-----------------------+
	 *
	 * where each thread restore zone is the following
	 *
	 * | <-- low addresses                                     high addresses --> |
	 * +--------------------------------------------------------------------------+
	 * | thread restore proc | thread1 stack | thread1 heap | thread1 rt_sigframe |
	 * +--------------------------------------------------------------------------+
	 */

	if (args->nr_threads > 1) {
		struct thread_restore_args *thread_args = args->thread_args;
		long clone_flags = CLONE_VM | CLONE_FILES | CLONE_SIGHAND	|
				   CLONE_THREAD | CLONE_SYSVSEM;
		long last_pid_len;
		long parent_tid;
		int i, fd;

		fd = sys_open(LAST_PID_PATH, O_RDWR, LAST_PID_PERM);
		if (fd < 0) {
			pr_err("Can't open last_pid %d\n", fd);
			goto core_restore_end;
		}

		ret = sys_flock(fd, LOCK_EX);
		if (ret) {
			pr_err("Can't lock last_pid %d\n", fd);
			goto core_restore_end;
		}

		for (i = 0; i < args->nr_threads; i++) {
			char last_pid_buf[16], *s;

			/* skip self */
			if (thread_args[i].pid == args->t->pid)
				continue;

			mutex_lock(&args->rst_lock);

			new_sp =
				RESTORE_ALIGN_STACK((long)thread_args[i].mem_zone.stack,
						    sizeof(thread_args[i].mem_zone.stack));

			last_pid_len = vprint_num(last_pid_buf, sizeof(last_pid_buf), thread_args[i].pid - 1, &s);
			ret = sys_write(fd, s, last_pid_len);
			if (ret < 0) {
				pr_err("Can't set last_pid %ld/%s\n", ret, last_pid_buf);
				goto core_restore_end;
			}

			/*
			 * To achieve functionality like libc's clone()
			 * we need a pure assembly here, because clone()'ed
			 * thread will run with own stack and we must not
			 * have any additional instructions... oh, dear...
			 */

			RUN_CLONE_RESTORE_FN(ret, clone_flags, new_sp, parent_tid, thread_args, args->clone_restore_fn);
		}

		ret = sys_flock(fd, LOCK_UN);
		if (ret) {
			pr_err("Can't unlock last_pid %ld\n", ret);
			goto core_restore_end;
		}

		sys_close(fd);
	}

	restore_rlims(args);

	pr_info("%ld: Restored\n", sys_getpid());

	futex_set(&zombies_inprogress, args->nr_zombies);

	restore_finish_stage(CR_STATE_RESTORE);

	futex_wait_while_gt(&zombies_inprogress, 0);

	sys_sigaction(SIGCHLD, &args->sigchld_act, NULL, sizeof(k_rtsigset_t));

	ret = restore_signals(args->siginfo, args->siginfo_nr, true);
	if (ret)
		goto core_restore_end;

	ret = restore_signals(args->t->siginfo, args->t->siginfo_nr, false);
	if (ret)
		goto core_restore_end;

	restore_finish_stage(CR_STATE_RESTORE_SIGCHLD);

	if (args->siginfo_size) {
		ret = sys_munmap(args->siginfo, args->siginfo_size);
		if (ret < 0) {
			pr_err("Can't unmap signals %ld\n", ret);
			goto core_restore_failed;
		}
	}

	rst_tcp_socks_all(args->rst_tcp_socks, args->rst_tcp_socks_size);

	/* 
	 * Writing to last-pid is CAP_SYS_ADMIN protected,
	 * turning off TCP repair is CAP_SYS_NED_ADMIN protected,
	 * thus restore* creds _after_ all of the above.
	 */

	ret = restore_creds(&args->creds);

	futex_set_and_wake(&thread_inprogress, args->nr_threads);

	restore_finish_stage(CR_STATE_RESTORE_CREDS);

	if (ret)
		BUG();

	/* Wait until children stop to use args->task_entries */
	futex_wait_while_gt(&thread_inprogress, 1);

	log_set_fd(-1);

	/*
	 * The code that prepared the itimers makes shure the
	 * code below doesn't fail due to bad timing values.
	 */

#define itimer_armed(args, i)				\
		(args->itimers[i].it_interval.tv_sec ||	\
		 args->itimers[i].it_interval.tv_usec)

	if (itimer_armed(args, 0))
		sys_setitimer(ITIMER_REAL, &args->itimers[0], NULL);
	if (itimer_armed(args, 1))
		sys_setitimer(ITIMER_VIRTUAL, &args->itimers[1], NULL);
	if (itimer_armed(args, 2))
		sys_setitimer(ITIMER_PROF, &args->itimers[2], NULL);

	ret = sys_munmap(args->task_entries, TASK_ENTRIES_SIZE);
	if (ret < 0) {
		ret = ((long)__LINE__ << 16) | ((-ret) & 0xffff);
		goto core_restore_failed;
	}

	/*
	 * Sigframe stack.
	 */
	new_sp = (long)rt_sigframe + SIGFRAME_OFFSET;

	/*
	 * Prepare the stack and call for sigreturn,
	 * pure assembly since we don't need any additional
	 * code insns from gcc.
	 */
	ARCH_RT_SIGRETURN(new_sp);

core_restore_end:
	futex_abort_and_wake(&task_entries->nr_in_progress);
	pr_err("Restorer fail %ld\n", sys_getpid());
	sys_exit_group(1);
	return -1;

core_restore_failed:
	ARCH_FAIL_CORE_RESTORE;

	return ret;
}
Exemple #14
0
static void brk_fini(void)
{
	sys_munmap(brk_start, MAX_HEAP_SIZE);
}
int munmap(unsigned long addr, size_t len)
{
  return sys_munmap(addr, len);
}
Exemple #16
0
int munmap(uintptr_t addr, size_t len)
{
	return sys_munmap(addr, len);
}
Exemple #17
0
static int syscall_dispatch(uint32_t sysnum, uint32_t args, regs_t *regs)
{
    switch (sysnum) {
        case SYS_waitpid:
            return sys_waitpid((waitpid_args_t *)args);
            
        case SYS_exit:
            do_exit((int)args);
            panic("exit failed!\n");
            return 0;
            
        case SYS_thr_exit:
            kthread_exit((void *)args);
            panic("thr_exit failed!\n");
            return 0;
            
        case SYS_thr_yield:
            sched_make_runnable(curthr);
            sched_switch();
            return 0;
            
        case SYS_fork:
            return sys_fork(regs);
            
        case SYS_getpid:
            return curproc->p_pid;
            
        case SYS_sync:
            sys_sync();
            return 0;
            
#ifdef __MOUNTING__
        case SYS_mount:
            return sys_mount((mount_args_t *) args);
            
        case SYS_umount:
            return sys_umount((argstr_t *) args);
#endif
            
        case SYS_mmap:
            return (int) sys_mmap((mmap_args_t *) args);
            
        case SYS_munmap:
            return sys_munmap((munmap_args_t *) args);
            
        case SYS_open:
            return sys_open((open_args_t *) args);
            
        case SYS_close:
            return sys_close((int)args);
            
        case SYS_read:
            return sys_read((read_args_t *)args);
            
        case SYS_write:
            return sys_write((write_args_t *)args);
            
        case SYS_dup:
            return sys_dup((int)args);
            
        case SYS_dup2:
            return sys_dup2((dup2_args_t *)args);
            
        case SYS_mkdir:
            return sys_mkdir((mkdir_args_t *)args);
            
        case SYS_rmdir:
            return sys_rmdir((argstr_t *)args);
            
        case SYS_unlink:
            return sys_unlink((argstr_t *)args);
            
        case SYS_link:
            return sys_link((link_args_t *)args);
            
        case SYS_rename:
            return sys_rename((rename_args_t *)args);
            
        case SYS_chdir:
            return sys_chdir((argstr_t *)args);
            
        case SYS_getdents:
            return sys_getdents((getdents_args_t *)args);
            
        case SYS_brk:
            return (int) sys_brk((void *)args);
            
        case SYS_lseek:
            return sys_lseek((lseek_args_t *)args);
            
        case SYS_halt:
            sys_halt();
            return -1;
            
        case SYS_set_errno:
            curthr->kt_errno = (int)args;
            return 0;
            
        case SYS_errno:
            return curthr->kt_errno;
            
        case SYS_execve:
            return sys_execve((execve_args_t *)args, regs);
            
        case SYS_stat:
            return sys_stat((stat_args_t *)args);
            
        case SYS_uname:
            return sys_uname((struct utsname *)args);
            
        case SYS_debug:
            return sys_debug((argstr_t *)args);
        case SYS_kshell:
            return sys_kshell((int)args);
        default:
            dbg(DBG_ERROR, "ERROR: unknown system call: %d (args: %#08x)\n", sysnum, args);
            curthr->kt_errno = ENOSYS;
            return -1;
    }
}
Exemple #18
0
void __export_unmap(void)
{
	sys_munmap(bootstrap_start, bootstrap_len);
}
Exemple #19
0
void __export_unmap(void)
{
	sys_munmap(bootstrap_start, bootstrap_len - vdso_rt_size);
}
Exemple #20
0
static void
syscall_handler (struct intr_frame *f)
{
  /* Check to see that we can read supplied user memory pointer, using the
     check_mem_ptr helper() function, in get_word_from_stack(). If the
     check fails, the process is terminated. */

  int syscall_number = (int)get_word_on_stack(f, 0);

  switch(syscall_number) {
    case SYS_HALT:
    {
      sys_halt();
      break;
    }
    case SYS_EXIT:
    {
      int status = (int)get_word_on_stack(f, 1);
      sys_exit(status);
      /* Returns exit status to the kernel. */
      f->eax = status;
      break;
    }
    case SYS_EXEC:
    {
      const char *cmd_line  = (const char *)get_word_on_stack(f, 1);
      pid_t pid = sys_exec(cmd_line);
      /* Returns new processes pid. */
      f->eax = pid;
      break;
    }
    case SYS_WAIT:
    {
      pid_t pid = (pid_t)get_word_on_stack(f, 1);
      /* Returns child's exit status (pid argument is pid of this child). */
      f->eax = sys_wait(pid);
      break;
    }
    case SYS_CREATE:
    {
      const char *filename  = (const char *)get_word_on_stack(f, 1);
      unsigned initial_size = (unsigned)get_word_on_stack(f, 2);
      /* Returns true to the kernel if creation is successful. */
      f->eax = (int)sys_create(filename, initial_size);
      break;
    }
    case SYS_REMOVE:
    {
      const char *filename = (const char *)get_word_on_stack(f, 1);
      /* Returns true if successful, and false otherwise. */
      f->eax = sys_remove(filename);
      break;
    }
    case SYS_OPEN:
    {
      const char *filename = (const char *)get_word_on_stack(f, 1);
      /* Returns file descriptor of opened file, or -1 if it could not
         be opened. */
      f->eax = sys_open(filename);
      break;
    }
    case SYS_FILESIZE:
    {
      int fd = (int)get_word_on_stack(f, 1);
      /* Returns size of file in bytes. */
      f->eax = sys_filesize(fd);
      break;
    }
    case SYS_READ:
    {
      int fd        = (int)get_word_on_stack(f, 1);
      void *buffer  = (void *)get_word_on_stack(f, 2);
      unsigned size = (unsigned)get_word_on_stack(f, 3);
      /* Returns number of bytes actually read, or -1 if it could not
         be read. */
      f->eax = sys_read(fd, buffer, size, f);
      break;
    }
    case SYS_WRITE:
    {
      int fd        = (int)get_word_on_stack(f, 1);
      void *buffer  = (void *)get_word_on_stack(f, 2);
      unsigned size = (unsigned)get_word_on_stack(f, 3);
      /* Returns number of bytes written. */
      f->eax = sys_write(fd, buffer, size);
      break;
    }
    case SYS_SEEK:
    {
      int fd             = (int)get_word_on_stack(f, 1);
      unsigned position  = (int)get_word_on_stack(f, 2);
      sys_seek(fd, position);
      break;
    }
    case SYS_TELL:
    {
      int fd        = (int)get_word_on_stack(f, 1);
      /* Returns the position of the next byte to be read or written in open
         file 'fd' (in bytes, from start of file). */
      f->eax = sys_tell(fd);
      break;
    }
    case SYS_CLOSE:
    {
      int fd        = (int)get_word_on_stack(f, 1);
      sys_close(fd);
      break;
    }
    case SYS_MMAP:
    {
        int fd     = (int)get_word_on_stack(f, 1);
        void *addr = (void *)get_word_on_stack(f, 2);
        f->eax = sys_mmap(fd, addr);
        break;
    }
    case SYS_MUNMAP:
    {
        mapid_t mapping = (mapid_t)get_word_on_stack(f, 1);
        sys_munmap(mapping);
        break;
    }
    default:
    {
      NOT_REACHED();
    }
  }

}
Exemple #21
0
int vdso_proxify(char *who, struct vdso_symtable *sym_rt,
		 unsigned long vdso_rt_parked_at, size_t index,
		 VmaEntry *vmas, size_t nr_vmas)
{
	VmaEntry *vma_vdso = NULL, *vma_vvar = NULL;
	struct vdso_symtable s = VDSO_SYMTABLE_INIT;
	bool remap_rt = false;

	/*
	 * Figure out which kind of vdso tuple we get.
	 */
	if (vma_entry_is(&vmas[index], VMA_AREA_VDSO))
		vma_vdso = &vmas[index];
	else if (vma_entry_is(&vmas[index], VMA_AREA_VVAR))
		vma_vvar = &vmas[index];

	if (index < (nr_vmas - 1)) {
		if (vma_entry_is(&vmas[index + 1], VMA_AREA_VDSO))
			vma_vdso = &vmas[index + 1];
		else if (vma_entry_is(&vmas[index + 1], VMA_AREA_VVAR))
			vma_vvar = &vmas[index + 1];
	}

	if (!vma_vdso) {
		pr_err("Can't find vDSO area in image\n");
		return -1;
	}

	/*
	 * vDSO mark overwrites Elf program header of proxy vDSO thus
	 * it must never ever be greater in size.
	 */
	BUILD_BUG_ON(sizeof(struct vdso_mark) > sizeof(Elf64_Phdr));

	/*
	 * Find symbols in vDSO zone read from image.
	 */
	if (vdso_fill_symtable((void *)vma_vdso->start, vma_entry_len(vma_vdso), &s))
		return -1;

	/*
	 * Proxification strategy
	 *
	 *  - There might be two vDSO zones: vdso code and optionally vvar data
	 *  - To be able to use in-place remapping we need
	 *
	 *    a) Size and order of vDSO zones are to match
	 *    b) Symbols offsets must match
	 *    c) Have same number of vDSO zones
	 */
	if (vma_entry_len(vma_vdso) == vdso_vma_size(sym_rt)) {
		size_t i;

		for (i = 0; i < ARRAY_SIZE(s.symbols); i++) {
			if (s.symbols[i].offset != sym_rt->symbols[i].offset)
				break;
		}

		if (i == ARRAY_SIZE(s.symbols)) {
			if (vma_vvar && sym_rt->vvar_start != VVAR_BAD_ADDR) {
				remap_rt = (vvar_vma_size(sym_rt) == vma_entry_len(vma_vvar));
				if (remap_rt) {
					long delta_rt = sym_rt->vvar_start - sym_rt->vma_start;
					long delta_this = vma_vvar->start - vma_vdso->start;

					remap_rt = (delta_rt ^ delta_this) < 0 ? false : true;
				}
			} else
				remap_rt = true;
		}
	}

	pr_debug("image [vdso] %lx-%lx [vvar] %lx-%lx\n",
		 vma_vdso->start, vma_vdso->end,
		 vma_vvar ? vma_vvar->start : VVAR_BAD_ADDR,
		 vma_vvar ? vma_vvar->end : VVAR_BAD_ADDR);

	/*
	 * Easy case -- the vdso from image has same offsets, order and size
	 * as runtime, so we simply remap runtime vdso to dumpee position
	 * without generating any proxy.
	 *
	 * Note we may remap VVAR vdso as well which might not yet been mapped
	 * by a caller code. So drop VMA_AREA_REGULAR from it and caller would
	 * not touch it anymore.
	 */
	if (remap_rt) {
		int ret = 0;

		pr_info("Runtime vdso/vvar matches dumpee, remap inplace\n");

		if (sys_munmap((void *)vma_vdso->start, vma_entry_len(vma_vdso))) {
			pr_err("Failed to unmap %s\n", who);
			return -1;
		}

		if (vma_vvar) {
			if (sys_munmap((void *)vma_vvar->start, vma_entry_len(vma_vvar))) {
				pr_err("Failed to unmap %s\n", who);
				return -1;
			}

			if (vma_vdso->start < vma_vvar->start) {
				ret  = vdso_remap(who, vdso_rt_parked_at, vma_vdso->start, vdso_vma_size(sym_rt));
				vdso_rt_parked_at += vdso_vma_size(sym_rt);
				ret |= vdso_remap(who, vdso_rt_parked_at, vma_vvar->start, vvar_vma_size(sym_rt));
			} else {
				ret  = vdso_remap(who, vdso_rt_parked_at, vma_vvar->start, vvar_vma_size(sym_rt));
				vdso_rt_parked_at += vvar_vma_size(sym_rt);
				ret |= vdso_remap(who, vdso_rt_parked_at, vma_vdso->start, vdso_vma_size(sym_rt));
			}
		} else
			ret = vdso_remap(who, vdso_rt_parked_at, vma_vdso->start, vdso_vma_size(sym_rt));

		return ret;
	}

	/*
	 * Now complex case -- we need to proxify calls. We redirect
	 * calls from dumpee vdso to runtime vdso, making dumpee
	 * to operate as proxy vdso.
	 */
	pr_info("Runtime vdso mismatches dumpee, generate proxy\n");

	/*
	 * Don't forget to shift if vvar is before vdso.
	 */
	if (sym_rt->vvar_start != VDSO_BAD_ADDR &&
	    sym_rt->vvar_start < sym_rt->vma_start)
		vdso_rt_parked_at += vvar_vma_size(sym_rt);

	if (vdso_redirect_calls(vdso_rt_parked_at,
				vma_vdso->start,
				sym_rt, &s)) {
		pr_err("Failed to proxify dumpee contents\n");
		return -1;
	}

	/*
	 * Put a special mark into runtime vdso, thus at next checkpoint
	 * routine we could detect this vdso and do not dump it, since
	 * it's auto-generated every new session if proxy required.
	 */
	sys_mprotect((void *)vdso_rt_parked_at,  vdso_vma_size(sym_rt), PROT_WRITE);
	vdso_put_mark((void *)vdso_rt_parked_at, vma_vdso->start, vma_vvar ? vma_vvar->start : VVAR_BAD_ADDR);
	sys_mprotect((void *)vdso_rt_parked_at,  vdso_vma_size(sym_rt), VDSO_PROT);
	return 0;
}
Exemple #22
0
int
cloudabi_sys_mem_advise(struct thread *td,
    struct cloudabi_sys_mem_advise_args *uap)
{
	struct madvise_args madvise_args = {
		.addr	= uap->addr,
		.len	= uap->len
	};

	switch (uap->advice) {
	case CLOUDABI_ADVICE_DONTNEED:
		madvise_args.behav = MADV_DONTNEED;
		break;
	case CLOUDABI_ADVICE_NORMAL:
		madvise_args.behav = MADV_NORMAL;
		break;
	case CLOUDABI_ADVICE_RANDOM:
		madvise_args.behav = MADV_RANDOM;
		break;
	case CLOUDABI_ADVICE_SEQUENTIAL:
		madvise_args.behav = MADV_SEQUENTIAL;
		break;
	case CLOUDABI_ADVICE_WILLNEED:
		madvise_args.behav = MADV_WILLNEED;
		break;
	default:
		return (EINVAL);
	}

	return (sys_madvise(td, &madvise_args));
}

int
cloudabi_sys_mem_lock(struct thread *td, struct cloudabi_sys_mem_lock_args *uap)
{
	struct mlock_args mlock_args = {
		.addr	= uap->addr,
		.len	= uap->len
	};

	return (sys_mlock(td, &mlock_args));
}

int
cloudabi_sys_mem_map(struct thread *td, struct cloudabi_sys_mem_map_args *uap)
{
	struct mmap_args mmap_args = {
		.addr	= uap->addr,
		.len	= uap->len,
		.fd	= uap->fd,
		.pos	= uap->off
	};
	int error;

	/* Translate flags. */
	if (uap->flags & CLOUDABI_MAP_ANON)
		mmap_args.flags |= MAP_ANON;
	if (uap->flags & CLOUDABI_MAP_FIXED)
		mmap_args.flags |= MAP_FIXED;
	if (uap->flags & CLOUDABI_MAP_PRIVATE)
		mmap_args.flags |= MAP_PRIVATE;
	if (uap->flags & CLOUDABI_MAP_SHARED)
		mmap_args.flags |= MAP_SHARED;

	/* Translate protection. */
	error = convert_mprot(uap->prot, &mmap_args.prot);
	if (error != 0)
		return (error);

	return (sys_mmap(td, &mmap_args));
}

int
cloudabi_sys_mem_protect(struct thread *td,
    struct cloudabi_sys_mem_protect_args *uap)
{
	struct mprotect_args mprotect_args = {
		.addr	= uap->addr,
		.len	= uap->len,
	};
	int error;

	/* Translate protection. */
	error = convert_mprot(uap->prot, &mprotect_args.prot);
	if (error != 0)
		return (error);

	return (sys_mprotect(td, &mprotect_args));
}

int
cloudabi_sys_mem_sync(struct thread *td, struct cloudabi_sys_mem_sync_args *uap)
{
	struct msync_args msync_args = {
		.addr	= uap->addr,
		.len	= uap->len,
	};

	/* Convert flags. */
	switch (uap->flags & (CLOUDABI_MS_ASYNC | CLOUDABI_MS_SYNC)) {
	case CLOUDABI_MS_ASYNC:
		msync_args.flags |= MS_ASYNC;
		break;
	case CLOUDABI_MS_SYNC:
		msync_args.flags |= MS_SYNC;
		break;
	default:
		return (EINVAL);
	}
	if ((uap->flags & CLOUDABI_MS_INVALIDATE) != 0)
		msync_args.flags |= MS_INVALIDATE;

	return (sys_msync(td, &msync_args));
}

int
cloudabi_sys_mem_unlock(struct thread *td,
    struct cloudabi_sys_mem_unlock_args *uap)
{
	struct munlock_args munlock_args = {
		.addr	= uap->addr,
		.len	= uap->len
	};

	return (sys_munlock(td, &munlock_args));
}

int
cloudabi_sys_mem_unmap(struct thread *td,
    struct cloudabi_sys_mem_unmap_args *uap)
{
	struct munmap_args munmap_args = {
		.addr	= uap->addr,
		.len	= uap->len
	};

	return (sys_munmap(td, &munmap_args));
}