* process.c (has_privilege): New function.

(retry_fork_async_signal_safe): Don't use vfork() for privileged
  process.

* configure.in (getresuid): Check function.
  (getresgid): Ditto.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47386 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2014-09-04 14:56:03 +00:00
Родитель d80282eecc
Коммит f20d51b0ad
3 изменённых файлов: 81 добавлений и 1 удалений

Просмотреть файл

@ -1,3 +1,12 @@
Thu Sep 4 23:39:52 2014 Tanaka Akira <akr@fsij.org>
* process.c (has_privilege): New function.
(retry_fork_async_signal_safe): Don't use vfork() for privileged
process.
* configure.in (getresuid): Check function.
(getresgid): Ditto.
Thu Sep 4 20:22:14 2014 Laurent Arnoud <laurent@spkdev.net>
* test/pathname/test_pathname.rb: added testcase for Pathname#mountpoint.

Просмотреть файл

@ -1996,6 +1996,8 @@ AC_CHECK_FUNCS(getpgid)
AC_CHECK_FUNCS(getpgrp)
AC_CHECK_FUNCS(getpriority)
AC_CHECK_FUNCS(getpwnam_r)
AC_CHECK_FUNCS(getresgid)
AC_CHECK_FUNCS(getresuid)
AC_CHECK_FUNCS(getrlimit)
AC_CHECK_FUNCS(getsid)
AC_CHECK_FUNCS(gettimeofday) # for making ac_cv_func_gettimeofday

Просмотреть файл

@ -3277,6 +3277,72 @@ recv_child_error(int fd, int *errp, char *errmsg, size_t errmsg_buflen)
return size != 0;
}
static int
has_privilege(void)
{
/*
* has_privilege() is used to choose vfork() or fork().
*
* If the process has privilege, the parent process or
* the child process can change UID/GID.
* If vfork() is used to create the child process and
* the parent or child process change effective UID/GID,
* different privileged processes shares memory.
* It is a bad situation.
* So, fork() should be used.
*/
rb_uid_t ruid, euid;
rb_gid_t rgid, egid;
#if defined HAVE_ISSETUGID
if (issetugid())
return 1;
#endif
#ifdef HAVE_GETRESUID
{
int ret;
rb_uid_t suid;
ret = getresuid(&ruid, &euid, &suid);
if (ret == -1)
rb_sys_fail("getresuid(2)");
if (ruid != suid)
return 1;
}
#else
{
rb_uid_t ruid = getuid();
rb_uid_t euid = geteuid();
}
#endif
if (ruid == 0 || ruid != euid)
return 1;
#ifdef HAVE_GETRESGID
{
int ret;
rb_gid_t sgid;
ret = getresgid(&rgid, &egid, &sgid);
if (ret == -1)
rb_sys_fail("getresgid(2)");
if (rgid != sgid)
return 0;
}
#else
{
rb_gid_t rgid = getgid();
rb_gid_t egid = getegid();
}
#endif
if (rgid == 0 || rgid != egid)
return 1;
return 0;
}
static rb_pid_t
retry_fork_async_signal_safe(int *status, int *ep,
int (*chfunc)(void*, char *, size_t), void *charg,
@ -3289,7 +3355,10 @@ retry_fork_async_signal_safe(int *status, int *ep,
while (1) {
prefork();
#ifdef HAVE_WORKING_VFORK
pid = vfork();
if (!has_privilege())
pid = vfork();
else
pid = fork();
#else
pid = fork();
#endif