Example #1
0
int
main()
{
    char *stack;
    char *stackTop;
    pid_t pid;

    stack = malloc(STACK_SIZE);
    stackTop = stack + STACK_SIZE;	/* Assume stack grows downward */

#if defined(__ia64__)
    pid = __clone2(child_fn, stack, STACK_SIZE, SIGCHLD);
    //staptest// clone2 (0x0|SIGCHLD, XXXX, 0x100000, XXXX, XXXX)
#else
    pid = clone(child_fn, stackTop, SIGCHLD, NULL);
    //staptest// clone (0x0|SIGCHLD, XXXX, XXXX, XXXX)
#endif
    wait4(pid, NULL, 0, NULL);		/* Wait for child */
    //staptest// wait4 (NNNN, 0x0, 0, 0x0) = NNNN

#define FLAG_ALL (CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD)
#if defined(__ia64__)
    pid = __clone2(child_fn, stack, STACK_SIZE, FLAG_ALL);
    //staptest// clone2 (CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD, XXXX, 0x100000, XXXX, XXXX)
#else
    pid = clone(child_fn, stackTop, FLAG_ALL, NULL);
    //staptest// clone (CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD, XXXX, XXXX, XXXX)
#endif
    wait4(pid, NULL, 0, NULL);		/* Wait for child */
    //staptest// wait4 (NNNN, 0x0, 0, 0x0) = NNNN

    return 0;
}
int
main (int argc, char **argv)
{
  unsigned char *stack;
  int res;

  alarm (300);

  stack = malloc (STACK_SIZE);
  assert (stack != NULL);

#define CLONE_FLAGS (CLONE_THREAD | CLONE_SIGHAND | CLONE_VM)

#ifdef __ia64__
  clone_pid = __clone2 (clone_fn, stack, STACK_SIZE, CLONE_FLAGS, NULL);
#else
  clone_pid = clone (clone_fn, stack + STACK_SIZE, CLONE_FLAGS, NULL);
#endif

  assert (clone_pid > 0);

  /* Wait for alarm.  */
  while (1)
    sleep (1);

  return 0;
}
Example #3
0
File: cloner.c Project: 1587/ltp
/*
 * ltp_clone: wrapper for clone to hide the architecture dependencies.
 *   1. hppa takes bottom of stack and no stacksize (stack grows up)
 *   2. __ia64__ takes bottom of stack and uses clone2
 *   3. all others take top of stack (stack grows down)
 */
static int
ltp_clone_(unsigned long flags, int (*fn)(void *arg), void *arg,
	   size_t stack_size, void *stack, pid_t *ptid, void *tls, pid_t *ctid)
{
	int ret;

#if defined(__ia64__)
	ret = __clone2(fn, stack, stack_size, flags, arg, ptid, tls, ctid);
#else
# if defined(__hppa__) || defined(__metag__)
	/*
	 * These arches grow their stack up, so don't need to adjust the base.
	 * XXX: This should be made into a runtime test.
	 */
# else
	/*
	 * For archs where stack grows downwards, stack points to the topmost
	 * address of the memory space set up for the child stack.
	 */
	if (stack)
		stack += stack_size;
# endif

	ret = clone(fn, stack, flags, arg, ptid, tls, ctid);
#endif

	return ret;
}
Example #4
0
static int
do_test (void)
{
  bool ok = true;

  puts ("in main");

  if (TEST_STACK_ALIGN ())
    ok = false;

#ifdef __ia64__
  extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
		       size_t __child_stack_size, int __flags,
		       void *__arg, ...);
  char st[256 * 1024];
  pid_t p = __clone2 (f, st, sizeof (st), 0, 0);
#else
  char st[128 * 1024] __attribute__ ((aligned));
# if _STACK_GROWS_DOWN
  pid_t p = clone (f, st + sizeof (st), 0, 0);
# elif _STACK_GROWS_UP
  pid_t p = clone (f, st, 0, 0);
# else
#  error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
# endif
#endif
  if (p == -1)
    {
      printf("clone failed: %m\n");
      return 1;
    }

  int e;
  if (waitpid (p, &e, __WCLONE) != p)
    {
      puts ("waitpid failed");
      kill (p, SIGKILL);
      return 1;
    }
  if (!WIFEXITED (e))
    {
      if (WIFSIGNALED (e))
	printf ("died from signal %s\n", strsignal (WTERMSIG (e)));
      else
	puts ("did not terminate correctly");
      return 1;
    }
  if (WEXITSTATUS (e) != 0)
    ok = false;

  return ok ? 0 : 1;
}
Example #5
0
File: start.c Project: rowhit/lxc
static int must_drop_cap_sys_boot(struct lxc_conf *conf)
{
	FILE *f;
	int ret, cmd, v, flags;
        long stack_size = 4096;
        void *stack = alloca(stack_size);
        int status;
        pid_t pid;

	f = fopen("/proc/sys/kernel/ctrl-alt-del", "r");
	if (!f) {
		DEBUG("failed to open /proc/sys/kernel/ctrl-alt-del");
		return 1;
	}

	ret = fscanf(f, "%d", &v);
	fclose(f);
	if (ret != 1) {
		DEBUG("Failed to read /proc/sys/kernel/ctrl-alt-del");
		return 1;
	}
	cmd = v ? LINUX_REBOOT_CMD_CAD_ON : LINUX_REBOOT_CMD_CAD_OFF;

	flags = CLONE_NEWPID | SIGCHLD;
	if (!lxc_list_empty(&conf->id_map))
		flags |= CLONE_NEWUSER;

#ifdef __ia64__
	pid = __clone2(container_reboot_supported, stack, stack_size, flags,  &cmd);
#else
	stack += stack_size;
	pid = clone(container_reboot_supported, stack, flags, &cmd);
#endif
	if (pid < 0) {
		if (flags & CLONE_NEWUSER)
			ERROR("failed to clone (%#x): %s (includes CLONE_NEWUSER)", flags, strerror(errno));
		else
			ERROR("failed to clone (%#x): %s", flags, strerror(errno));
		return -1;
	}
	if (wait(&status) < 0) {
		SYSERROR("unexpected wait error: %m");
		return -1;
	}

	if (WEXITSTATUS(status) != 1)
		return 1;

	return 0;
}
Example #6
0
int main ()
{
  pid_t pid;
  static char stack[STACK_SIZE];
#ifdef __ia64__
  pid = __clone2((myfunc)&child, stack, STACK_SIZE, CLONE_FS, NULL);
#else
  pid = clone((myfunc)&child, stack + STACK_SIZE, CLONE_FS, NULL);
#endif
  if (pid < 0)
    {
      perror("clone called failed");
      exit (1);
    }
  
  return 0;
}
Example #7
0
static pid_t clone_newns(void *a)
{
	char buf[131072];
	char *stack = buf + (sizeof(buf) / 2 - ((size_t) buf & 15));

#ifdef __ia64__
	extern int __clone2(int (*fn)(void *),
			    void *child_stack_base, size_t stack_size,
			    int flags, void *arg, pid_t *ptid,
			    void *tls, pid_t *ctid);

	return __clone2(check_is_mount_child, stack, sizeof(buf) / 2,
			CLONE_NEWNS, a, NULL, NULL, NULL);
#else
	return clone(check_is_mount_child, stack, CLONE_NEWNS, a);
#endif
}
Example #8
0
static int clone_monitor(struct supertype *container)
{
	static char stack[4096];

#ifdef __ia64__
	mon_tid = __clone2(run_child, stack, sizeof(stack),
		   CLONE_FS|CLONE_FILES|CLONE_VM|CLONE_SIGHAND|CLONE_THREAD,
		   container);
#else
	mon_tid = clone(run_child, stack+4096-64,
		   CLONE_FS|CLONE_FILES|CLONE_VM|CLONE_SIGHAND|CLONE_THREAD,
		   container);
#endif

	mgr_tid = syscall(SYS_gettid);

	return mon_tid;
}
Example #9
0
/**
 * Wrapper for system clone function.
 */
pid_t saferun_clone(int (*fn)(void *), void *arg, int flags)
{
    long stack_size = sysconf(_SC_PAGESIZE);
    void *stack = alloca(stack_size) + stack_size;
    pid_t ret;
 
#ifdef __ia64__
    ret = __clone2(fn, stack,
            stack_size, flags | SIGCHLD, arg);
#else
    ret = clone(fn, stack, flags | SIGCHLD, arg);
#endif
    if (ret < 0) {
        ERROR("Failed to clone(0x%x): %s", flags, strerror(errno));
        throw -1;
    }

    return ret;
}
Example #10
0
pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
{
	struct clone_arg clone_arg = {
		.fn = fn,
		.arg = arg,
	};

	long stack_size = sysconf(_SC_PAGESIZE);
	void *stack = alloca(stack_size);
	pid_t ret;

#ifdef __ia64__
	ret = __clone2(do_clone, stack,
		       stack_size, flags | SIGCHLD, &clone_arg);
#else
	ret = clone(do_clone, stack  + stack_size, flags | SIGCHLD, &clone_arg);
#endif
	if (ret < 0)
		ERROR("failed to clone(0x%x): %s", flags, strerror(errno));

	return ret;
}
Example #11
0
void *
thread_fn (void *arg)
{
  unsigned char *stack;
  int res;

  stack = malloc (STACK_SIZE);
  assert (stack != NULL);

#ifdef __ia64__
  clone_pid = __clone2 (clone_fn, stack, STACK_SIZE, CLONE_VM, NULL);
#else
  clone_pid = clone (clone_fn, stack + STACK_SIZE, CLONE_VM, NULL);
#endif

  assert (clone_pid > 0);

  /* Wait for child.  */
  res = waitpid (clone_pid, NULL, __WCLONE);
  assert (res != -1);

  return NULL;
}
Example #12
0
int __pthread_initialize_manager(void)
{
  int manager_pipe[2];
  int pid;
  int report_events;
  struct pthread_request request;

  *__libc_multiple_threads_ptr = 1;

  /* If basic initialization not done yet (e.g. we're called from a
     constructor run before our constructor), do it now */
  if (__pthread_initial_thread_bos == NULL) pthread_initialize();
  /* Setup stack for thread manager */
  __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
  if (__pthread_manager_thread_bos == NULL) return -1;
  __pthread_manager_thread_tos =
    __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;

  /* On non-MMU systems we make sure that the initial thread bounds don't overlap
   * with the manager stack frame */
  NOMMU_INITIAL_THREAD_BOUNDS(__pthread_manager_thread_tos,__pthread_manager_thread_bos);
  PDEBUG("manager stack: size=%d, bos=%p, tos=%p\n", THREAD_MANAGER_STACK_SIZE,
	 __pthread_manager_thread_bos, __pthread_manager_thread_tos);
#if 0
  PDEBUG("initial stack: estimate bos=%p, tos=%p\n",
	 __pthread_initial_thread_bos, __pthread_initial_thread_tos);
#endif

  /* Setup pipe to communicate with thread manager */
  if (pipe(manager_pipe) == -1) {
    free(__pthread_manager_thread_bos);
    return -1;
  }
  /* Start the thread manager */
  pid = 0;
#if defined(USE_TLS) && USE_TLS
  if (__linuxthreads_initial_report_events != 0)
    THREAD_SETMEM (((pthread_descr) NULL), p_report_events,
		   __linuxthreads_initial_report_events);
  report_events = THREAD_GETMEM (((pthread_descr) NULL), p_report_events);
#else
  if (__linuxthreads_initial_report_events != 0)
    __pthread_initial_thread.p_report_events
      = __linuxthreads_initial_report_events;
  report_events = __pthread_initial_thread.p_report_events;
#endif
  if (__builtin_expect (report_events, 0))
    {
      /* It's a bit more complicated.  We have to report the creation of
	 the manager thread.  */
      int idx = __td_eventword (TD_CREATE);
      uint32_t mask = __td_eventmask (TD_CREATE);

      if ((mask & (__pthread_threads_events.event_bits[idx]
		   | __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]))
	  != 0)
	{

	 __pthread_lock(__pthread_manager_thread.p_lock, NULL);

#ifdef __ia64__
	  pid = __clone2(__pthread_manager_event,
			(void **) __pthread_manager_thread_tos,
			THREAD_MANAGER_STACK_SIZE,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
			(void *)(long)manager_pipe[0]);
#else
	  pid = clone(__pthread_manager_event,
			(void **) __pthread_manager_thread_tos,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
			(void *)(long)manager_pipe[0]);
#endif

	  if (pid != -1)
	    {
	      /* Now fill in the information about the new thread in
	         the newly created thread's data structure.  We cannot let
	         the new thread do this since we don't know whether it was
	         already scheduled when we send the event.  */
	      __pthread_manager_thread.p_eventbuf.eventdata =
		  &__pthread_manager_thread;
	      __pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE;
	      __pthread_last_event = &__pthread_manager_thread;
	      __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
	      __pthread_manager_thread.p_pid = pid;

	      /* Now call the function which signals the event.  */
	      __linuxthreads_create_event ();
	    }
	  /* Now restart the thread.  */
	  __pthread_unlock(__pthread_manager_thread.p_lock);
	}
    }

  if (pid == 0) {
#ifdef __ia64__
    pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_tos,
		  THREAD_MANAGER_STACK_SIZE,
		  CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
		  (void *)(long)manager_pipe[0]);
#else
    pid = clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
		  CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
		  (void *)(long)manager_pipe[0]);
#endif
  }
  if (pid == -1) {
    free(__pthread_manager_thread_bos);
    close(manager_pipe[0]);
    close(manager_pipe[1]);
    return -1;
  }
  __pthread_manager_request = manager_pipe[1]; /* writing end */
  __pthread_manager_reader = manager_pipe[0]; /* reading end */
  __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
  __pthread_manager_thread.p_pid = pid;

  /* Make gdb aware of new thread manager */
  if (__pthread_threads_debug && __pthread_sig_debug > 0)
    {
      raise(__pthread_sig_debug);
      /* We suspend ourself and gdb will wake us up when it is
	 ready to handle us. */
      __pthread_wait_for_restart_signal(thread_self());
    }
  /* Synchronize debugging of the thread manager */
  PDEBUG("send REQ_DEBUG to manager thread\n");
  request.req_kind = REQ_DEBUG;
  TEMP_FAILURE_RETRY(write(__pthread_manager_request,
	      (char *) &request, sizeof(request)));
  return 0;
}
Example #13
0
static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
				 void * (*start_routine)(void *), void *arg,
				 sigset_t * mask, int father_pid,
				 int report_events,
				 td_thr_events_t *event_maskp)
{
  size_t sseg;
  int pid;
  pthread_descr new_thread;
  char * new_thread_bottom;
  char * new_thread_top;
  pthread_t new_thread_id;
  char *guardaddr = NULL;
  size_t guardsize = 0;
  int pagesize = getpagesize();
  int saved_errno = 0;

  /* First check whether we have to change the policy and if yes, whether
     we can  do this.  Normally this should be done by examining the
     return value of the sched_setscheduler call in pthread_start_thread
     but this is hard to implement.  FIXME  */
  if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0)
    return EPERM;
  /* Find a free segment for the thread, and allocate a stack if needed */
  for (sseg = 2; ; sseg++)
    {
      if (sseg >= PTHREAD_THREADS_MAX)
	return EAGAIN;
      if (__pthread_handles[sseg].h_descr != NULL)
	continue;
      if (pthread_allocate_stack(attr, thread_segment(sseg), pagesize,
                                 &new_thread, &new_thread_bottom,
                                 &guardaddr, &guardsize) == 0)
        break;
#ifndef __ARCH_USE_MMU__
      else
        /* When there is MMU, mmap () is used to allocate the stack. If one
         * segment is already mapped, we should continue to see if we can
         * use the next one. However, when there is no MMU, malloc () is used.
         * It's waste of CPU cycles to continue to try if it fails.  */
        return EAGAIN;
#endif
    }
  __pthread_handles_num++;
  /* Allocate new thread identifier */
  pthread_threads_counter += PTHREAD_THREADS_MAX;
  new_thread_id = sseg + pthread_threads_counter;
  /* Initialize the thread descriptor.  Elements which have to be
     initialized to zero already have this value.  */
  new_thread->p_tid = new_thread_id;
  new_thread->p_lock = &(__pthread_handles[sseg].h_lock);
  new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
  new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
  new_thread->p_errnop = &new_thread->p_errno;
  new_thread->p_h_errnop = &new_thread->p_h_errno;
#ifdef __UCLIBC_HAS_XLOCALE__
  /* Initialize thread's locale to the global locale. */
  new_thread->locale = __global_locale;
#endif /* __UCLIBC_HAS_XLOCALE__ */
  new_thread->p_guardaddr = guardaddr;
  new_thread->p_guardsize = guardsize;
  new_thread->p_self = new_thread;
  new_thread->p_nr = sseg;
  /* Initialize the thread handle */
  __pthread_init_lock(&__pthread_handles[sseg].h_lock);
  __pthread_handles[sseg].h_descr = new_thread;
  __pthread_handles[sseg].h_bottom = new_thread_bottom;
  /* Determine scheduling parameters for the thread */
  new_thread->p_start_args.schedpolicy = -1;
  if (attr != NULL) {
    new_thread->p_detached = attr->__detachstate;
    new_thread->p_userstack = attr->__stackaddr_set;

    switch(attr->__inheritsched) {
    case PTHREAD_EXPLICIT_SCHED:
      new_thread->p_start_args.schedpolicy = attr->__schedpolicy;
      memcpy (&new_thread->p_start_args.schedparam, &attr->__schedparam,
	      sizeof (struct sched_param));
      break;
    case PTHREAD_INHERIT_SCHED:
      new_thread->p_start_args.schedpolicy = sched_getscheduler(father_pid);
      sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
      break;
    }
    new_thread->p_priority =
      new_thread->p_start_args.schedparam.sched_priority;
  }
  /* Finish setting up arguments to pthread_start_thread */
  new_thread->p_start_args.start_routine = start_routine;
  new_thread->p_start_args.arg = arg;
  new_thread->p_start_args.mask = *mask;
  /* Raise priority of thread manager if needed */
  __pthread_manager_adjust_prio(new_thread->p_priority);
  /* Do the cloning.  We have to use two different functions depending
     on whether we are debugging or not.  */
  pid = 0;     /* Note that the thread never can have PID zero.  */
  new_thread_top = ((char *)new_thread - THREAD_STACK_OFFSET);

  /* ******************************************************** */
  /*  This code was moved from below to cope with running threads
   *  on uClinux systems.  See comment below...
   * Insert new thread in doubly linked list of active threads */
  new_thread->p_prevlive = __pthread_main_thread;
  new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
  __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
  __pthread_main_thread->p_nextlive = new_thread;
  /* ********************************************************* */

  if (report_events)
    {
      /* See whether the TD_CREATE event bit is set in any of the
         masks.  */
      int idx = __td_eventword (TD_CREATE);
      uint32_t m = __td_eventmask (TD_CREATE);

      if ((m & (__pthread_threads_events.event_bits[idx]
		   | event_maskp->event_bits[idx])) != 0)
	{
	  /* Lock the mutex the child will use now so that it will stop.  */
	  __pthread_lock(new_thread->p_lock, NULL);

	  /* We have to report this event.  */
#ifdef __ia64__
	  pid = __clone2(pthread_start_thread_event, new_thread_top,
			new_thread_top - new_thread_bottom,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
			__pthread_sig_cancel, new_thread);
#else
	  pid = clone(pthread_start_thread_event, new_thread_top,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
			__pthread_sig_cancel, new_thread);
#endif

	  saved_errno = errno;
	  if (pid != -1)
	    {
	      /* Now fill in the information about the new thread in
	         the newly created thread's data structure.  We cannot let
	         the new thread do this since we don't know whether it was
	         already scheduled when we send the event.  */
	      new_thread->p_eventbuf.eventdata = new_thread;
	      new_thread->p_eventbuf.eventnum = TD_CREATE;
	      __pthread_last_event = new_thread;

	      /* We have to set the PID here since the callback function
		 in the debug library will need it and we cannot guarantee
		 the child got scheduled before the debugger.  */
	      new_thread->p_pid = pid;

	      /* Now call the function which signals the event.  */
	      __linuxthreads_create_event ();

	      /* Now restart the thread.  */
	      __pthread_unlock(new_thread->p_lock);
	    }
	}
    }
  if (pid == 0)
    {
      PDEBUG("cloning new_thread = %p\n", new_thread);
#ifdef __ia64__
      pid = __clone2(pthread_start_thread, new_thread_top,
		    new_thread_top - new_thread_bottom,
		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
		    __pthread_sig_cancel, new_thread);
#else
      pid = clone(pthread_start_thread, new_thread_top,
		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
		    __pthread_sig_cancel, new_thread);
#endif
      saved_errno = errno;
    }
  /* Check if cloning succeeded */
  if (pid == -1) {
    /********************************************************
     * Code inserted to remove the thread from our list of active
     * threads in case of failure (needed to cope with uClinux),
     * See comment below. */
    new_thread->p_nextlive->p_prevlive = new_thread->p_prevlive;
    new_thread->p_prevlive->p_nextlive = new_thread->p_nextlive;
    /********************************************************/

    /* Free the stack if we allocated it */
    if (attr == NULL || !attr->__stackaddr_set)
      {
#ifdef __ARCH_USE_MMU__
	if (new_thread->p_guardsize != 0)
	  munmap(new_thread->p_guardaddr, new_thread->p_guardsize);
	munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
	       INITIAL_STACK_SIZE);
#else
	free(new_thread_bottom);
#endif /* __ARCH_USE_MMU__ */
      }
    __pthread_handles[sseg].h_descr = NULL;
    __pthread_handles[sseg].h_bottom = NULL;
    __pthread_handles_num--;
    return saved_errno;
  }
  PDEBUG("new thread pid = %d\n", pid);

#if 0
  /* ***********************************************************
   This code has been moved before the call to clone().  In uClinux,
   the use of wait on a semaphore is dependant upon that the child so
   the child must be in the active threads list. This list is used in
   pthread_find_self() to get the pthread_descr of self. So, if the
   child calls sem_wait before this code is executed , it will hang
   forever and initial_thread will instead be posted by a sem_post
   call. */

  /* Insert new thread in doubly linked list of active threads */
  new_thread->p_prevlive = __pthread_main_thread;
  new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
  __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
  __pthread_main_thread->p_nextlive = new_thread;
  /************************************************************/
#endif

  /* Set pid field of the new thread, in case we get there before the
     child starts. */
  new_thread->p_pid = pid;
  /* We're all set */
  *thread = new_thread_id;
  return 0;
}
Example #14
0
static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
				 void * (*start_routine)(void *), void *arg,
				 sigset_t * mask, int father_pid,
				 int report_events,
				 td_thr_events_t *event_maskp)
{
  size_t sseg;
  int pid;
  pthread_descr new_thread;
  char *stack_addr;
  char * new_thread_bottom;
  pthread_t new_thread_id;
  char *guardaddr = NULL;
  size_t guardsize = 0, stksize = 0;
  int pagesize = __getpagesize();
  int saved_errno = 0;

#ifdef USE_TLS
  new_thread = _dl_allocate_tls (NULL);
  if (new_thread == NULL)
    return EAGAIN;
# if TLS_DTV_AT_TP
  /* pthread_descr is below TP.  */
  new_thread = (pthread_descr) ((char *) new_thread - TLS_PRE_TCB_SIZE);
# endif
#else
  /* Prevent warnings.  */
  new_thread = NULL;
#endif

  /* First check whether we have to change the policy and if yes, whether
     we can  do this.  Normally this should be done by examining the
     return value of the __sched_setscheduler call in pthread_start_thread
     but this is hard to implement.  FIXME  */
  if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0)
    return EPERM;
  /* Find a free segment for the thread, and allocate a stack if needed */
  for (sseg = 2; ; sseg++)
    {
      if (sseg >= PTHREAD_THREADS_MAX)
	{
#ifdef USE_TLS
# if TLS_DTV_AT_TP
	  new_thread = (pthread_descr) ((char *) new_thread + TLS_PRE_TCB_SIZE);
# endif
	  _dl_deallocate_tls (new_thread, true);
#endif
	  return EAGAIN;
	}
      if (__pthread_handles[sseg].h_descr != NULL)
	continue;
      if (pthread_allocate_stack(attr, thread_segment(sseg),
				 pagesize, &stack_addr, &new_thread_bottom,
                                 &guardaddr, &guardsize, &stksize) == 0)
	{
#ifdef USE_TLS
	  new_thread->p_stackaddr = stack_addr;
#else
	  new_thread = (pthread_descr) stack_addr;
#endif
	  break;
#ifndef __ARCH_USE_MMU__
	} else {
	  /* When there is MMU, mmap () is used to allocate the stack. If one
	   * segment is already mapped, we should continue to see if we can
	   * use the next one. However, when there is no MMU, malloc () is used.
	   * It's waste of CPU cycles to continue to try if it fails.  */
	  return EAGAIN;
#endif
	}
    }
  __pthread_handles_num++;
  /* Allocate new thread identifier */
  pthread_threads_counter += PTHREAD_THREADS_MAX;
  new_thread_id = sseg + pthread_threads_counter;
  /* Initialize the thread descriptor.  Elements which have to be
     initialized to zero already have this value.  */
#if !defined USE_TLS || !TLS_DTV_AT_TP
  new_thread->p_header.data.tcb = new_thread;
  new_thread->p_header.data.self = new_thread;
#endif
#if TLS_MULTIPLE_THREADS_IN_TCB || !defined USE_TLS || !TLS_DTV_AT_TP
  new_thread->p_multiple_threads = 1;
#endif
  new_thread->p_tid = new_thread_id;
  new_thread->p_lock = &(__pthread_handles[sseg].h_lock);
  new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
  new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
#if !(USE_TLS && HAVE___THREAD)
  new_thread->p_errnop = &new_thread->p_errno;
  new_thread->p_h_errnop = &new_thread->p_h_errno;
  new_thread->p_resp = &new_thread->p_res;
#endif
  new_thread->p_guardaddr = guardaddr;
  new_thread->p_guardsize = guardsize;
  new_thread->p_nr = sseg;
  new_thread->p_inheritsched = attr ? attr->__inheritsched : 0;
  new_thread->p_alloca_cutoff = stksize / 4 > __MAX_ALLOCA_CUTOFF
				 ? __MAX_ALLOCA_CUTOFF : stksize / 4;
  /* Initialize the thread handle */
  __pthread_init_lock(&__pthread_handles[sseg].h_lock);
  __pthread_handles[sseg].h_descr = new_thread;
  __pthread_handles[sseg].h_bottom = new_thread_bottom;
  /* Determine scheduling parameters for the thread */
  new_thread->p_start_args.schedpolicy = -1;
  if (attr != NULL) {
    new_thread->p_detached = attr->__detachstate;
    new_thread->p_userstack = attr->__stackaddr_set;

    switch(attr->__inheritsched) {
    case PTHREAD_EXPLICIT_SCHED:
      new_thread->p_start_args.schedpolicy = attr->__schedpolicy;
      memcpy (&new_thread->p_start_args.schedparam, &attr->__schedparam,
	      sizeof (struct sched_param));
      break;
    case PTHREAD_INHERIT_SCHED:
      new_thread->p_start_args.schedpolicy = __sched_getscheduler(father_pid);
      __sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
      break;
    }
    new_thread->p_priority =
      new_thread->p_start_args.schedparam.sched_priority;
  }
  /* Finish setting up arguments to pthread_start_thread */
  new_thread->p_start_args.start_routine = start_routine;
  new_thread->p_start_args.arg = arg;
  new_thread->p_start_args.mask = *mask;
  /* Make the new thread ID available already now.  If any of the later
     functions fail we return an error value and the caller must not use
     the stored thread ID.  */
  *thread = new_thread_id;
  /* Raise priority of thread manager if needed */
  __pthread_manager_adjust_prio(new_thread->p_priority);
  /* Do the cloning.  We have to use two different functions depending
     on whether we are debugging or not.  */
  pid = 0;	/* Note that the thread never can have PID zero.  */
  if (report_events)
    {
      /* See whether the TD_CREATE event bit is set in any of the
         masks.  */
      int idx = __td_eventword (TD_CREATE);
      uint32_t mask = __td_eventmask (TD_CREATE);

      if ((mask & (__pthread_threads_events.event_bits[idx]
		   | event_maskp->event_bits[idx])) != 0)
	{
	  /* Lock the mutex the child will use now so that it will stop.  */
	  __pthread_lock(new_thread->p_lock, NULL);

	  /* We have to report this event.  */
#ifdef NEED_SEPARATE_REGISTER_STACK
	  /* Perhaps this version should be used on all platforms. But
	   this requires that __clone2 be uniformly supported
	   everywhere.

	   And there is some argument for changing the __clone2
	   interface to pass sp and bsp instead, making it more IA64
	   specific, but allowing stacks to grow outward from each
	   other, to get less paging and fewer mmaps.  */
	  pid = __clone2(pthread_start_thread_event,
  		 (void **)new_thread_bottom,
			 (char *)stack_addr - new_thread_bottom,
			 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
			 __pthread_sig_cancel, new_thread);
#elif _STACK_GROWS_UP
	  pid = __clone(pthread_start_thread_event, (void *) new_thread_bottom,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
			__pthread_sig_cancel, new_thread);
#else
	  pid = __clone(pthread_start_thread_event, stack_addr,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
			__pthread_sig_cancel, new_thread);
#endif
	  saved_errno = errno;
	  if (pid != -1)
	    {
	      /* Now fill in the information about the new thread in
		 the newly created thread's data structure.  We cannot let
		 the new thread do this since we don't know whether it was
		 already scheduled when we send the event.  */
	      new_thread->p_eventbuf.eventdata = new_thread;
	      new_thread->p_eventbuf.eventnum = TD_CREATE;
	      __pthread_last_event = new_thread;

	      /* We have to set the PID here since the callback function
		 in the debug library will need it and we cannot guarantee
		 the child got scheduled before the debugger.  */
	      new_thread->p_pid = pid;

	      /* Now call the function which signals the event.  */
	      __linuxthreads_create_event ();

	      /* Now restart the thread.  */
	      __pthread_unlock(new_thread->p_lock);
	    }
	}
    }
  if (pid == 0)
    {
#ifdef NEED_SEPARATE_REGISTER_STACK
      pid = __clone2(pthread_start_thread,
		     (void **)new_thread_bottom,
                     (char *)stack_addr - new_thread_bottom,
		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
		     __pthread_sig_cancel, new_thread);
#elif _STACK_GROWS_UP
      pid = __clone(pthread_start_thread, (void *) new_thread_bottom,
		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
		    __pthread_sig_cancel, new_thread);
#else
      pid = __clone(pthread_start_thread, stack_addr,
		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
		    __pthread_sig_cancel, new_thread);
#endif /* !NEED_SEPARATE_REGISTER_STACK */
      saved_errno = errno;
    }
  /* Check if cloning succeeded */
  if (pid == -1) {
    /* Free the stack if we allocated it */
    if (attr == NULL || !attr->__stackaddr_set)
      {
#ifdef NEED_SEPARATE_REGISTER_STACK
	size_t stacksize = ((char *)(new_thread->p_guardaddr)
			    - new_thread_bottom);
	munmap((caddr_t)new_thread_bottom,
	       2 * stacksize + new_thread->p_guardsize);
#elif _STACK_GROWS_UP
# ifdef USE_TLS
	size_t stacksize = guardaddr - stack_addr;
	munmap(stack_addr, stacksize + guardsize);
# else
	size_t stacksize = guardaddr - (char *)new_thread;
	munmap(new_thread, stacksize + guardsize);
# endif
#else
# ifdef USE_TLS
	size_t stacksize = stack_addr - new_thread_bottom;
# else
	size_t stacksize = (char *)(new_thread+1) - new_thread_bottom;
# endif
	munmap(new_thread_bottom - guardsize, guardsize + stacksize);
#endif
      }
#ifdef USE_TLS
# if TLS_DTV_AT_TP
    new_thread = (pthread_descr) ((char *) new_thread + TLS_PRE_TCB_SIZE);
# endif
    _dl_deallocate_tls (new_thread, true);
#endif
    __pthread_handles[sseg].h_descr = NULL;
    __pthread_handles[sseg].h_bottom = NULL;
    __pthread_handles_num--;
    return saved_errno;
  }
  /* Insert new thread in doubly linked list of active threads */
  new_thread->p_prevlive = __pthread_main_thread;
  new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
  __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
  __pthread_main_thread->p_nextlive = new_thread;
  /* Set pid field of the new thread, in case we get there before the
     child starts. */
  new_thread->p_pid = pid;
  return 0;
}
static int
do_test (void)
{
  int mypid = getpid ();

  sig = SIGRTMIN;
  sigset_t ss;
  sigemptyset (&ss);
  sigaddset (&ss, sig);
  if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0)
    {
      printf ("sigprocmask failed: %m\n");
      return 1;
    }

#ifdef __ia64__
  extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
		       size_t __child_stack_size, int __flags,
		       void *__arg, ...);
  char st[256 * 1024] __attribute__ ((aligned));
  pid_t p = __clone2 (f, st, sizeof (st), TEST_CLONE_FLAGS, 0);
#else
  char st[128 * 1024] __attribute__ ((aligned));
  pid_t p = clone (f, st + sizeof (st), TEST_CLONE_FLAGS, 0);
#endif
  if (p == -1)
    {
      printf("clone failed: %m\n");
      return 1;
    }
  printf ("new thread: %d\n", (int) p);

  siginfo_t si;
  do
    if (sigwaitinfo (&ss, &si) < 0)
      {
	printf("sigwaitinfo failed: %m\n");
	kill (p, SIGKILL);
	return 1;
      }
  while  (si.si_signo != sig || si.si_code != SI_QUEUE);

  int e;
  if (waitpid (p, &e, __WCLONE) != p)
    {
      puts ("waitpid failed");
      kill (p, SIGKILL);
      return 1;
    }
  if (!WIFEXITED (e))
    {
      if (WIFSIGNALED (e))
	printf ("died from signal %s\n", strsignal (WTERMSIG (e)));
      else
	puts ("did not terminate correctly");
      return 1;
    }
  if (WEXITSTATUS (e) != 0)
    {
      printf ("exit code %d\n", WEXITSTATUS (e));
      return 1;
    }

  if (si.si_int != (int) p)
    {
      printf ("expected PID %d, got si_int %d\n", (int) p, si.si_int);
      kill (p, SIGKILL);
      return 1;
    }

  if (si.si_pid != p)
    {
      printf ("expected PID %d, got si_pid %d\n", (int) p, (int) si.si_pid);
      kill (p, SIGKILL);
      return 1;
    }

  if (getpid () != mypid)
    {
      puts ("my PID changed");
      return 1;
    }

  return 0;
}
Example #16
0
int main(int argc, char **argv)
{
	int pagesize;
	void *clone_stack, *page;
	int pid, rc, status, cloneflags;
	security_context_t context_s;
	context_t context;

	if (argc != 4) {
		fprintf(stderr, "usage:  %s cloneflags newdomain program\n", argv[0]);
		exit(-1);
	}

	cloneflags = strtol(argv[1], NULL, 0);
	if (!cloneflags) {
		fprintf(stderr, "invalid clone flags %s\n", argv[1]);
		exit(-1);
	}

	pagesize = 16 * getpagesize();
	page = malloc(pagesize);
	if (!page) {
		perror("malloc");
		exit(-1);
	}
	clone_stack = page + pagesize;

	rc = getcon(&context_s);
	if (rc < 0) {
		fprintf(stderr, "%s:  unable to get my context\n", argv[0]);
		exit(-1);

	}

	context = context_new(context_s);
	if (!context) {
		fprintf(stderr, "%s:  unable to create context structure\n", argv[0]);
		exit(-1);
	}

	if (context_type_set(context, argv[2])) {
		fprintf(stderr, "%s:  unable to set new type\n", argv[0]);
		exit(-1);
	}

	freecon(context_s);
	context_s = context_str(context);
	if (!context_s) {
		fprintf(stderr, "%s:  unable to obtain new context string\n", argv[0]);
		exit(-1);
	}

	rc = setexeccon(context_s);
	if (rc < 0) {
		fprintf(stderr, "%s:  unable to set exec context to %s\n", argv[0], context_s);
		exit(-1);
	}

#if defined(__hppa__)
	pid = clone(clone_fn, page, cloneflags | SIGCHLD, argv);
#elif defined(__ia64__)
	pid = __clone2(clone_fn, page, pagesize, cloneflags | SIGCHLD, argv, NULL, NULL,
		       NULL);
#else
	pid = clone(clone_fn, clone_stack, cloneflags | SIGCHLD, argv);
#endif
	if (pid < 0) {
		perror("clone");
		exit(-1);
	}

	pid = wait(&status);
	if (pid < 0) {
		perror("wait");
		exit(-1);
	}

	if (WIFEXITED(status)) {
		fprintf(stderr, "Child exited with status %d.\n", WEXITSTATUS(status));
		exit(WEXITSTATUS(status));
	}

	if (WIFSTOPPED(status)) {
		fprintf(stderr, "Child stopped by signal %d.\n", WSTOPSIG(status));
		fprintf(stderr, "..This shouldn't happen.\n");
		fprintf(stderr, "..Killing the child.\n");
		rc = kill(pid, SIGKILL);
		if (rc < 0) {
			perror("kill");
			exit(-1);
		}
		exit(-1);
	}

	if (WIFSIGNALED(status)) {
		fprintf(stderr, "Child terminated by signal %d.\n", WTERMSIG(status));
		fprintf(stderr,
			"..This is consistent with a share permission denial, check the audit message.\n");
		exit(1);
	}

	fprintf(stderr, "Unexpected exit status 0x%x\n", status);
	exit(-1);
}
Example #17
0
int __pthread_initialize_manager(void)
{
  int manager_pipe[2];
  int pid;
  struct pthread_request request;

#ifndef HAVE_Z_NODELETE
  if (__builtin_expect (&__dso_handle != NULL, 1))
    __cxa_atexit ((void (*) (void *)) pthread_atexit_retcode, NULL,
		  __dso_handle);
#endif

  if (__pthread_max_stacksize == 0)
    __pthread_init_max_stacksize ();
  /* If basic initialization not done yet (e.g. we're called from a
     constructor run before our constructor), do it now */
  if (__pthread_initial_thread_bos == NULL) pthread_initialize();
  /* Setup stack for thread manager */
  __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
  if (__pthread_manager_thread_bos == NULL) return -1;
  __pthread_manager_thread_tos =
    __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;
  /* Setup pipe to communicate with thread manager */
  if (__libc_pipe(manager_pipe) == -1) {
    free(__pthread_manager_thread_bos);
    return -1;
  }
  /* Start the thread manager */
  pid = 0;
  if (__builtin_expect (__pthread_initial_thread.p_report_events, 0))
    {
      /* It's a bit more complicated.  We have to report the creation of
	 the manager thread.  */
      int idx = __td_eventword (TD_CREATE);
      uint32_t mask = __td_eventmask (TD_CREATE);

      if ((mask & (__pthread_threads_events.event_bits[idx]
		   | __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]))
	  != 0)
	{
	  __pthread_lock(__pthread_manager_thread.p_lock, NULL);

#ifdef NEED_SEPARATE_REGISTER_STACK
	  pid = __clone2(__pthread_manager_event,
			 (void **) __pthread_manager_thread_bos,
			 THREAD_MANAGER_STACK_SIZE,
			 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
			 (void *)(long)manager_pipe[0]);
#elif _STACK_GROWS_UP
	  pid = __clone(__pthread_manager_event,
			(void **) __pthread_manager_thread_bos,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
			(void *)(long)manager_pipe[0]);
#else
	  pid = __clone(__pthread_manager_event,
			(void **) __pthread_manager_thread_tos,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
			(void *)(long)manager_pipe[0]);
#endif

	  if (pid != -1)
	    {
	      /* Now fill in the information about the new thread in
	         the newly created thread's data structure.  We cannot let
	         the new thread do this since we don't know whether it was
	         already scheduled when we send the event.  */
	      __pthread_manager_thread.p_eventbuf.eventdata =
		&__pthread_manager_thread;
	      __pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE;
	      __pthread_last_event = &__pthread_manager_thread;
	      __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
	      __pthread_manager_thread.p_pid = pid;

	      /* Now call the function which signals the event.  */
	      __linuxthreads_create_event ();
	    }

	  /* Now restart the thread.  */
	  __pthread_unlock(__pthread_manager_thread.p_lock);
	}
    }

  if (__builtin_expect (pid, 0) == 0)
    {
#ifdef NEED_SEPARATE_REGISTER_STACK
      pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos,
		     THREAD_MANAGER_STACK_SIZE,
		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
		     (void *)(long)manager_pipe[0]);
#elif _STACK_GROWS_UP
      pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos,
		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
		    (void *)(long)manager_pipe[0]);
#else
      pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
		    (void *)(long)manager_pipe[0]);
#endif
    }
  if (__builtin_expect (pid, 0) == -1) {
    free(__pthread_manager_thread_bos);
    __libc_close(manager_pipe[0]);
    __libc_close(manager_pipe[1]);
    return -1;
  }
  __pthread_manager_request = manager_pipe[1]; /* writing end */
  __pthread_manager_reader = manager_pipe[0]; /* reading end */
  __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
  __pthread_manager_thread.p_pid = pid;
  /* Make gdb aware of new thread manager */
  if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0)
    {
      raise(__pthread_sig_debug);
      /* We suspend ourself and gdb will wake us up when it is
	 ready to handle us. */
      __pthread_wait_for_restart_signal(thread_self());
    }
  /* Synchronize debugging of the thread manager */
  request.req_kind = REQ_DEBUG;
  TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
				  (char *) &request, sizeof(request)));
  return 0;
}