From: Ryan Davis Date: 2006-08-15T11:31:42+09:00 Subject: Process.gid= fails on OS X - need feedback (sorry for repost, All I've added is a subject to attract eyes) I'm looking at Ticket # 5365 (Process.gid= fails on OS X) at: http://rubyforge.org/tracker/? func=detail&atid=1698&aid=5365&group_id=426 and am poking at process.c. There are some problems with either the implementation and/or the documentation for it. To summarize: 1) Documentation doesn't agree with implementation - might want to state only sets to egid. 2) setregid is not recommended for use. 3) rb_notimplemented used for a permissions error. 4) root can't set to anything but effective gid. We should let the system decide. #1: The doco states: Sets the group ID for this process. But the implementation only does a setgid if the desired gid is the effective gid. Given change_privilege, I think it is the doco that is wrong. Please confirm. #2/3: With regard to the implementation, it is preferring setregid over setegid/setgid, but my man page states (on both darwin and freebsd): The setregid() function was intended to allow swapping the real and effective group IDs in set-group-ID programs to temporarily relinquish the set-group-ID value. This function did not work correctly, and its purpose is now better served by the use of the setegid() function (see setuid(2)). When setting the real and effective group IDs to the same value, the standard setgid() function is preferred. So maybe we should prefer the following change: --- process.c 06 Aug 2006 16:10:26 -0700 1.92.2.33 +++ process.c 14 Aug 2006 12:19:16 -0700 @@ -2494,9 +2494,7 @@ check_gid_switch(); #if defined(HAVE_SETRESGID) && !defined(__CHECKER__) if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0); -#elif defined HAVE_SETREGID - if (setregid(gid, -1) < 0) rb_sys_fail(0); -#elif defined HAVE_SETRGID +#elif defined _WIN32 && !defined __CYGWIN__ && defined HAVE_SETRGID if (setrgid((GIDTYPE)gid) < 0) rb_sys_fail(0); #elif defined HAVE_SETGID { @@ -2504,7 +2502,7 @@ if (setgid(gid) < 0) rb_sys_fail(0); } else { - rb_notimplement(); + rb_raise(rb_eSecurityError, "gid (%d) is not equal to the effective group id", gid); } } #else Note also that I changed the rb_notimplemented to be a correct error message for the situation. #4: If the doco is fine and #gid= should be able to set the gid, then we should probably take out the effective gid check entirely and let the system call do it. The man page says that you should be able to set to whatever you want if you are root: [EPERM] The current process is not the super-user and a change other than changing the effective group-id to the real group-id was specified. But our implementation doesn't allow for that. This does: --- process.c 06 Aug 2006 16:10:26 -0700 1.92.2.33 +++ process.c 14 Aug 2006 12:20:52 -0700 @@ -2494,18 +2494,11 @@ check_gid_switch(); #if defined(HAVE_SETRESGID) && !defined(__CHECKER__) if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0); -#elif defined HAVE_SETREGID - if (setregid(gid, -1) < 0) rb_sys_fail(0); -#elif defined HAVE_SETRGID +#elif defined _WIN32 && !defined __CYGWIN__ && defined HAVE_SETRGID if (setrgid((GIDTYPE)gid) < 0) rb_sys_fail(0); #elif defined HAVE_SETGID { - if (getegid() == gid) { - if (setgid(gid) < 0) rb_sys_fail(0); - } - else { - rb_notimplement(); - } + if (setgid(gid) < 0) rb_sys_fail(0); } #else rb_notimplement(); Please tell me what you guys prefer and I'll get it tested and committed.