Process::GID.change_privilege not changing groups properly?

Hello.

I am trying to use Process::GID.change_privilege to get a root process
to assume the full group permissions of a specified user. However, it
seems that the process does not assume the proper group permissions of
the new group.

Consider the following scenario (running on Linux Centos 5):

  • I have a normal user account ‘scott’ with UID = GID = 502. This user
    belongs to two groups (‘scott’ and ‘testdev’), which can be seen as
    follows:

[scott@localhost ~]$ irb
irb(main):001:0> groups
=> “scott testdev\n”
irb(main):002:0>

  • Now, when I run the ruby interpreter as root and attempt to switch to
    user 502, I get the following output:

[root@localhost ~]# irb
irb(main):001:0> groups
=> “root bin daemon sys adm disk wheel\n”
irb(main):002:0> Process::GID.change_privilege(502)
=> 502
irb(main):003:0> Process::UID.change_privilege(502)
=> 502
irb(main):004:0> groups
=> “scott root bin daemon sys adm disk wheel\n”
irb(main):005:0>

  • Notice here how the process has correctly assumed the privileges of
    group ‘scott’, but is missing the ‘testdev’ group.

  • Also, why does the process still have all the root user group
    privileges too? Should they not have been revoked?

Note: if I do the same thing using shell commands I get the correct
result as expected:

[root@localhost ~]# groups
root bin daemon sys adm disk wheel
[root@localhost ~]# su - scott
[scott@localhost ~]$ groups
scott testdev
[scott@localhost ~]$

Can anyone please explain why this doesn’t work as expected? How can I
achieve this desired outcome with ruby?

Thanks
Scott

On Sun, Jun 03, 2007 at 11:28:59PM +0900, Scott McNab wrote:

  • Notice here how the process has correctly assumed the privileges of
    group ‘scott’, but is missing the ‘testdev’ group.

Try using Process.initgroups

Note: if I do the same thing using shell commands I get the correct
result as expected:

[root@localhost ~]# groups
root bin daemon sys adm disk wheel
[root@localhost ~]# su - scott
[scott@localhost ~]$ groups
scott testdev
[scott@localhost ~]$

If you look at the source code to su, you’ll probably find it calls
initgroups() somewhere.

Regards,

Brian.

Brian C. wrote:

Try using Process.initgroups

Thanks Brian that fixed it!

If you look at the source code to su, you’ll probably find it calls
initgroups() somewhere.

Actually you were spot on. The source in su.c (in the coreutils package)
does exactly that:

/* Become the user and group(s) specified by PW. */

static void
change_identity (const struct passwd *pw)
{
#ifdef HAVE_INITGROUPS
errno = 0;
if (initgroups (pw->pw_name, pw->pw_gid) == -1)
error (EXIT_FAIL, errno, _(“cannot set groups”));
endgrent ();
#endif
if (setgid (pw->pw_gid))
error (EXIT_FAIL, errno, _(“cannot set group id”));
if (setuid (pw->pw_uid))
error (EXIT_FAIL, errno, _(“cannot set user id”));
}

Now, all we need is to get this fix incorporated into the Mongrel gem
source tree…

Regards
Scott