Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Process.euid= #1931

Merged
merged 5 commits into from

2 participants

@hosiawak
Collaborator

On Ubuntu 12.04 when I run the following as root (assuming user with id 1000 exists in the system):

Process.euid = 1000
Process.uid = 1000

I get:

Errno::EPERM: Operation not permitted
from Errno.handle at kernel/common/errno.rb:18
from Process::Sys.setuid at kernel/common/process.rb:492
from Process.uid= at kernel/common/process.rb:203
from { } in Object#irb_binding at (irb):2
from Rubinius::BlockEnvironment#call_on_instance at kernel/common/block_environment.rb:75

Works on MRI 1.8.7 on the same box.

@brixen brixen merged commit d70d3a2 into rubinius:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
57 kernel/common/process.rb
@@ -199,8 +199,31 @@ def self.ppid
end
def self.uid=(uid)
+ # the 4 rescue clauses below are needed
+ # until respond_to? can be used to query the implementation of methods attached via FFI
+ # atm respond_to returns true if a method is attached but not implemented on the platform
uid = Rubinius::Type.coerce_to uid, Integer, :to_int
- Process::Sys.setuid uid
+ begin
+ ret = FFI::Platform::POSIX.setresuid(uid, -1, -1)
+ rescue NotImplementedError
+ begin
+ ret = FFI::Platform::POSIX.setreuid(uid, -1)
+ rescue NotImplementedError
+ begin
+ ret = FFI::Platform::POSIX.setruid(uid)
+ rescue NotImplementedError
+ if Process.euid == uid
+ ret = FFI::Platform::POSIX.setuid(uid)
+ else
+ raise NotImplementedError
+ end
+ end
+ end
+ end
+
+ Errno.handle if ret == -1
+
+ uid
end
def self.gid=(gid)
@@ -209,8 +232,31 @@ def self.gid=(gid)
end
def self.euid=(uid)
+ # the 4 rescue clauses below are needed
+ # until respond_to? can be used to query the implementation of methods attached via FFI
+ # atm respond_to returns true if a method is attached but not implemented on the platform
uid = Rubinius::Type.coerce_to uid, Integer, :to_int
- Process::Sys.seteuid uid
+ begin
+ ret = FFI::Platform::POSIX.setresuid(-1, uid, -1)
+ rescue NotImplementedError
+ begin
+ ret = FFI::Platform::POSIX.setreuid(-1, uid)
+ rescue NotImplementedError
+ begin
+ ret = FFI::Platform::POSIX.seteuid(uid)
+ rescue NotImplementedError
+ if Process.uid == uid
+ ret = FFI::Platform::POSIX.setuid(uid)
+ else
+ raise NotImplementedError
+ end
+ end
+ end
+ end
+
+ Errno.handle if ret == -1
+
+ uid
end
def self.egid=(gid)
@@ -526,10 +572,11 @@ def setregid(rid, eid)
nil
end
- def setreuid(rid)
+ def setreuid(rid, eid)
rid = Rubinius::Type.coerce_to rid, Integer, :to_int
+ eid = Rubinius::Type.coerce_to eid, Integer, :to_int
- ret = FFI::Platform::POSIX.setreuid rid
+ ret = FFI::Platform::POSIX.setreuid rid, eid
Errno.handle if ret == -1
nil
end
@@ -544,7 +591,7 @@ def setresgid(rid, eid, sid)
nil
end
- def setresuid(rid, eig, sid)
+ def setresuid(rid, eid, sid)
rid = Rubinius::Type.coerce_to rid, Integer, :to_int
eid = Rubinius::Type.coerce_to eid, Integer, :to_int
sid = Rubinius::Type.coerce_to sid, Integer, :to_int
View
3  kernel/platform/posix.rb
@@ -72,6 +72,9 @@ module FFI::Platform::POSIX
attach_function :setregid, [:gid_t, :gid_t], :int
attach_function :setreuid, [:uid_t, :uid_t], :int
+ attach_function :setresgid, [:gid_t, :gid_t, :gid_t], :int
+ attach_function :setresuid, [:uid_t, :uid_t, :uid_t], :int
+
attach_function :getpriority, [:int, :id_t], :int
attach_function :setpriority, [:int, :id_t, :int], :int
View
37 spec/ruby/core/process/euid_spec.rb
@@ -15,5 +15,42 @@
end
describe "Process.euid=" do
+
+ platform_is_not :windows do
+ it "raises TypeError if not passed an int" do
+ lambda { Process.euid = "100"}.should raise_error(TypeError)
+ end
+
+ as_user do
+ it "raises Errno::ERPERM if run by a non superuser trying to set the superuser id" do
+ lambda { (Process.euid = 0)}.should raise_error(Errno::EPERM)
+ end
+ end
+
+ as_superuser do
+ describe "if run by a superuser" do
+ with_feature :fork do
+ it "sets the effective user id for the current process if run by a superuser" do
+ read, write = IO.pipe
+ pid = Process.fork do
+ begin
+ read.close
+ Process.euid = 1
+ write << Process.euid
+ write.close
+ rescue Exception => e
+ write << e << e.backtrace
+ end
+ Process.exit!
+ end
+ write.close
+ euid = read.gets
+ euid.should == "1"
+ end
+ end
+ end
+ end
+ end
+
it "needs to be reviewed for spec completeness"
end
View
56 spec/ruby/core/process/uid_spec.rb
@@ -18,5 +18,61 @@
end
describe "Process.uid=" do
+
+ platform_is_not :windows do
+ it "raises TypeError if not passed an int" do
+ lambda { Process.uid = "100"}.should raise_error(TypeError)
+ end
+
+ as_user do
+ it "raises Errno::ERPERM if run by a non privileged user trying to set the superuser id" do
+ lambda { (Process.uid = 0)}.should raise_error(Errno::EPERM)
+ end
+ end
+
+ as_superuser do
+ describe "if run by a superuser" do
+ with_feature :fork do
+ it "sets the real user id for the current process" do
+ read, write = IO.pipe
+ pid = Process.fork do
+ begin
+ read.close
+ Process.uid = 1
+ write << Process.uid
+ write.close
+ rescue Exception => e
+ write << e << e.backtrace
+ end
+ Process.exit!
+ end
+ write.close
+ uid = read.gets
+ uid.should == "1"
+ end
+
+ it "sets the real user id if preceded by Process.euid=id" do
+ read, write = IO.pipe
+ pid = Process.fork do
+ begin
+ read.close
+ Process.euid = 1
+ Process.uid = 1
+ write << Process.uid
+ write.close
+ rescue Exception => e
+ write << e << e.backtrace
+ end
+ Process.exit!
+ end
+ write.close
+ uid = read.gets
+ uid.should == "1"
+ end
+ end
+ end
+ end
+ end
+
it "needs to be reviewed for spec completeness"
end
Something went wrong with that request. Please try again.