Skip to content

Commit

Permalink
Showing 6 changed files with 150 additions and 7 deletions.
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/process/euid_tags.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
fails:Process.euid= raises TypeError if not passed an Integer
fails:Process.euid= raises Errno::ERPERM if run by a non superuser trying to set the superuser id
fails:Process.euid= raises Errno::ERPERM if run by a non superuser trying to set the superuser id from username
3 changes: 0 additions & 3 deletions spec/truffle/tags/core/process/uid_tags.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
fails:Process.uid also goes by Process::UID.rid
fails:Process.uid also goes by Process::Sys.getuid
fails:Process.uid= raises TypeError if not passed an Integer
fails:Process.uid= raises Errno::ERPERM if run by a non privileged user trying to set the superuser id
fails:Process.uid= raises Errno::ERPERM if run by a non privileged user trying to set the superuser id from username
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ public abstract class ExceptionPrimitiveNodes {
public static abstract class ExceptionErrnoErrorPrimitiveNode extends RubiniusPrimitiveNode {

// If you add a constant here, add it below in isExceptionSupported() too.
protected final static int EPERM = Errno.EPERM.intValue();
protected final static int ENOENT = Errno.ENOENT.intValue();
protected final static int EBADF = Errno.EBADF.intValue();
protected final static int EEXIST = Errno.EEXIST.intValue();
@@ -37,13 +38,23 @@ public static abstract class ExceptionErrnoErrorPrimitiveNode extends RubiniusPr
protected final static int ENOTDIR = Errno.ENOTDIR.intValue();

public static boolean isExceptionSupported(int errno) {
return errno == ENOENT || errno == EBADF || errno == EEXIST || errno == EACCES || errno == EFAULT || errno == ENOTDIR;
return errno == EPERM || errno == ENOENT || errno == EBADF || errno == EEXIST || errno == EACCES || errno == EFAULT || errno == ENOTDIR;
}

public ExceptionErrnoErrorPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization(guards = "errno == EPERM")
public RubyException eperm(RubyString message, int errno) {
return getContext().getCoreLibrary().operationNotPermittedError(message.toString(), this);
}

@Specialization(guards = {"errno == EPERM", "isNil(message)"})
public RubyException eperm(Object message, int errno) {
return getContext().getCoreLibrary().operationNotPermittedError("nil", this);
}

@Specialization(guards = "errno == ENOENT")
public RubyException enoent(RubyString message, int errno) {
return getContext().getCoreLibrary().fileNotFoundError(message.toString(), this);
Original file line number Diff line number Diff line change
@@ -365,6 +365,76 @@ public int setpriority(int kind, int id, int priority) {

}

@CoreMethod(names = "setresuid", isModuleFunction = true, required = 3, lowerFixnumParameters = {0, 1, 2})
public abstract static class SetResuidNode extends CoreMethodArrayArgumentsNode {

public SetResuidNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization
public int setresuid(int uid, int id, int priority) {
throw new RaiseException(getContext().getCoreLibrary().notImplementedError("setresuid", this));
}

}

@CoreMethod(names = "seteuid", isModuleFunction = true, required = 1, lowerFixnumParameters = 0)
public abstract static class SetEuidNode extends CoreMethodArrayArgumentsNode {

public SetEuidNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization
public int seteuid(int uid) {
return posix().seteuid(uid);
}

}

@CoreMethod(names = "setreuid", isModuleFunction = true, required = 2, lowerFixnumParameters = {0, 1})
public abstract static class SetReuidNode extends CoreMethodArrayArgumentsNode {

public SetReuidNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization
public int setreuid(int uid, int id) {
throw new RaiseException(getContext().getCoreLibrary().notImplementedError("setreuid", this));
}

}

@CoreMethod(names = "setruid", isModuleFunction = true, required = 1, lowerFixnumParameters = 0)
public abstract static class SetRuidNode extends CoreMethodArrayArgumentsNode {

public SetRuidNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization
public int setruid(int uid) {
throw new RaiseException(getContext().getCoreLibrary().notImplementedError("setruid", this));
}

}

@CoreMethod(names = "setuid", isModuleFunction = true, required = 1, lowerFixnumParameters = 0)
public abstract static class SetUidNode extends CoreMethodArrayArgumentsNode {

public SetUidNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization
public int setuid(int uid) {
return posix().setuid(uid);
}

}

@CoreMethod(names = "flock", isModuleFunction = true, required = 2, lowerFixnumParameters = {0, 1})
public abstract static class FlockNode extends CoreMethodArrayArgumentsNode {

Original file line number Diff line number Diff line change
@@ -94,6 +94,7 @@ public class CoreLibrary {
private final RubyClass nameErrorClass;
private final RubyClass nilClass;
private final RubyClass noMethodErrorClass;
private final RubyClass notImplementedErrorClass;
private final RubyClass numericClass;
private final RubyClass objectClass;
private final RubyClass procClass;
@@ -270,7 +271,7 @@ public CoreLibrary(RubyContext context) {
// ScriptError
RubyClass scriptErrorClass = defineClass(exceptionClass, "ScriptError");
loadErrorClass = defineClass(scriptErrorClass, "LoadError");
defineClass(scriptErrorClass, "NotImplementedError");
notImplementedErrorClass = defineClass(scriptErrorClass, "NotImplementedError");
syntaxErrorClass = defineClass(scriptErrorClass, "SyntaxError");

// SecurityError
@@ -1014,6 +1015,11 @@ public RubyException zeroDivisionError(Node currentNode) {
return new RubyException(context.getCoreLibrary().getZeroDivisionErrorClass(), context.makeString("divided by 0"), RubyCallStack.getBacktrace(currentNode));
}

public RubyException notImplementedError(String message, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return new RubyException(notImplementedErrorClass, context.makeString(String.format("Method %s not implemented", message)), RubyCallStack.getBacktrace(currentNode));
}

public RubyException syntaxError(String message, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return new RubyException(syntaxErrorClass, context.makeString(message), RubyCallStack.getBacktrace(currentNode));
@@ -1065,6 +1071,11 @@ public RubyException dirNotEmptyError(String path, Node currentNode) {
return new RubyException(getErrnoClass(Errno.ENOTEMPTY), context.makeString(String.format("Directory not empty - %s", path)), RubyCallStack.getBacktrace(currentNode));
}

public RubyException operationNotPermittedError(String path, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return new RubyException(getErrnoClass(Errno.EPERM), context.makeString(String.format("Operation not permitted - %s", path)), RubyCallStack.getBacktrace(currentNode));
}

public RubyException permissionDeniedError(String path, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return new RubyException(getErrnoClass(Errno.EACCES), context.makeString(String.format("Permission denied - %s", path)), RubyCallStack.getBacktrace(currentNode));
56 changes: 56 additions & 0 deletions truffle/src/main/ruby/core/rubinius/common/process.rb
Original file line number Diff line number Diff line change
@@ -90,6 +90,62 @@ def self.getpgrp
ret
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
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.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
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.uid
ret = FFI::Platform::POSIX.getuid
Errno.handle if ret == -1

0 comments on commit 7831586

Please sign in to comment.