Skip to content

Commit

Permalink
Replace Ruby's setgid/setuid/initgroups with our own functions becaus…
Browse files Browse the repository at this point in the history
…e Ruby's are broken.
  • Loading branch information
FooBarWidget committed Apr 11, 2010
1 parent 2ed806b commit e6a1bc5
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 9 deletions.
25 changes: 25 additions & 0 deletions ext/phusion_passenger/native_support.c
Expand Up @@ -30,6 +30,7 @@
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <grp.h>
#ifdef __OpenBSD__
// OpenBSD needs this for 'struct iovec'. Apparently it isn't
// always included by unistd.h and sys/types.h.
Expand Down Expand Up @@ -286,6 +287,29 @@ disable_stdio_buffering() {
return Qnil;
}

/**
* Ruby's implementations of initgroups, setgid and setuid are broken various ways,
* sigh...
* Ruby's setgid and setuid can't handle negative UIDs and initgroups is just broken.
* Work around it by using our own implementation.
*/
static VALUE
switch_user(VALUE self, VALUE username, VALUE uid, VALUE gid) {
uid_t the_uid = NUM2LL(uid);
gid_t the_gid = NUM2LL(gid);

if (initgroups(RSTRING_PTR(username), the_gid) == -1) {
rb_sys_fail("initgroups");
}
if (setgid(the_gid) == -1) {
rb_sys_fail("setgid");
}
if (setuid(the_uid) == -1) {
rb_sys_fail("setuid");
}
return Qnil;
}

/***************************/

void
Expand All @@ -306,6 +330,7 @@ Init_native_support() {
rb_define_singleton_method(mNativeSupport, "accept", f_accept, 1);
rb_define_singleton_method(mNativeSupport, "close_all_file_descriptors", close_all_file_descriptors, 1);
rb_define_singleton_method(mNativeSupport, "disable_stdio_buffering", disable_stdio_buffering, 0);
rb_define_singleton_method(mNativeSupport, "switch_user", switch_user, 3);

/* The maximum length of a Unix socket path, including terminating null. */
rb_define_const(mNativeSupport, "UNIX_PATH_MAX", INT2NUM(sizeof(addr.sun_path)));
Expand Down
10 changes: 1 addition & 9 deletions lib/phusion_passenger/utils.rb
Expand Up @@ -425,15 +425,7 @@ def switch_to_user(user)
if uid == 0
return false
else
# Some systems are broken. initgroups can fail because of
# all kinds of stupid reasons. So we ignore any errors
# raised by initgroups.
begin
Process.groups = Process.initgroups(username, gid)
rescue
end
Process::Sys.setgid(gid)
Process::Sys.setuid(uid)
NativeSupport.switch_user(username, uid, gid)
ENV['HOME'] = pw.dir
return true
end
Expand Down

0 comments on commit e6a1bc5

Please sign in to comment.