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 /process.c | |
parent | d80282eecce4d2b6a7c3f419659d6e4d8eecb536 (diff) |
* 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
Diffstat (limited to 'process.c')
-rw-r--r-- | process.c | 71 |
1 files changed, 70 insertions, 1 deletions
@@ -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 |