diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-09-04 14:56:03 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-09-04 14:56:03 +0000 |
commit | f20d51b0adb640c9351b3025e6dda7843c3342aa (patch) | |
tree | dd5586bf5ac5f1177bba913e00b58acbaee17d48 | |
parent | d80282eecce4d2b6a7c3f419659d6e4d8eecb536 (diff) | |
download | ruby-f20d51b0adb640c9351b3025e6dda7843c3342aa.tar.gz |
* 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
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | process.c | 71 |
3 files changed, 81 insertions, 1 deletions
@@ -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. diff --git a/configure.in b/configure.in index 5bd006f865..9080ab7559 100644 --- a/configure.in +++ b/configure.in @@ -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 |