ext/phusion_passenger/native_support.c in colouringcode-passenger-0.1 vs ext/phusion_passenger/native_support.c in colouringcode-passenger-0.2
- old
+ new
@@ -28,10 +28,11 @@
#include <sys/socket.h>
#include <stdio.h>
#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.
#include <sys/uio.h>
#endif
@@ -156,14 +157,18 @@
rb_sys_fail("Cannot read file descriptor with recvmsg()");
return Qnil;
}
control_header = CMSG_FIRSTHDR(&msg);
+ if (control_header == NULL) {
+ rb_raise(rb_eIOError, "No valid file descriptor received.");
+ return Qnil;
+ }
if (control_header->cmsg_len != EXPECTED_CMSG_LEN
|| control_header->cmsg_level != SOL_SOCKET
|| control_header->cmsg_type != SCM_RIGHTS) {
- rb_sys_fail("No valid file descriptor received.");
+ rb_raise(rb_eIOError, "No valid file descriptor received.");
return Qnil;
}
#if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
return INT2NUM(control_data.fd);
#else
@@ -280,10 +285,33 @@
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
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
Init_native_support() {
struct sockaddr_un addr;
@@ -300,9 +328,10 @@
rb_define_singleton_method(mNativeSupport, "recv_fd", recv_fd, 1);
rb_define_singleton_method(mNativeSupport, "create_unix_socket", create_unix_socket, 2);
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)));
}