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.