Esempio n. 1
0
int
signalfd (int fd, const sigset_t *mask, int flags)
{
#ifdef __NR_signalfd4
  int res = INLINE_SYSCALL (signalfd4, 4, fd, mask, _NSIG / 8, flags);
# ifndef __ASSUME_SIGNALFD4
  if (res != -1 || errno != ENOSYS)
# endif
    return res;
#endif

#ifndef __ASSUME_SIGNALFD4
  /* The old system call has no flag parameter which is bad.  So we have
     to wait until we have to support to pass additional values to the
     kernel (sys_indirect) before implementing setting flags like
     O_NONBLOCK etc.  */
  if (flags != 0)
    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);

# ifdef __NR_signalfd
  return INLINE_SYSCALL (signalfd, 3, fd, mask, _NSIG / 8);
# else
  return INLINE_SYSCALL_ERROR_RETURN_VALUE (ENOSYS);
# endif
#elif !defined __NR_signalfd4
# error "__ASSUME_SIGNALFD4 defined but not __NR_signalfd4"
#endif
}
Esempio n. 2
0
int
eventfd (unsigned int count, int flags)
{
#ifdef __NR_eventfd2
    int res = INLINE_SYSCALL (eventfd2, 2, count, flags);
# ifndef __ASSUME_EVENTFD2
    if (res != -1 || errno != ENOSYS)
# endif
        return res;
#endif

#ifndef __ASSUME_EVENTFD2
    /* The old system call has no flag parameter which is bad.  So we have
       to wait until we have to support to pass additional values to the
       kernel (sys_indirect) before implementing setting flags like
       O_NONBLOCK etc.  */
    if (flags != 0)
        return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);

# ifdef __NR_eventfd
    return INLINE_SYSCALL (eventfd, 1, count);
# else
    return INLINE_SYSCALL_ERROR_RETURN_VALUE (ENOSYS);
# endif
#elif !defined __NR_eventfd2
# error "__ASSUME_EVENTFD2 defined but not __NR_eventfd2"
#endif
}
Esempio n. 3
0
int
prlimit (__pid_t pid, enum __rlimit_resource resource,
	 const struct rlimit *new_rlimit, struct rlimit *old_rlimit)
{
  struct rlimit64 new_rlimit64_mem;
  struct rlimit64 *new_rlimit64 = NULL;
  struct rlimit64 old_rlimit64_mem;
  struct rlimit64 *old_rlimit64 = (old_rlimit != NULL
				   ? &old_rlimit64_mem : NULL);

  if (new_rlimit != NULL)
    {
      if (new_rlimit->rlim_cur == RLIM_INFINITY)
	new_rlimit64_mem.rlim_cur = RLIM64_INFINITY;
      else
	new_rlimit64_mem.rlim_cur = new_rlimit->rlim_cur;
      if (new_rlimit->rlim_max == RLIM_INFINITY)
	new_rlimit64_mem.rlim_max = RLIM64_INFINITY;
      else
	new_rlimit64_mem.rlim_max = new_rlimit->rlim_max;
      new_rlimit64 = &new_rlimit64_mem;
    }

  int res = INLINE_SYSCALL (prlimit64, 4, pid, resource, new_rlimit64,
			    old_rlimit64);

  if (res == 0 && old_rlimit != NULL)
    {
      /* The prlimit64 syscall is ill-designed for 32-bit machines.
	 We have to provide a 32-bit variant since otherwise the LFS
	 system would not work.  The infinity value can be translated,
	 but otherwise what shall we do if the syscall succeeds but the
	 old values do not fit into a rlimit structure?  We cannot return
	 an error because the operation itself worked.  Best is perhaps
	 to return RLIM_INFINITY.  */
      old_rlimit->rlim_cur = old_rlimit64_mem.rlim_cur;
      if (old_rlimit->rlim_cur != old_rlimit64_mem.rlim_cur)
	{
	  if ((new_rlimit == NULL)
	      && (old_rlimit64_mem.rlim_cur != RLIM64_INFINITY))
	    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
	  old_rlimit->rlim_cur = RLIM_INFINITY;
	}
      old_rlimit->rlim_max = old_rlimit64_mem.rlim_max;
      if (old_rlimit->rlim_max != old_rlimit64_mem.rlim_max)
	{
	  if ((new_rlimit == NULL)
	      && (old_rlimit64_mem.rlim_max != RLIM64_INFINITY))
	    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
	  old_rlimit->rlim_max = RLIM_INFINITY;
	}
    }

  return res;
}
Esempio n. 4
0
int
__fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag)
{
  if (__glibc_unlikely (vers != _STAT_VER_LINUX))
    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);

  int result;
  INTERNAL_SYSCALL_DECL (err);

  result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, st, flag);
  if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1))
    return 0;
  else
    return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result,
								      err));
}
Esempio n. 5
0
__ptr_t
__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
{
  if (offset & (MMAP_PAGE_UNIT - 1))
    return (__ptr_t) INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
  return (__ptr_t) INLINE_SYSCALL (mmap2, 6, addr, len, prot, flags, fd,
                                   offset / MMAP_PAGE_UNIT);
}
Esempio n. 6
0
/* Change the access time of the file associated with FD to TSP[0] and
   the modification time of FILE to TSP[1].

   Starting with 2.6.22 the Linux kernel has the utimensat syscall which
   can be used to implement futimens.  */
int
futimens (int fd, const struct timespec tsp[2])
{
  if (fd < 0)
    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EBADF);
  /* Avoid implicit array coercion in syscall macros.  */
  return INLINE_SYSCALL (utimensat, 4, fd, NULL, &tsp[0], 0);
}
Esempio n. 7
0
int
lockf64 (int fd, int cmd, off64_t len64)
{
  struct flock64 fl64;
  int cmd64;
  int result;

  memset ((char *) &fl64, '\0', sizeof (fl64));
  fl64.l_whence = SEEK_CUR;
  fl64.l_start = 0;
  fl64.l_len = len64;

  switch (cmd)
    {
    case F_TEST:
      /* Test the lock: return 0 if FD is unlocked or locked by this process;
	 return -1, set errno to EACCES, if another process holds the lock.  */
      fl64.l_type = F_RDLCK;
      INTERNAL_SYSCALL_DECL (err);
      result = INTERNAL_SYSCALL (fcntl64, err, 3, fd, F_GETLK64, &fl64);
      if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
	return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result,
									  err));
      if (fl64.l_type == F_UNLCK || fl64.l_pid == __getpid ())
        return 0;
      return INLINE_SYSCALL_ERROR_RETURN_VALUE (EACCES);
    case F_ULOCK:
      fl64.l_type = F_UNLCK;
      cmd64 = F_SETLK64;
      break;
    case F_LOCK:
      fl64.l_type = F_WRLCK;
      cmd64 = F_SETLKW64;
      break;
    case F_TLOCK:
      fl64.l_type = F_WRLCK;
      cmd64 = F_SETLK64;
      break;

    default:
      return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
    }
  return INLINE_SYSCALL (fcntl64, 3, fd, cmd64, &fl64);
}
Esempio n. 8
0
int
faccessat (int fd, const char *file, int mode, int flag)
{
  if (flag & ~(AT_SYMLINK_NOFOLLOW | AT_EACCESS))
    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);

  if ((flag == 0 || ((flag & ~AT_EACCESS) == 0 && ! __libc_enable_secure)))
    return INLINE_SYSCALL (faccessat, 3, fd, file, mode);

  struct stat64 stats;
  if (__fxstatat64 (_STAT_VER, fd, file, &stats, flag & AT_SYMLINK_NOFOLLOW))
    return -1;

  mode &= (X_OK | W_OK | R_OK);	/* Clear any bogus bits. */
#if R_OK != S_IROTH || W_OK != S_IWOTH || X_OK != S_IXOTH
# error Oops, portability assumptions incorrect.
#endif

  if (mode == F_OK)
    return 0;			/* The file exists. */

  uid_t uid = (flag & AT_EACCESS) ? __geteuid () : __getuid ();

  /* The super-user can read and write any file, and execute any file
     that anyone can execute. */
  if (uid == 0 && ((mode & X_OK) == 0
		   || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
    return 0;

  int granted = (uid == stats.st_uid
		 ? (unsigned int) (stats.st_mode & (mode << 6)) >> 6
		 : (stats.st_gid == ((flag & AT_EACCESS)
				     ? __getegid () : __getgid ())
		    || __group_member (stats.st_gid))
		 ? (unsigned int) (stats.st_mode & (mode << 3)) >> 3
		 : (stats.st_mode & mode));

  if (granted == mode)
    return 0;

  return INLINE_SYSCALL_ERROR_RETURN_VALUE (EACCES);
}
Esempio n. 9
0
int
ustat (dev_t dev, struct ustat *ubuf)
{
  unsigned long long int k_dev;

  /* We must convert the value to dev_t type used by the kernel.  */
  k_dev =  dev & ((1ULL << 32) - 1);
  if (k_dev != dev)
    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);

  return INLINE_SYSCALL (ustat, 2, (unsigned int) k_dev, ubuf);
}
Esempio n. 10
0
int
seteuid (uid_t uid)
{
    int result;

    if (uid == (uid_t) ~0)
        return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);

    result = INLINE_SETXID_SYSCALL (setresuid32, 3, -1, uid, -1);

    return result;
}
Esempio n. 11
0
/* Get information about the file NAME relative to FD in ST.  */
int
__fxstatat (int vers, int fd, const char *file, struct stat *st, int flag)
{
  int result;
  INTERNAL_SYSCALL_DECL (err);
  struct stat64 st64;

  result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, &st64, flag);
  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
    return INLINE_SYSCALL_ERROR_RETURN_VALUE (-result);
  else
    return __xstat32_conv (vers, &st64, st);
}
Esempio n. 12
0
static int
do_fcntl (int fd, int cmd, void *arg)
{
  if (cmd != F_GETOWN)
    return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg);

  INTERNAL_SYSCALL_DECL (err);
  struct f_owner_ex fex;
  int res = INTERNAL_SYSCALL (fcntl, err, 3, fd, F_GETOWN_EX, &fex);
  if (!INTERNAL_SYSCALL_ERROR_P (res, err))
    return fex.type == F_OWNER_GID ? -fex.pid : fex.pid;

  return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (res,
								    err));
}
Esempio n. 13
0
int
setegid (gid_t gid)
{
  int result;

  if (gid == (gid_t) ~0)
    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);

#ifdef __NR_setresgid32
  result = INLINE_SETXID_SYSCALL (setresgid32, 3, -1, gid, -1);
#else
  result = INLINE_SETXID_SYSCALL (setresgid, 3, -1, gid, -1);
#endif

  return result;
}
Esempio n. 14
0
/* Change the access time of the file associated with FD to TVP[0] and
   the modification time of FILE to TVP[1].

   Starting with 2.6.22 the Linux kernel has the utimensat syscall which
   can be used to implement futimes.  */
int
__futimes (int fd, const struct timeval tvp[2])
{
  /* The utimensat system call expects timespec not timeval.  */
  struct timespec ts[2];
  if (tvp != NULL)
    {
      if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
          || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
	return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);

      TIMEVAL_TO_TIMESPEC (&tvp[0], &ts[0]);
      TIMEVAL_TO_TIMESPEC (&tvp[1], &ts[1]);
    }

  return INLINE_SYSCALL (utimensat, 4, fd, NULL, tvp ? &ts : NULL, 0);
}
Esempio n. 15
0
void *
shmat (int shmid, const void *shmaddr, int shmflg)
{
  INTERNAL_SYSCALL_DECL(err);
  unsigned long resultvar;
  void *raddr;

  resultvar = INTERNAL_SYSCALL (ipc, err, 5, IPCOP_shmat,
				shmid, shmflg,
				(long int) &raddr,
				(void *) shmaddr);
  if (INTERNAL_SYSCALL_ERROR_P (resultvar, err))
    return (void *) INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (resultvar,
									       err));

  return raddr;
}
Esempio n. 16
0
int
lutimes (const char *file, const struct timeval tvp[2])
{
  /* The system call espects timespec, not timeval.  */
  struct timespec ts[2];
  if (tvp != NULL)
    {
      if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
          || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
	return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);

      TIMEVAL_TO_TIMESPEC (&tvp[0], &ts[0]);
      TIMEVAL_TO_TIMESPEC (&tvp[1], &ts[1]);
    }

  return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, tvp ? ts : NULL,
			 AT_SYMLINK_NOFOLLOW);
}
Esempio n. 17
0
/* Get information about the file NAME in BUF.  */
int
__xstat (int vers, const char *name, struct stat *buf)
{
  if (vers == _STAT_VER_KERNEL)
    return INLINE_SYSCALL (stat, 2, name, buf);

#ifdef STAT_IS_KERNEL_STAT
  return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
#else
  struct kernel_stat kbuf;
  int result;

  result = INLINE_SYSCALL (stat, 2, name, &kbuf);
  if (result == 0)
    result = __xstat_conv (vers, &kbuf, buf);

  return result;
#endif
}
Esempio n. 18
0
/* Get information about the file NAME in BUF.  */
int
__lxstat (int vers, const char *name, struct stat *buf)
{
  int result;

  if (vers == _STAT_VER_KERNEL)
    return INLINE_SYSCALL (lstat, 2, name, (struct kernel_stat *) buf);

  {
    struct stat64 buf64;

    INTERNAL_SYSCALL_DECL (err);
    result = INTERNAL_SYSCALL (lstat64, err, 2, name, &buf64);
    if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
      return INLINE_SYSCALL_ERROR_RETURN_VALUE (-result);
    else
      return __xstat32_conv (vers, &buf64, buf);
  }
}
Esempio n. 19
0
/* Get information about the file FD in BUF.  */
int
__fxstat (int vers, int fd, struct stat *buf)
{
  int result;

  if (vers == _STAT_VER_KERNEL)
    return INLINE_SYSCALL (fstat, 2, fd, buf);

  {
    struct stat64 buf64;

    INTERNAL_SYSCALL_DECL (err);
    result = INTERNAL_SYSCALL (fstat64, err, 2, fd, &buf64);
    if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
      return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result,
									err));
    else
      return __xstat32_conv (vers, &buf64, buf);
  }
}
Esempio n. 20
0
LINKAGE int
ADJTIME (const struct TIMEVAL *itv, struct TIMEVAL *otv)
{
  struct TIMEX tntx;

  if (itv)
    {
      struct TIMEVAL tmp;

      /* We will do some check here. */
      tmp.tv_sec = itv->tv_sec + itv->tv_usec / 1000000L;
      tmp.tv_usec = itv->tv_usec % 1000000L;
      if (tmp.tv_sec > MAX_SEC || tmp.tv_sec < MIN_SEC)
	return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
      tntx.offset = tmp.tv_usec + tmp.tv_sec * 1000000L;
      tntx.modes = ADJ_OFFSET_SINGLESHOT;
    }
  else
    tntx.modes = ADJ_OFFSET_SS_READ;

  if (__glibc_unlikely (ADJTIMEX (&tntx) < 0))
    return -1;

  if (otv)
    {
      if (tntx.offset < 0)
	{
	  otv->tv_usec = -(-tntx.offset % 1000000);
	  otv->tv_sec  = -(-tntx.offset / 1000000);
	}
      else
	{
	  otv->tv_usec = tntx.offset % 1000000;
	  otv->tv_sec  = tntx.offset / 1000000;
	}
    }
  return 0;
}
Esempio n. 21
0
/* Get information about the file NAME in BUF.  */
int
__fxstatat (int vers, int fd, const char *file, struct stat *st, int flag)
{
  int result;
  INTERNAL_SYSCALL_DECL (err);
#ifdef STAT_IS_KERNEL_STAT
# define kst (*st)
#else
  struct kernel_stat kst;
#endif

  result = INTERNAL_SYSCALL (newfstatat, err, 4, fd, file, &kst, flag);
  if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1))
    {
#ifdef STAT_IS_KERNEL_STAT
      return 0;
#else
      return __xstat_conv (vers, &kst, st);
#endif
    }
  else
    return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result,
								      err));
}