diff options
author | Eric Wong <normalperson@yhbt.net> | 2009-11-04 08:10:48 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2009-11-04 00:27:47 -0800 |
commit | c81ed9a7e417e15b3c3e0ac500af52841b3f8575 (patch) | |
tree | 115e21a4434c9ef0732ea10fe37391f8dc4f5599 | |
parent | e5491062605d1d6bec1c43bfadb5e348c142df8d (diff) | |
download | unicorn-c81ed9a7e417e15b3c3e0ac500af52841b3f8575.tar.gz |
This must be called in the after_fork hook because there may be Ruby modules that'll allow things such as CPU affinity and scheduling class/priority to be set on a per-worker basis. So we give the user the ability to change users at any time during the after_fork hook.
-rw-r--r-- | lib/unicorn.rb | 26 | ||||
-rw-r--r-- | lib/unicorn/configurator.rb | 11 |
2 files changed, 27 insertions, 10 deletions
diff --git a/lib/unicorn.rb b/lib/unicorn.rb index 94be9d2..396b8e3 100644 --- a/lib/unicorn.rb +++ b/lib/unicorn.rb @@ -3,6 +3,7 @@ require 'fcntl' require 'unicorn/socket_helper' autoload :Rack, 'rack' +autoload :Etc, 'etc' # Unicorn module containing all of the classes (include C extensions) for running # a Unicorn web server. It contains a minimalist HTTP server with just enough @@ -117,6 +118,31 @@ module Unicorn def ==(other_nr) self.nr == other_nr end + + # Changes the worker process to the specified +user+ and +group+ + # This is only intended to be called from within the worker + # process from the +after_fork+ hook. This should be called in + # the +after_fork+ hook after any priviledged functions need to be + # run (e.g. to set per-worker CPU affinity, niceness, etc) + # + # Any and all errors raised within this method will be propagated + # directly back to the caller (usually the +after_fork+ hook. + # These errors commonly include ArgumentError for specifying an + # invalid user/group and Errno::EPERM for insufficient priviledges + def user(user, group = nil) + # we do not protect the caller, checking Process.euid == 0 is + # insufficient because modern systems have fine-grained + # capabilities. Let the caller handle any and all errors. + uid = Etc.getpwnam(user).uid + gid = Etc.getgrnam(group).gid if group + tmp.chown(uid, gid) + if gid && Process.egid != gid + Process.initgroups(user, gid) + Process::GID.change_privilege(gid) + end + Process.euid != uid and Process::UID.change_privilege(uid) + end + end # Creates a working server on host:port (strange things happen if diff --git a/lib/unicorn/configurator.rb b/lib/unicorn/configurator.rb index aee4605..dcbf39a 100644 --- a/lib/unicorn/configurator.rb +++ b/lib/unicorn/configurator.rb @@ -147,16 +147,7 @@ module Unicorn # # drop permissions to "www-data" in the worker # # generally there's no reason to start Unicorn as a priviledged user # # as it is not recommended to expose Unicorn to public clients. - # uid, gid = Process.euid, Process.egid - # user, group = 'www-data', 'www-data' - # target_uid = Etc.getpwnam(user).uid - # target_gid = Etc.getgrnam(group).gid - # worker.tmp.chown(target_uid, target_gid) - # if uid != target_uid || gid != target_gid - # Process.initgroups(user, target_gid) - # Process::GID.change_privilege(target_gid) - # Process::UID.change_privilege(target_uid) - # end + # worker.user('www-data', 'www-data') if Process.euid == 0 # end def after_fork(*args, &block) set_hook(:after_fork, block_given? ? block : args[0]) |