Skip to content

Instantly share code, notes, and snippets.

@eam
Created August 24, 2012 22:11
Show Gist options
  • Save eam/3456311 to your computer and use it in GitHub Desktop.
Save eam/3456311 to your computer and use it in GitHub Desktop.
require 'etc'
module Elvis
def Elvis.check_threads
if Thread.list.length != 1
raise "Elvis.run_as cannot be used with threads"
end
end
arch, os = RUBY_PLATFORM.split('-')
if os =~ /^darwin/
def Elvis.run_as(user)
check_threads
pw = Etc.getpwnam(user)
original_uid = Process.euid
original_gid = Process.egid
original_groups = Process.groups
begin
Process::Sys.setregid(pw.gid, pw.gid)
Process.initgroups(user, pw.gid)
Process::Sys.seteuid(pw.uid)
Process::Sys.setreuid(pw.uid, -1)
yield
ensure
Process::Sys.setreuid(original_uid, original_uid)
Process::Sys.setregid(original_gid, original_gid)
Process.groups = original_groups
end
end
elsif os == "linux"
def Elvis.run_as(user)
check_threads
pw = Etc.getpwnam(user)
original_uid = Process.euid
original_gid = Process.egid
original_groups = Process.groups
begin
Process::Sys.setresgid(pw.gid, pw.gid, -1)
Process.initgroups(user, pw.gid)
Process::Sys.setresuid(pw.uid, pw.uid, -1)
yield
ensure
Process::Sys.setresuid(original_uid, original_uid, -1)
Process::Sys.setresgid(original_gid, original_gid, -1)
Process.groups = original_groups
end
end
else
raise "unknown platform: #{RUBY_PLATFORM}. set*id() functions do not have reliable behavior between systems."
end
end
if __FILE__ == $0
print "Starting up as: "
system "id"
begin
Elvis.run_as(ARGV.first) {
print "inside block as: "
system "id"
}
ensure
print "outside block as: "
system "id"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment