Exemple #1
0
/* Function depends on CMD:
   1 = Return the limit on the size of a file, in units of 512 bytes.
   2 = Set the limit on the size of a file to NEWLIMIT.  Only the
       super-user can increase the limit.
   3 = illegal due to shared libraries; normally is
       (Return the maximum possible address of the data segment.)
   4 = Return the maximum number of files that the calling process
       can open.
   Returns -1 on errors.  */
long int
__ulimit (int cmd, ...)
{
  struct rlimit limit;
  va_list va;
  long int result = -1;

  va_start (va, cmd);

  switch (cmd)
    {
    case UL_GETFSIZE:
      /* Get limit on file size.  */
      if (__getrlimit (RLIMIT_FSIZE, &limit) == 0)
	/* Convert from bytes to 512 byte units.  */
	result =  (limit.rlim_cur == RLIM_INFINITY
		   ? LONG_MAX : limit.rlim_cur / 512);
      break;

    case UL_SETFSIZE:
      /* Set limit on file size.  */
      {
	long int newlimit = va_arg (va, long int);
	long int newlen;

	if ((rlim_t) newlimit > RLIM_INFINITY / 512)
	  {
	    limit.rlim_cur = RLIM_INFINITY;
	    limit.rlim_max = RLIM_INFINITY;
	    newlen = LONG_MAX;
	  }
	else
	  {
	    limit.rlim_cur = newlimit * 512;
	    limit.rlim_max = newlimit * 512;
	    newlen = newlimit;
	  }

	result = __setrlimit (RLIMIT_FSIZE, &limit);
	if (result != -1)
	  result = newlen;
      }
      break;

    case __UL_GETOPENMAX:
      result = __sysconf (_SC_OPEN_MAX);
      break;

    default:
      __set_errno (EINVAL);
    }

  va_end (va);

  return result;
}
long int
__get_child_max (void)
{
# ifdef RLIMIT_NPROC
  struct rlimit limit;
  if (__getrlimit (RLIMIT_NPROC, &limit) == 0
      && limit.rlim_cur != RLIM_INFINITY)
    return limit.rlim_cur;
# endif

  return -1;
}
Exemple #3
0
/* Put the soft and hard limits for RESOURCE in *RLIMITS.
   Returns 0 if successful, -1 if not (and sets errno).  */
int
getrlimit64 (enum __rlimit_resource resource, struct rlimit64 *rlimits)
{
  struct rlimit rlimits32;

  if (__getrlimit (resource, &rlimits32) < 0)
    return -1;

  if (rlimits32.rlim_cur == RLIM_INFINITY)
    rlimits->rlim_cur = RLIM64_INFINITY;
  else
    rlimits->rlim_cur = rlimits32.rlim_cur;
  if (rlimits32.rlim_max == RLIM_INFINITY)
    rlimits->rlim_max = RLIM64_INFINITY;
  else
    rlimits->rlim_max = rlimits32.rlim_max;

  return 0;
}
Exemple #4
0
/* Set the soft limit for RESOURCE to be VALUE.
   Returns 0 for success, -1 for failure.  */
int
vlimit (enum __vlimit_resource resource, int value)
{
  if (resource >= LIM_CPU && resource <= LIM_MAXRSS)
    {
      /* The rlimit codes happen to each be one less
	 than the corresponding vlimit codes.  */
      enum __rlimit_resource rlimit_res =
	(enum __rlimit_resource) ((int) resource - 1);
      struct rlimit lims;

      if (__getrlimit (rlimit_res, &lims) < 0)
	return -1;

      lims.rlim_cur = value;
      return __setrlimit (rlimit_res, &lims);
    }

  __set_errno (EINVAL);
  return -1;
}
Exemple #5
0
/* Put the soft and hard limits for RESOURCE in *RLIMITS.
   Returns 0 if successful, -1 if not (and sets errno).  */
int
getrlimit64 (enum __rlimit_resource resource, struct rlimit64 *rlimits)
{
  /* Same code than the common getrlimit64, but without using the
     prlimit64 syscall until the inconsistency between kernel and
     userland is solved. See:
     http://www.linux-mips.org/archives/linux-mips/2013-06/msg00541.html */

  struct rlimit rlimits32;

  if (__getrlimit (resource, &rlimits32) < 0)
    return -1;

  if (rlimits32.rlim_cur == RLIM_INFINITY)
    rlimits->rlim_cur = RLIM64_INFINITY;
  else
    rlimits->rlim_cur = rlimits32.rlim_cur;
  if (rlimits32.rlim_max == RLIM_INFINITY)
    rlimits->rlim_max = RLIM64_INFINITY;
  else
    rlimits->rlim_max = rlimits32.rlim_max;

  return 0;
}
Exemple #6
0
void
__pthread_initialize_minimal_internal (void)
{
#ifndef SHARED
  /* Unlike in the dynamically linked case the dynamic linker has not
     taken care of initializing the TLS data structures.  */
  __libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN);

  /* We must prevent gcc from being clever and move any of the
     following code ahead of the __libc_setup_tls call.  This function
     will initialize the thread register which is subsequently
     used.  */
  __asm __volatile ("");
#endif

  /* Minimal initialization of the thread descriptor.  */
  struct pthread *pd = THREAD_SELF;
  __pthread_initialize_pids (pd);
  THREAD_SETMEM (pd, specific[0], &pd->specific_1stblock[0]);
  THREAD_SETMEM (pd, user_stack, true);
  if (LLL_LOCK_INITIALIZER != 0)
    THREAD_SETMEM (pd, lock, LLL_LOCK_INITIALIZER);
#if HP_TIMING_AVAIL
  THREAD_SETMEM (pd, cpuclock_offset, GL(dl_cpuclock_offset));
#endif

  /* Initialize the robust mutex data.  */
  {
#ifdef __PTHREAD_MUTEX_HAVE_PREV
    pd->robust_prev = &pd->robust_head;
#endif
    pd->robust_head.list = &pd->robust_head;
#ifdef __NR_set_robust_list
    pd->robust_head.futex_offset = (offsetof (pthread_mutex_t, __data.__lock)
				    - offsetof (pthread_mutex_t,
						__data.__list.__next));
    INTERNAL_SYSCALL_DECL (err);
    int res = INTERNAL_SYSCALL (set_robust_list, err, 2, &pd->robust_head,
				sizeof (struct robust_list_head));
    if (INTERNAL_SYSCALL_ERROR_P (res, err))
#endif
      set_robust_list_not_avail ();
  }

#ifdef __NR_futex
# ifndef __ASSUME_PRIVATE_FUTEX
  /* Private futexes are always used (at least internally) so that
     doing the test once this early is beneficial.  */
  {
    int word = 0;
    INTERNAL_SYSCALL_DECL (err);
    word = INTERNAL_SYSCALL (futex, err, 3, &word,
			    FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1);
    if (!INTERNAL_SYSCALL_ERROR_P (word, err))
      THREAD_SETMEM (pd, header.private_futex, FUTEX_PRIVATE_FLAG);
  }

  /* Private futexes have been introduced earlier than the
     FUTEX_CLOCK_REALTIME flag.  We don't have to run the test if we
     know the former are not supported.  This also means we know the
     kernel will return ENOSYS for unknown operations.  */
  if (THREAD_GETMEM (pd, header.private_futex) != 0)
# endif
# ifndef __ASSUME_FUTEX_CLOCK_REALTIME
    {
      int word = 0;
      /* NB: the syscall actually takes six parameters.  The last is the
	 bit mask.  But since we will not actually wait at all the value
	 is irrelevant.  Given that passing six parameters is difficult
	 on some architectures we just pass whatever random value the
	 calling convention calls for to the kernel.  It causes no harm.  */
      INTERNAL_SYSCALL_DECL (err);
      word = INTERNAL_SYSCALL (futex, err, 5, &word,
			       FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME
			       | FUTEX_PRIVATE_FLAG, 1, NULL, 0);
      assert (INTERNAL_SYSCALL_ERROR_P (word, err));
      if (INTERNAL_SYSCALL_ERRNO (word, err) != ENOSYS)
	__set_futex_clock_realtime ();
    }
# endif
#endif

  /* Set initial thread's stack block from 0 up to __libc_stack_end.
     It will be bigger than it actually is, but for unwind.c/pt-longjmp.c
     purposes this is good enough.  */
  THREAD_SETMEM (pd, stackblock_size, (size_t) __libc_stack_end);

  /* Initialize the list of all running threads with the main thread.  */
  INIT_LIST_HEAD (&__stack_user);
  list_add (&pd->list, &__stack_user);

  /* Before initializing __stack_user, the debugger could not find us and
     had to set __nptl_initial_report_events.  Propagate its setting.  */
  THREAD_SETMEM (pd, report_events, __nptl_initial_report_events);

#if defined SIGCANCEL || defined SIGSETXID
  struct sigaction sa;
  __sigemptyset (&sa.sa_mask);

# ifdef SIGCANCEL
  /* Install the cancellation signal handler.  If for some reason we
     cannot install the handler we do not abort.  Maybe we should, but
     it is only asynchronous cancellation which is affected.  */
  sa.sa_sigaction = sigcancel_handler;
  sa.sa_flags = SA_SIGINFO;
  (void) __libc_sigaction (SIGCANCEL, &sa, NULL);
# endif

# ifdef SIGSETXID
  /* Install the handle to change the threads' uid/gid.  */
  sa.sa_sigaction = sighandler_setxid;
  sa.sa_flags = SA_SIGINFO | SA_RESTART;
  (void) __libc_sigaction (SIGSETXID, &sa, NULL);
# endif

  /* The parent process might have left the signals blocked.  Just in
     case, unblock it.  We reuse the signal mask in the sigaction
     structure.  It is already cleared.  */
# ifdef SIGCANCEL
  __sigaddset (&sa.sa_mask, SIGCANCEL);
# endif
# ifdef SIGSETXID
  __sigaddset (&sa.sa_mask, SIGSETXID);
# endif
  {
    INTERNAL_SYSCALL_DECL (err);
    (void) INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_UNBLOCK, &sa.sa_mask,
			     NULL, _NSIG / 8);
  }
#endif

  /* Get the size of the static and alignment requirements for the TLS
     block.  */
  size_t static_tls_align;
  _dl_get_tls_static_info (&__static_tls_size, &static_tls_align);

  /* Make sure the size takes all the alignments into account.  */
  if (STACK_ALIGN > static_tls_align)
    static_tls_align = STACK_ALIGN;
  __static_tls_align_m1 = static_tls_align - 1;

  __static_tls_size = roundup (__static_tls_size, static_tls_align);

  /* Determine the default allowed stack size.  This is the size used
     in case the user does not specify one.  */
  struct rlimit limit;
  if (__getrlimit (RLIMIT_STACK, &limit) != 0
      || limit.rlim_cur == RLIM_INFINITY)
    /* The system limit is not usable.  Use an architecture-specific
       default.  */
    limit.rlim_cur = ARCH_STACK_DEFAULT_SIZE;
  else if (limit.rlim_cur < PTHREAD_STACK_MIN)
    /* The system limit is unusably small.
       Use the minimal size acceptable.  */
    limit.rlim_cur = PTHREAD_STACK_MIN;

  /* Make sure it meets the minimum size that allocate_stack
     (allocatestack.c) will demand, which depends on the page size.  */
  const uintptr_t pagesz = GLRO(dl_pagesize);
  const size_t minstack = pagesz + __static_tls_size + MINIMAL_REST_STACK;
  if (limit.rlim_cur < minstack)
    limit.rlim_cur = minstack;

  /* Round the resource limit up to page size.  */
  limit.rlim_cur = ALIGN_UP (limit.rlim_cur, pagesz);
  lll_lock (__default_pthread_attr_lock, LLL_PRIVATE);
  __default_pthread_attr.stacksize = limit.rlim_cur;
  __default_pthread_attr.guardsize = GLRO (dl_pagesize);
  lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE);

#ifdef SHARED
  /* Transfer the old value from the dynamic linker's internal location.  */
  *__libc_dl_error_tsd () = *(*GL(dl_error_catch_tsd)) ();
  GL(dl_error_catch_tsd) = &__libc_dl_error_tsd;

  /* Make __rtld_lock_{,un}lock_recursive use pthread_mutex_{,un}lock,
     keep the lock count from the ld.so implementation.  */
  GL(dl_rtld_lock_recursive) = (void *) __pthread_mutex_lock;
  GL(dl_rtld_unlock_recursive) = (void *) __pthread_mutex_unlock;
  unsigned int rtld_lock_count = GL(dl_load_lock).mutex.__data.__count;
  GL(dl_load_lock).mutex.__data.__count = 0;
  while (rtld_lock_count-- > 0)
    __pthread_mutex_lock (&GL(dl_load_lock).mutex);

  GL(dl_make_stack_executable_hook) = &__make_stacks_executable;
#endif

  GL(dl_init_static_tls) = &__pthread_init_static_tls;

  GL(dl_wait_lookup_done) = &__wait_lookup_done;

  /* Register the fork generation counter with the libc.  */
#ifndef TLS_MULTIPLE_THREADS_IN_TCB
  __libc_multiple_threads_ptr =
#endif
    __libc_pthread_init (&__fork_generation, __reclaim_stacks,
			 ptr_pthread_functions);

  /* Determine whether the machine is SMP or not.  */
  __is_smp = is_smp_system ();
}
Exemple #7
0
/* Get the value of the system variable NAME.  */
long int
__sysconf (int name)
{
  const char *procfname = NULL;

  switch (name)
    {
      struct rlimit rlimit;
#ifdef __NR_clock_getres
    case _SC_MONOTONIC_CLOCK:
      /* Check using the clock_getres system call.  */
      {
	struct timespec ts;
	INTERNAL_SYSCALL_DECL (err);
	int r;
	r = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts);
	return INTERNAL_SYSCALL_ERROR_P (r, err) ? -1 : _POSIX_VERSION;
      }
#endif

    case _SC_CPUTIME:
    case _SC_THREAD_CPUTIME:
      return HAS_CPUCLOCK (name);

    case _SC_ARG_MAX:
#if !__ASSUME_ARG_MAX_STACK_BASED
      /* Determine whether this is a kernel with an argument limit
	 determined by the stack size.  */
      if (GLRO(dl_discover_osversion) ()
	  >= __LINUX_ARG_MAX_STACK_BASED_MIN_KERNEL)
#endif
	/* Use getrlimit to get the stack limit.  */
	if (__getrlimit (RLIMIT_STACK, &rlimit) == 0)
	  return MAX (legacy_ARG_MAX, rlimit.rlim_cur / 4);

      return legacy_ARG_MAX;

    case _SC_NGROUPS_MAX:
      /* Try to read the information from the /proc/sys/kernel/ngroups_max
	 file.  */
      procfname = "/proc/sys/kernel/ngroups_max";
      break;

    case _SC_SIGQUEUE_MAX:
      if (__getrlimit (RLIMIT_SIGPENDING, &rlimit) == 0)
	return rlimit.rlim_cur;

      /* The /proc/sys/kernel/rtsig-max file contains the answer.  */
      procfname = "/proc/sys/kernel/rtsig-max";
      break;

    default:
      break;
    }

  if (procfname != NULL)
    {
      int fd = open_not_cancel_2 (procfname, O_RDONLY);
      if (fd != -1)
	{
	  /* This is more than enough, the file contains a single integer.  */
	  char buf[32];
	  ssize_t n;
	  n = TEMP_FAILURE_RETRY (read_not_cancel (fd, buf, sizeof (buf) - 1));
	  close_not_cancel_no_status (fd);

	  if (n > 0)
	    {
	      /* Terminate the string.  */
	      buf[n] = '\0';

	      char *endp;
	      long int res = strtol (buf, &endp, 10);
	      if (endp != buf && (*endp == '\0' || *endp == '\n'))
		return res;
	    }
	}
    }

  return posix_sysconf (name);
}