Index: mojo/edk/system/core.cc |
diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc |
index 9a167acf69a9468f969b9f874611b210f8ccc05e..59bd543bcede502c243c8f9d7f05bf366e1cb2e0 100644 |
--- a/mojo/edk/system/core.cc |
+++ b/mojo/edk/system/core.cc |
@@ -90,25 +90,28 @@ Core::Core(embedder::PlatformSupport* platform_support) |
: platform_support_(platform_support), |
handle_table_(GetConfiguration().max_handle_table_size) {} |
-Core::~Core() { |
-} |
+Core::~Core() {} |
MojoHandle Core::AddHandle(Handle&& handle) { |
MutexLocker locker(&handle_table_mutex_); |
return handle_table_.AddHandle(std::move(handle)); |
} |
-MojoResult Core::GetDispatcher(MojoHandle handle, |
- RefPtr<Dispatcher>* dispatcher) { |
+MojoResult Core::GetHandle(MojoHandle handle, Handle* h) { |
if (handle == MOJO_HANDLE_INVALID) |
return MOJO_RESULT_INVALID_ARGUMENT; |
MutexLocker locker(&handle_table_mutex_); |
+ return handle_table_.GetHandle(handle, h); |
+} |
+ |
+MojoResult Core::GetDispatcher(MojoHandle handle, |
+ RefPtr<Dispatcher>* dispatcher) { |
Handle h; |
- MojoResult rv = handle_table_.GetHandle(handle, &h); |
- if (rv == MOJO_RESULT_OK) |
+ MojoResult result = GetHandle(handle, &h); |
+ if (result == MOJO_RESULT_OK) |
*dispatcher = std::move(h.dispatcher); |
- return rv; |
+ return result; |
} |
MojoResult Core::GetAndRemoveDispatcher(MojoHandle handle, |
@@ -118,17 +121,41 @@ MojoResult Core::GetAndRemoveDispatcher(MojoHandle handle, |
MutexLocker locker(&handle_table_mutex_); |
Handle h; |
- MojoResult rv = handle_table_.GetAndRemoveHandle(handle, &h); |
- if (rv == MOJO_RESULT_OK) |
+ MojoResult result = handle_table_.GetAndRemoveHandle(handle, &h); |
+ if (result == MOJO_RESULT_OK) |
*dispatcher = std::move(h.dispatcher); |
- return rv; |
+ return result; |
+} |
+ |
+MojoResult Core::GetDispatcherAndCheckRights( |
+ MojoHandle handle, |
+ MojoHandleRights required_handle_rights, |
+ EntrypointClass entrypoint_class, |
+ util::RefPtr<Dispatcher>* dispatcher) { |
+ if (handle == MOJO_HANDLE_INVALID) |
+ return MOJO_RESULT_INVALID_ARGUMENT; |
+ |
+ Handle h; |
+ MojoResult result = GetHandle(handle, &h); |
+ if (result != MOJO_RESULT_OK) |
+ return result; |
+ |
+ if ((h.rights & required_handle_rights) != required_handle_rights) { |
+ return h.dispatcher->SupportsEntrypointClass(entrypoint_class) |
+ ? MOJO_RESULT_PERMISSION_DENIED |
+ : MOJO_RESULT_INVALID_ARGUMENT; |
+ } |
+ |
+ *dispatcher = std::move(h.dispatcher); |
+ return MOJO_RESULT_OK; |
} |
MojoResult Core::AsyncWait(MojoHandle handle, |
MojoHandleSignals signals, |
const std::function<void(MojoResult)>& callback) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(handle, &dispatcher); |
+ MojoResult result = GetDispatcherAndCheckRights( |
+ handle, MOJO_HANDLE_RIGHT_NONE, EntrypointClass::NONE, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -265,7 +292,9 @@ MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, |
uint32_t num_handles, |
MojoWriteMessageFlags flags) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(message_pipe_handle, &dispatcher); |
+ MojoResult result = |
+ GetDispatcherAndCheckRights(message_pipe_handle, MOJO_HANDLE_RIGHT_WRITE, |
+ EntrypointClass::MESSAGE_PIPE, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -332,7 +361,9 @@ MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, |
UserPointer<uint32_t> num_handles, |
MojoReadMessageFlags flags) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(message_pipe_handle, &dispatcher); |
+ MojoResult result = |
+ GetDispatcherAndCheckRights(message_pipe_handle, MOJO_HANDLE_RIGHT_READ, |
+ EntrypointClass::MESSAGE_PIPE, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -423,7 +454,9 @@ MojoResult Core::SetDataPipeProducerOptions( |
MojoHandle data_pipe_producer_handle, |
UserPointer<const MojoDataPipeProducerOptions> options) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(data_pipe_producer_handle, &dispatcher); |
+ MojoResult result = GetDispatcherAndCheckRights( |
+ data_pipe_producer_handle, MOJO_HANDLE_RIGHT_WRITE, |
+ EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -435,7 +468,9 @@ MojoResult Core::GetDataPipeProducerOptions( |
UserPointer<MojoDataPipeProducerOptions> options, |
uint32_t options_num_bytes) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(data_pipe_producer_handle, &dispatcher); |
+ MojoResult result = GetDispatcherAndCheckRights( |
+ data_pipe_producer_handle, MOJO_HANDLE_RIGHT_READ, |
+ EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -447,7 +482,9 @@ MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle, |
UserPointer<uint32_t> num_bytes, |
MojoWriteDataFlags flags) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(data_pipe_producer_handle, &dispatcher); |
+ MojoResult result = GetDispatcherAndCheckRights( |
+ data_pipe_producer_handle, MOJO_HANDLE_RIGHT_WRITE, |
+ EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -459,7 +496,9 @@ MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle, |
UserPointer<uint32_t> buffer_num_bytes, |
MojoWriteDataFlags flags) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(data_pipe_producer_handle, &dispatcher); |
+ MojoResult result = GetDispatcherAndCheckRights( |
+ data_pipe_producer_handle, MOJO_HANDLE_RIGHT_WRITE, |
+ EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -469,7 +508,9 @@ MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle, |
MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle, |
uint32_t num_bytes_written) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(data_pipe_producer_handle, &dispatcher); |
+ MojoResult result = GetDispatcherAndCheckRights( |
+ data_pipe_producer_handle, MOJO_HANDLE_RIGHT_WRITE, |
+ EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -480,7 +521,9 @@ MojoResult Core::SetDataPipeConsumerOptions( |
MojoHandle data_pipe_consumer_handle, |
UserPointer<const MojoDataPipeConsumerOptions> options) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(data_pipe_consumer_handle, &dispatcher); |
+ MojoResult result = GetDispatcherAndCheckRights( |
+ data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_WRITE, |
+ EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -492,7 +535,9 @@ MojoResult Core::GetDataPipeConsumerOptions( |
UserPointer<MojoDataPipeConsumerOptions> options, |
uint32_t options_num_bytes) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(data_pipe_consumer_handle, &dispatcher); |
+ MojoResult result = GetDispatcherAndCheckRights( |
+ data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_READ, |
+ EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -504,7 +549,9 @@ MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle, |
UserPointer<uint32_t> num_bytes, |
MojoReadDataFlags flags) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(data_pipe_consumer_handle, &dispatcher); |
+ MojoResult result = GetDispatcherAndCheckRights( |
+ data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_READ, |
+ EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -516,7 +563,9 @@ MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle, |
UserPointer<uint32_t> buffer_num_bytes, |
MojoReadDataFlags flags) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(data_pipe_consumer_handle, &dispatcher); |
+ MojoResult result = GetDispatcherAndCheckRights( |
+ data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_READ, |
+ EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -526,7 +575,9 @@ MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle, |
MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle, |
uint32_t num_bytes_read) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(data_pipe_consumer_handle, &dispatcher); |
+ MojoResult result = GetDispatcherAndCheckRights( |
+ data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_READ, |
+ EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -566,20 +617,26 @@ MojoResult Core::DuplicateBufferHandle( |
MojoHandle buffer_handle, |
UserPointer<const MojoDuplicateBufferHandleOptions> options, |
UserPointer<MojoHandle> new_buffer_handle) { |
- RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(buffer_handle, &dispatcher); |
+ // TODO(vtl): This is a big ugly and duplicates some code, but the plan is to |
+ // remove this method anyway. |
+ Handle h; |
+ MojoResult result = GetHandle(buffer_handle, &h); |
if (result != MOJO_RESULT_OK) |
return result; |
+ if (!(h.rights & MOJO_HANDLE_RIGHT_DUPLICATE)) { |
+ return h.dispatcher->SupportsEntrypointClass(EntrypointClass::BUFFER) |
+ ? MOJO_RESULT_PERMISSION_DENIED |
+ : MOJO_RESULT_INVALID_ARGUMENT; |
+ } |
+ |
// Don't verify |options| here; that's the dispatcher's job. |
RefPtr<Dispatcher> new_dispatcher; |
- result = dispatcher->DuplicateBufferHandle(options, &new_dispatcher); |
+ result = h.dispatcher->DuplicateBufferHandle(options, &new_dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
- // TODO(vtl): This should be done with the original handle's rights. |
- MojoHandle new_handle = AddHandle(Handle( |
- new_dispatcher.Clone(), SharedBufferDispatcher::kDefaultHandleRights)); |
+ MojoHandle new_handle = AddHandle(Handle(new_dispatcher.Clone(), h.rights)); |
if (new_handle == MOJO_HANDLE_INVALID) { |
LOG(ERROR) << "Handle table full"; |
new_dispatcher->Close(); |
@@ -594,7 +651,9 @@ MojoResult Core::GetBufferInformation(MojoHandle buffer_handle, |
UserPointer<MojoBufferInformation> info, |
uint32_t info_num_bytes) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(buffer_handle, &dispatcher); |
+ MojoResult result = |
+ GetDispatcherAndCheckRights(buffer_handle, MOJO_HANDLE_RIGHT_READ, |
+ EntrypointClass::BUFFER, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |
@@ -607,7 +666,11 @@ MojoResult Core::MapBuffer(MojoHandle buffer_handle, |
UserPointer<void*> buffer, |
MojoMapBufferFlags flags) { |
RefPtr<Dispatcher> dispatcher; |
- MojoResult result = GetDispatcher(buffer_handle, &dispatcher); |
+ // TODO(vtl): Is this right? Or should there be a "map" right? Probably I need |
+ // to rethink rights for buffers. |
+ MojoResult result = |
+ GetDispatcherAndCheckRights(buffer_handle, MOJO_HANDLE_RIGHT_WRITE, |
+ EntrypointClass::BUFFER, &dispatcher); |
if (result != MOJO_RESULT_OK) |
return result; |