Add thunks for MojoGetRights(), etc.

I.e., this makes MojoGetRights() to apps.

R=azani@chromium.org

Review URL: https://codereview.chromium.org/1993283002 .
diff --git a/mojo/edk/embedder/entrypoints.cc b/mojo/edk/embedder/entrypoints.cc
index 44c1e22..b500f6b 100644
--- a/mojo/edk/embedder/entrypoints.cc
+++ b/mojo/edk/embedder/entrypoints.cc
@@ -27,6 +27,10 @@
   return g_core->Close(handle);
 }
 
+MojoResult MojoGetRights(MojoHandle handle, MojoHandleRights* rights) {
+  return g_core->GetRights(handle, MakeUserPointer(rights));
+}
+
 MojoResult MojoWait(MojoHandle handle,
                     MojoHandleSignals signals,
                     MojoDeadline deadline,
diff --git a/mojo/edk/embedder/system_impl_private_entrypoints.cc b/mojo/edk/embedder/system_impl_private_entrypoints.cc
index f35c91f..0f1b18d 100644
--- a/mojo/edk/embedder/system_impl_private_entrypoints.cc
+++ b/mojo/edk/embedder/system_impl_private_entrypoints.cc
@@ -92,6 +92,14 @@
   return core->Close(handle);
 }
 
+MojoResult MojoSystemImplGetRights(MojoSystemImpl system,
+                                   MojoHandle handle,
+                                   MojoHandleRights* rights) {
+  mojo::system::Core* core = static_cast<mojo::system::Core*>(system);
+  DCHECK(core);
+  return core->GetRights(handle, MakeUserPointer(rights));
+}
+
 MojoResult MojoSystemImplWait(MojoSystemImpl system,
                               MojoHandle handle,
                               MojoHandleSignals signals,
diff --git a/mojo/edk/system/core_unittest.cc b/mojo/edk/system/core_unittest.cc
index 745b5af..c91ef7b 100644
--- a/mojo/edk/system/core_unittest.cc
+++ b/mojo/edk/system/core_unittest.cc
@@ -20,6 +20,17 @@
 namespace system {
 namespace {
 
+const MojoHandleRights kDefaultMessagePipeHandleRights =
+    MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ |
+    MOJO_HANDLE_RIGHT_WRITE | MOJO_HANDLE_RIGHT_GET_OPTIONS |
+    MOJO_HANDLE_RIGHT_SET_OPTIONS;
+const MojoHandleRights kDefaultDataPipeProducerHandleRights =
+    MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_WRITE |
+    MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS;
+const MojoHandleRights kDefaultDataPipeConsumerHandleRights =
+    MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ |
+    MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS;
+
 const MojoHandleSignalsState kEmptyMojoHandleSignalsState = {0u, 0u};
 const MojoHandleSignalsState kFullMojoHandleSignalsState = {~0u, ~0u};
 
@@ -44,7 +55,7 @@
   EXPECT_EQ(1u, info.GetCtorCallCount());
   EXPECT_NE(h, MOJO_HANDLE_INVALID);
 
-  MojoHandleRights rights = 0;
+  MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE;
   EXPECT_EQ(MOJO_RESULT_OK, core()->GetRights(h, MakeUserPointer(&rights)));
   EXPECT_EQ(kDefaultMockHandleRights, rights);
 
@@ -210,7 +221,7 @@
 
   // |GetRights()|:
   {
-    MojoHandleRights rights = 0;
+    MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE;
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
               core()->GetRights(MOJO_HANDLE_INVALID, MakeUserPointer(&rights)));
     EXPECT_EQ(0u, rights);
@@ -670,16 +681,12 @@
   EXPECT_NE(h[0], h[1]);
 
   // Both should have the correct rights.
-  static const MojoHandleRights kMessagePipeHandleRights =
-      MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ |
-      MOJO_HANDLE_RIGHT_WRITE | MOJO_HANDLE_RIGHT_GET_OPTIONS |
-      MOJO_HANDLE_RIGHT_SET_OPTIONS;
   MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE;
   EXPECT_EQ(MOJO_RESULT_OK, core()->GetRights(h[0], MakeUserPointer(&rights)));
-  EXPECT_EQ(kMessagePipeHandleRights, rights);
+  EXPECT_EQ(kDefaultMessagePipeHandleRights, rights);
   rights = MOJO_HANDLE_RIGHT_NONE;
   EXPECT_EQ(MOJO_RESULT_OK, core()->GetRights(h[1], MakeUserPointer(&rights)));
-  EXPECT_EQ(kMessagePipeHandleRights, rights);
+  EXPECT_EQ(kDefaultMessagePipeHandleRights, rights);
 
   // Neither should be readable.
   MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_READABLE,
@@ -981,6 +988,12 @@
   // fails. See above note.
   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(h_passed[1]));
 
+  // Check that |h_received| still has the expected rights.
+  MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            core()->GetRights(h_received, MakeUserPointer(&rights)));
+  EXPECT_EQ(kDefaultMessagePipeHandleRights, rights);
+
   // Write to |h_passed[0]|. Should receive on |h_received|.
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->WriteMessage(h_passed[0], UserPointer<const void>(kHello),
@@ -1027,18 +1040,12 @@
   EXPECT_NE(ph, ch);
 
   // Both should have the correct rights.
-  static const MojoHandleRights kDataPipeProducerHandleRights =
-      MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_WRITE |
-      MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS;
-  static const MojoHandleRights kDataPipeConsumerHandleRights =
-      MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ |
-      MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS;
   MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE;
   EXPECT_EQ(MOJO_RESULT_OK, core()->GetRights(ph, MakeUserPointer(&rights)));
-  EXPECT_EQ(kDataPipeProducerHandleRights, rights);
+  EXPECT_EQ(kDefaultDataPipeProducerHandleRights, rights);
   rights = MOJO_HANDLE_RIGHT_NONE;
   EXPECT_EQ(MOJO_RESULT_OK, core()->GetRights(ch, MakeUserPointer(&rights)));
-  EXPECT_EQ(kDataPipeConsumerHandleRights, rights);
+  EXPECT_EQ(kDefaultDataPipeConsumerHandleRights, rights);
 
   // Producer should be never-readable, but already writable.
   hss = kEmptyMojoHandleSignalsState;
@@ -1464,6 +1471,12 @@
   // above note.
   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(ch));
 
+  // Check that |ch_received| still has the expected rights.
+  MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            core()->GetRights(ch_received, MakeUserPointer(&rights)));
+  EXPECT_EQ(kDefaultDataPipeConsumerHandleRights, rights);
+
   // Write to |ph|. Should receive on |ch_received|.
   num_bytes = kWorldSize;
   EXPECT_EQ(MOJO_RESULT_OK,
@@ -1524,6 +1537,12 @@
   // above note.
   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(ph));
 
+  // Check that |ph_received| still has the expected rights.
+  rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            core()->GetRights(ph_received, MakeUserPointer(&rights)));
+  EXPECT_EQ(kDefaultDataPipeProducerHandleRights, rights);
+
   // Write to |ph_received|. Should receive on |ch_received|.
   num_bytes = kHelloSize;
   EXPECT_EQ(MOJO_RESULT_OK,
diff --git a/mojo/nacl/nonsfi/irt_mojo_nonsfi.cc b/mojo/nacl/nonsfi/irt_mojo_nonsfi.cc
index 02ed73b..7ccdc84 100644
--- a/mojo/nacl/nonsfi/irt_mojo_nonsfi.cc
+++ b/mojo/nacl/nonsfi/irt_mojo_nonsfi.cc
@@ -24,6 +24,7 @@
     nacl::MojoGetInitialHandle,
     MojoGetTimeTicksNow,
     MojoClose,
+    MojoGetRights,
     MojoWait,
     MojoWaitMany,
     MojoCreateMessagePipe,
diff --git a/mojo/nacl/sfi/nacl_bindings/mojo_irt.c b/mojo/nacl/sfi/nacl_bindings/mojo_irt.c
index 4da9e63..41c8c49 100644
--- a/mojo/nacl/sfi/nacl_bindings/mojo_irt.c
+++ b/mojo/nacl/sfi/nacl_bindings/mojo_irt.c
@@ -57,6 +57,19 @@
   return result;
 };
 
+static MojoResult irt_MojoGetRights(
+    MojoHandle handle,
+    MojoHandleRights* rights) {
+  uint32_t params[4];
+  MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
+  params[0] = 3;
+  params[1] = (uint32_t)(&handle);
+  params[2] = (uint32_t)(rights);
+  params[3] = (uint32_t)(&result);
+  DoMojoCall(params, sizeof(params));
+  return result;
+};
+
 static MojoResult irt_MojoWait(
     MojoHandle handle,
     MojoHandleSignals signals,
@@ -64,7 +77,7 @@
     struct MojoHandleSignalsState* signals_state) {
   uint32_t params[6];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 3;
+  params[0] = 4;
   params[1] = (uint32_t)(&handle);
   params[2] = (uint32_t)(&signals);
   params[3] = (uint32_t)(&deadline);
@@ -83,7 +96,7 @@
     struct MojoHandleSignalsState* signals_states) {
   uint32_t params[8];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 4;
+  params[0] = 5;
   params[1] = (uint32_t)(handles);
   params[2] = (uint32_t)(signals);
   params[3] = (uint32_t)(&num_handles);
@@ -101,7 +114,7 @@
     MojoHandle* message_pipe_handle1) {
   uint32_t params[5];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 5;
+  params[0] = 6;
   params[1] = (uint32_t)(options);
   params[2] = (uint32_t)(message_pipe_handle0);
   params[3] = (uint32_t)(message_pipe_handle1);
@@ -119,7 +132,7 @@
     MojoWriteMessageFlags flags) {
   uint32_t params[8];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 6;
+  params[0] = 7;
   params[1] = (uint32_t)(&message_pipe_handle);
   params[2] = (uint32_t)(bytes);
   params[3] = (uint32_t)(&num_bytes);
@@ -140,7 +153,7 @@
     MojoReadMessageFlags flags) {
   uint32_t params[8];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 7;
+  params[0] = 8;
   params[1] = (uint32_t)(&message_pipe_handle);
   params[2] = (uint32_t)(bytes);
   params[3] = (uint32_t)(num_bytes);
@@ -158,7 +171,7 @@
     MojoHandle* data_pipe_consumer_handle) {
   uint32_t params[5];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 8;
+  params[0] = 9;
   params[1] = (uint32_t)(options);
   params[2] = (uint32_t)(data_pipe_producer_handle);
   params[3] = (uint32_t)(data_pipe_consumer_handle);
@@ -172,7 +185,7 @@
     const struct MojoDataPipeProducerOptions* options) {
   uint32_t params[4];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 9;
+  params[0] = 10;
   params[1] = (uint32_t)(&data_pipe_producer_handle);
   params[2] = (uint32_t)(options);
   params[3] = (uint32_t)(&result);
@@ -186,7 +199,7 @@
     uint32_t options_num_bytes) {
   uint32_t params[5];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 10;
+  params[0] = 11;
   params[1] = (uint32_t)(&data_pipe_producer_handle);
   params[2] = (uint32_t)(options);
   params[3] = (uint32_t)(&options_num_bytes);
@@ -202,7 +215,7 @@
     MojoWriteDataFlags flags) {
   uint32_t params[6];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 11;
+  params[0] = 12;
   params[1] = (uint32_t)(&data_pipe_producer_handle);
   params[2] = (uint32_t)(elements);
   params[3] = (uint32_t)(num_bytes);
@@ -219,7 +232,7 @@
     MojoWriteDataFlags flags) {
   uint32_t params[6];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 12;
+  params[0] = 13;
   params[1] = (uint32_t)(&data_pipe_producer_handle);
   params[2] = (uint32_t)(buffer);
   params[3] = (uint32_t)(buffer_num_bytes);
@@ -234,7 +247,7 @@
     uint32_t num_bytes_written) {
   uint32_t params[4];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 13;
+  params[0] = 14;
   params[1] = (uint32_t)(&data_pipe_producer_handle);
   params[2] = (uint32_t)(&num_bytes_written);
   params[3] = (uint32_t)(&result);
@@ -247,7 +260,7 @@
     const struct MojoDataPipeConsumerOptions* options) {
   uint32_t params[4];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 14;
+  params[0] = 15;
   params[1] = (uint32_t)(&data_pipe_consumer_handle);
   params[2] = (uint32_t)(options);
   params[3] = (uint32_t)(&result);
@@ -261,7 +274,7 @@
     uint32_t options_num_bytes) {
   uint32_t params[5];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 15;
+  params[0] = 16;
   params[1] = (uint32_t)(&data_pipe_consumer_handle);
   params[2] = (uint32_t)(options);
   params[3] = (uint32_t)(&options_num_bytes);
@@ -277,7 +290,7 @@
     MojoReadDataFlags flags) {
   uint32_t params[6];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 16;
+  params[0] = 17;
   params[1] = (uint32_t)(&data_pipe_consumer_handle);
   params[2] = (uint32_t)(elements);
   params[3] = (uint32_t)(num_bytes);
@@ -294,7 +307,7 @@
     MojoReadDataFlags flags) {
   uint32_t params[6];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 17;
+  params[0] = 18;
   params[1] = (uint32_t)(&data_pipe_consumer_handle);
   params[2] = (uint32_t)(buffer);
   params[3] = (uint32_t)(buffer_num_bytes);
@@ -309,7 +322,7 @@
     uint32_t num_bytes_read) {
   uint32_t params[4];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 18;
+  params[0] = 19;
   params[1] = (uint32_t)(&data_pipe_consumer_handle);
   params[2] = (uint32_t)(&num_bytes_read);
   params[3] = (uint32_t)(&result);
@@ -323,7 +336,7 @@
     MojoHandle* shared_buffer_handle) {
   uint32_t params[5];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 19;
+  params[0] = 20;
   params[1] = (uint32_t)(options);
   params[2] = (uint32_t)(&num_bytes);
   params[3] = (uint32_t)(shared_buffer_handle);
@@ -338,7 +351,7 @@
     MojoHandle* new_buffer_handle) {
   uint32_t params[5];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 20;
+  params[0] = 21;
   params[1] = (uint32_t)(&buffer_handle);
   params[2] = (uint32_t)(options);
   params[3] = (uint32_t)(new_buffer_handle);
@@ -353,7 +366,7 @@
     uint32_t info_num_bytes) {
   uint32_t params[5];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 21;
+  params[0] = 22;
   params[1] = (uint32_t)(&buffer_handle);
   params[2] = (uint32_t)(info);
   params[3] = (uint32_t)(&info_num_bytes);
@@ -370,7 +383,7 @@
     MojoMapBufferFlags flags) {
   uint32_t params[7];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 22;
+  params[0] = 23;
   params[1] = (uint32_t)(&buffer_handle);
   params[2] = (uint32_t)(&offset);
   params[3] = (uint32_t)(&num_bytes);
@@ -384,7 +397,7 @@
 static MojoResult irt_MojoUnmapBuffer(void* buffer) {
   uint32_t params[3];
   MojoResult result = MOJO_RESULT_INVALID_ARGUMENT;
-  params[0] = 23;
+  params[0] = 24;
   params[1] = (uint32_t)(&buffer);
   params[2] = (uint32_t)(&result);
   DoMojoCall(params, sizeof(params));
@@ -395,6 +408,7 @@
   &irt__MojoGetInitialHandle,
   &irt_MojoGetTimeTicksNow,
   &irt_MojoClose,
+  &irt_MojoGetRights,
   &irt_MojoWait,
   &irt_MojoWaitMany,
   &irt_MojoCreateMessagePipe,
diff --git a/mojo/nacl/sfi/nacl_bindings/mojo_syscall.cc b/mojo/nacl/sfi/nacl_bindings/mojo_syscall.cc
index 21b2110..cbc89d8 100644
--- a/mojo/nacl/sfi/nacl_bindings/mojo_syscall.cc
+++ b/mojo/nacl/sfi/nacl_bindings/mojo_syscall.cc
@@ -130,6 +130,40 @@
       return 0;
     }
     case 3: {
+      if (num_params != 4) {
+        return -1;
+      }
+      MojoHandle handle_value;
+      MojoHandleRights volatile* rights_ptr;
+      MojoHandleRights rights_value;
+      MojoResult volatile* result_ptr;
+      MojoResult result_value;
+      {
+        ScopedCopyLock copy_lock(nap);
+        if (!ConvertScalarInput(nap, params[1], &handle_value)) {
+          return -1;
+        }
+        if (!ConvertScalarInOut(nap, params[2], false, &rights_value,
+                                &rights_ptr)) {
+          return -1;
+        }
+        if (!ConvertScalarOutput(nap, params[3], false, &result_ptr)) {
+          return -1;
+        }
+      }
+
+      result_value =
+          MojoSystemImplGetRights(g_mojo_system, handle_value, &rights_value);
+
+      {
+        ScopedCopyLock copy_lock(nap);
+        *rights_ptr = rights_value;
+        *result_ptr = result_value;
+      }
+
+      return 0;
+    }
+    case 4: {
       if (num_params != 6) {
         return -1;
       }
@@ -174,7 +208,7 @@
 
       return 0;
     }
-    case 4: {
+    case 5: {
       if (num_params != 8) {
         return -1;
       }
@@ -230,7 +264,7 @@
 
       return 0;
     }
-    case 5: {
+    case 6: {
       if (num_params != 5) {
         return -1;
       }
@@ -274,7 +308,7 @@
 
       return 0;
     }
-    case 6: {
+    case 7: {
       if (num_params != 8) {
         return -1;
       }
@@ -323,7 +357,7 @@
 
       return 0;
     }
-    case 7: {
+    case 8: {
       if (num_params != 8) {
         return -1;
       }
@@ -383,7 +417,7 @@
 
       return 0;
     }
-    case 8: {
+    case 9: {
       if (num_params != 5) {
         return -1;
       }
@@ -427,7 +461,7 @@
 
       return 0;
     }
-    case 9: {
+    case 10: {
       if (num_params != 4) {
         return -1;
       }
@@ -459,7 +493,7 @@
 
       return 0;
     }
-    case 10: {
+    case 11: {
       if (num_params != 5) {
         return -1;
       }
@@ -497,7 +531,7 @@
 
       return 0;
     }
-    case 11: {
+    case 12: {
       if (num_params != 6) {
         return -1;
       }
@@ -542,10 +576,10 @@
 
       return 0;
     }
-    case 12:
+    case 13:
       fprintf(stderr, "MojoBeginWriteData not implemented\n");
       return -1;
-    case 13: {
+    case 14: {
       if (num_params != 4) {
         return -1;
       }
@@ -578,7 +612,7 @@
 
       return 0;
     }
-    case 14: {
+    case 15: {
       if (num_params != 4) {
         return -1;
       }
@@ -610,7 +644,7 @@
 
       return 0;
     }
-    case 15: {
+    case 16: {
       if (num_params != 5) {
         return -1;
       }
@@ -648,7 +682,7 @@
 
       return 0;
     }
-    case 16: {
+    case 17: {
       if (num_params != 6) {
         return -1;
       }
@@ -693,10 +727,10 @@
 
       return 0;
     }
-    case 17:
+    case 18:
       fprintf(stderr, "MojoBeginReadData not implemented\n");
       return -1;
-    case 18: {
+    case 19: {
       if (num_params != 4) {
         return -1;
       }
@@ -728,7 +762,7 @@
 
       return 0;
     }
-    case 19: {
+    case 20: {
       if (num_params != 5) {
         return -1;
       }
@@ -767,7 +801,7 @@
 
       return 0;
     }
-    case 20: {
+    case 21: {
       if (num_params != 5) {
         return -1;
       }
@@ -806,7 +840,7 @@
 
       return 0;
     }
-    case 21: {
+    case 22: {
       if (num_params != 5) {
         return -1;
       }
@@ -842,10 +876,10 @@
 
       return 0;
     }
-    case 22:
+    case 23:
       fprintf(stderr, "MojoMapBuffer not implemented\n");
       return -1;
-    case 23:
+    case 24:
       fprintf(stderr, "MojoUnmapBuffer not implemented\n");
       return -1;
   }
diff --git a/mojo/nacl/sfi/nacl_bindings_generator/interface.py b/mojo/nacl/sfi/nacl_bindings_generator/interface.py
index dd51977..725f118 100644
--- a/mojo/nacl/sfi/nacl_bindings_generator/interface.py
+++ b/mojo/nacl/sfi/nacl_bindings_generator/interface.py
@@ -20,6 +20,10 @@
   f = mojo.Func('MojoClose', 'MojoResult')
   f.Param('handle').In('MojoHandle')
 
+  f = mojo.Func('MojoGetRights', 'MojoResult')
+  f.Param('handle').In('MojoHandle')
+  f.Param('rights').Out('MojoHandleRights')
+
   f = mojo.Func('MojoWait', 'MojoResult')
   f.Param('handle').In('MojoHandle')
   f.Param('signals').In('MojoHandleSignals')
diff --git a/mojo/public/c/system/tests/core_unittest.cc b/mojo/public/c/system/tests/core_unittest.cc
index b8667fd..4e36860 100644
--- a/mojo/public/c/system/tests/core_unittest.cc
+++ b/mojo/public/c/system/tests/core_unittest.cc
@@ -24,6 +24,22 @@
 namespace mojo {
 namespace {
 
+const MojoHandleRights kDefaultMessagePipeHandleRights =
+    MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ |
+    MOJO_HANDLE_RIGHT_WRITE | MOJO_HANDLE_RIGHT_GET_OPTIONS |
+    MOJO_HANDLE_RIGHT_SET_OPTIONS;
+const MojoHandleRights kDefaultDataPipeProducerHandleRights =
+    MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_WRITE |
+    MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS;
+const MojoHandleRights kDefaultDataPipeConsumerHandleRights =
+    MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ |
+    MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS;
+const MojoHandleRights kDefaultSharedBufferHandleRights =
+    MOJO_HANDLE_RIGHT_DUPLICATE | MOJO_HANDLE_RIGHT_TRANSFER |
+    MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS |
+    MOJO_HANDLE_RIGHT_MAP_READABLE | MOJO_HANDLE_RIGHT_MAP_WRITABLE |
+    MOJO_HANDLE_RIGHT_MAP_EXECUTABLE;
+
 TEST(CoreTest, GetTimeTicksNow) {
   const MojoTimeTicks start = MojoGetTimeTicksNow();
   EXPECT_NE(static_cast<MojoTimeTicks>(0), start)
@@ -42,6 +58,11 @@
   // Close:
   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(MOJO_HANDLE_INVALID));
 
+  // GetRights:
+  MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoGetRights(MOJO_HANDLE_INVALID, &rights));
+
   // Wait:
   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
             MojoWait(MOJO_HANDLE_INVALID, ~MOJO_HANDLE_SIGNAL_NONE, 1000000u,
@@ -129,6 +150,15 @@
   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &h0, &h1));
   EXPECT_NE(h0, MOJO_HANDLE_INVALID);
   EXPECT_NE(h1, MOJO_HANDLE_INVALID);
+  EXPECT_NE(h0, h1);
+
+  // Both handles should have the correct rights.
+  MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoGetRights(h0, &rights));
+  EXPECT_EQ(kDefaultMessagePipeHandleRights, rights);
+  rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoGetRights(h1, &rights));
+  EXPECT_EQ(kDefaultMessagePipeHandleRights, rights);
 
   // Shouldn't be readable, we haven't written anything.
   MojoHandleSignalsState state;
@@ -225,6 +255,15 @@
   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &hp, &hc));
   EXPECT_NE(hp, MOJO_HANDLE_INVALID);
   EXPECT_NE(hc, MOJO_HANDLE_INVALID);
+  EXPECT_NE(hp, hc);
+
+  // Both handles should have the correct rights.
+  MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoGetRights(hp, &rights));
+  EXPECT_EQ(kDefaultDataPipeProducerHandleRights, rights);
+  rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoGetRights(hc, &rights));
+  EXPECT_EQ(kDefaultDataPipeConsumerHandleRights, rights);
 
   // The consumer |hc| shouldn't be readable.
   MojoHandleSignalsState state;
@@ -583,6 +622,11 @@
   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(nullptr, 100, &h0));
   EXPECT_NE(h0, MOJO_HANDLE_INVALID);
 
+  // The handle should have the correct rights.
+  MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoGetRights(h0, &rights));
+  EXPECT_EQ(kDefaultSharedBufferHandleRights, rights);
+
   // Check information about the buffer from |h0|.
   MojoBufferInformation info = {};
   static const uint32_t kInfoSize = static_cast<uint32_t>(sizeof(info));
@@ -603,6 +647,11 @@
   EXPECT_EQ(MOJO_RESULT_OK, MojoDuplicateBufferHandle(h0, nullptr, &h1));
   EXPECT_NE(h1, MOJO_HANDLE_INVALID);
 
+  // The new handle should have the correct rights.
+  rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoGetRights(h1, &rights));
+  EXPECT_EQ(kDefaultSharedBufferHandleRights, rights);
+
   // Check information about the buffer from |h1|.
   info = MojoBufferInformation();
   EXPECT_EQ(MOJO_RESULT_OK, MojoGetBufferInformation(h1, &info, kInfoSize));
diff --git a/mojo/public/platform/nacl/libmojo.cc b/mojo/public/platform/nacl/libmojo.cc
index 415d950..716877c 100644
--- a/mojo/public/platform/nacl/libmojo.cc
+++ b/mojo/public/platform/nacl/libmojo.cc
@@ -53,6 +53,13 @@
   return irt_mojo->MojoClose(handle);
 }
 
+MojoResult MojoGetRights(MojoHandle handle, MojoHandleRights* rights) {
+  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
+  if (!irt_mojo)
+    abort();
+  return irt_mojo->MojoGetRights(handle, rights);
+}
+
 MojoResult MojoWait(MojoHandle handle,
                     MojoHandleSignals signals,
                     MojoDeadline deadline,
diff --git a/mojo/public/platform/nacl/mojo_irt.h b/mojo/public/platform/nacl/mojo_irt.h
index 6259eca..4a7edc3 100644
--- a/mojo/public/platform/nacl/mojo_irt.h
+++ b/mojo/public/platform/nacl/mojo_irt.h
@@ -21,6 +21,7 @@
   MojoResult (*_MojoGetInitialHandle)(MojoHandle* handle);
   MojoTimeTicks (*MojoGetTimeTicksNow)();
   MojoResult (*MojoClose)(MojoHandle handle);
+  MojoResult (*MojoGetRights)(MojoHandle handle, MojoHandleRights* rights);
   MojoResult (*MojoWait)(MojoHandle handle,
                          MojoHandleSignals signals,
                          MojoDeadline deadline,
diff --git a/mojo/public/platform/native/system_impl_private.h b/mojo/public/platform/native/system_impl_private.h
index 6aeba44..58b3560 100644
--- a/mojo/public/platform/native/system_impl_private.h
+++ b/mojo/public/platform/native/system_impl_private.h
@@ -51,6 +51,9 @@
 // APIs mirroring the Mojo system APIs, but also taking a MojoSystemImpl param.
 MojoTimeTicks MojoSystemImplGetTimeTicksNow(MojoSystemImpl system);
 MojoResult MojoSystemImplClose(MojoSystemImpl system, MojoHandle handle);
+MojoResult MojoSystemImplGetRights(MojoSystemImpl system,
+                                   MojoHandle handle,
+                                   MojoHandleRights* rights);
 MojoResult MojoSystemImplWait(MojoSystemImpl system,
                               MojoHandle handle,
                               MojoHandleSignals signals,
diff --git a/mojo/public/platform/native/system_impl_private_thunks.c b/mojo/public/platform/native/system_impl_private_thunks.c
index 4666685..82f2ac1 100644
--- a/mojo/public/platform/native/system_impl_private_thunks.c
+++ b/mojo/public/platform/native/system_impl_private_thunks.c
@@ -41,6 +41,13 @@
   return g_system_impl_thunks.Close(system, handle);
 }
 
+MojoResult MojoSystemImplGetRights(MojoSystemImpl system,
+                                   MojoHandle handle,
+                                   MojoHandleRights* rights) {
+  assert(g_system_impl_thunks.GetRights);
+  return g_system_impl_thunks.GetRights(system, handle, rights);
+}
+
 MojoResult MojoSystemImplWait(MojoSystemImpl system,
                               MojoHandle handle,
                               MojoHandleSignals signals,
diff --git a/mojo/public/platform/native/system_impl_private_thunks.h b/mojo/public/platform/native/system_impl_private_thunks.h
index 2f8b24d..e29fc8e 100644
--- a/mojo/public/platform/native/system_impl_private_thunks.h
+++ b/mojo/public/platform/native/system_impl_private_thunks.h
@@ -34,6 +34,9 @@
   size_t size;  // Should be set to sizeof(MojoExplicitThunksPrivate).
   MojoTimeTicks (*GetTimeTicksNow)(MojoSystemImpl system);
   MojoResult (*Close)(MojoSystemImpl system, MojoHandle handle);
+  MojoResult (*GetRights)(MojoSystemImpl system,
+                          MojoHandle handle,
+                          MojoHandleRights* rights);
   MojoResult (*Wait)(MojoSystemImpl system,
                      MojoHandle handle,
                      MojoHandleSignals signals,
@@ -153,6 +156,7 @@
       sizeof(MojoSystemImplThunksPrivate),
       MojoSystemImplGetTimeTicksNow,
       MojoSystemImplClose,
+      MojoSystemImplGetRights,
       MojoSystemImplWait,
       MojoSystemImplWaitMany,
       MojoSystemImplCreateMessagePipe,
diff --git a/mojo/public/platform/native/system_impl_private_unittest.cc b/mojo/public/platform/native/system_impl_private_unittest.cc
index 871d055..215ccd4 100644
--- a/mojo/public/platform/native/system_impl_private_unittest.cc
+++ b/mojo/public/platform/native/system_impl_private_unittest.cc
@@ -12,6 +12,22 @@
 namespace mojo {
 namespace {
 
+const MojoHandleRights kDefaultMessagePipeHandleRights =
+    MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ |
+    MOJO_HANDLE_RIGHT_WRITE | MOJO_HANDLE_RIGHT_GET_OPTIONS |
+    MOJO_HANDLE_RIGHT_SET_OPTIONS;
+const MojoHandleRights kDefaultDataPipeProducerHandleRights =
+    MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_WRITE |
+    MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS;
+const MojoHandleRights kDefaultDataPipeConsumerHandleRights =
+    MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ |
+    MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS;
+const MojoHandleRights kDefaultSharedBufferHandleRights =
+    MOJO_HANDLE_RIGHT_DUPLICATE | MOJO_HANDLE_RIGHT_TRANSFER |
+    MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS |
+    MOJO_HANDLE_RIGHT_MAP_READABLE | MOJO_HANDLE_RIGHT_MAP_WRITABLE |
+    MOJO_HANDLE_RIGHT_MAP_EXECUTABLE;
+
 TEST(SystemImplTest, GetTimeTicksNow) {
   MojoSystemImpl system = MojoSystemImplCreateImpl();
   const MojoTimeTicks start = MojoSystemImplGetTimeTicksNow(system);
@@ -37,6 +53,15 @@
             MojoSystemImplCreateMessagePipe(sys0, nullptr, &h0, &h1));
   EXPECT_NE(h0, MOJO_HANDLE_INVALID);
   EXPECT_NE(h1, MOJO_HANDLE_INVALID);
+  EXPECT_NE(h0, h1);
+
+  // Both handles should have the correct rights.
+  MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplGetRights(sys0, h0, &rights));
+  EXPECT_EQ(kDefaultMessagePipeHandleRights, rights);
+  rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplGetRights(sys0, h1, &rights));
+  EXPECT_EQ(kDefaultMessagePipeHandleRights, rights);
 
   // Move the other end of the pipe to a different SystemImpl.
   EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplTransferHandle(sys0, h1, sys1, &h1));
@@ -147,6 +172,15 @@
             MojoSystemImplCreateDataPipe(sys0, nullptr, &hp, &hc));
   EXPECT_NE(hp, MOJO_HANDLE_INVALID);
   EXPECT_NE(hc, MOJO_HANDLE_INVALID);
+  EXPECT_NE(hp, hc);
+
+  // Both handles should have the correct rights.
+  MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplGetRights(sys0, hp, &rights));
+  EXPECT_EQ(kDefaultDataPipeProducerHandleRights, rights);
+  rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplGetRights(sys0, hc, &rights));
+  EXPECT_EQ(kDefaultDataPipeConsumerHandleRights, rights);
 
   // Move the other end of the pipe to a different SystemImpl.
   EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplTransferHandle(sys0, hc, sys1, &hc));
@@ -574,6 +608,11 @@
             MojoSystemImplCreateSharedBuffer(sys0, nullptr, kSize, &h0));
   EXPECT_NE(h0, MOJO_HANDLE_INVALID);
 
+  // The handle should have the correct rights.
+  MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplGetRights(sys0, h0, &rights));
+  EXPECT_EQ(kDefaultSharedBufferHandleRights, rights);
+
   // Check the buffer information.
   {
     MojoBufferInformation info = {};
@@ -598,6 +637,11 @@
             MojoSystemImplDuplicateBufferHandle(sys0, h0, nullptr, &h1));
   EXPECT_NE(h1, MOJO_HANDLE_INVALID);
 
+  // The new handle should have the correct rights.
+  rights = MOJO_HANDLE_RIGHT_NONE;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplGetRights(sys0, h1, &rights));
+  EXPECT_EQ(kDefaultSharedBufferHandleRights, rights);
+
   // Move the other end of the pipe to a different SystemImpl.
   EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplTransferHandle(sys0, h1, sys1, &h1));
   EXPECT_NE(h1, MOJO_HANDLE_INVALID);
diff --git a/mojo/public/platform/native/system_thunks.c b/mojo/public/platform/native/system_thunks.c
index 2ac8e8c..9ed890f 100644
--- a/mojo/public/platform/native/system_thunks.c
+++ b/mojo/public/platform/native/system_thunks.c
@@ -20,6 +20,11 @@
   return g_thunks.Close(handle);
 }
 
+MojoResult MojoGetRights(MojoHandle handle, MojoHandleRights* rights) {
+  assert(g_thunks.GetRights);
+  return g_thunks.GetRights(handle, rights);
+}
+
 MojoResult MojoWait(MojoHandle handle,
                     MojoHandleSignals signals,
                     MojoDeadline deadline,
diff --git a/mojo/public/platform/native/system_thunks.h b/mojo/public/platform/native/system_thunks.h
index 8ada0f0..23f7d69 100644
--- a/mojo/public/platform/native/system_thunks.h
+++ b/mojo/public/platform/native/system_thunks.h
@@ -126,6 +126,7 @@
       MojoHandle data_pipe_producer_handle,
       struct MojoDataPipeProducerOptions* options,
       uint32_t options_num_bytes);
+  MojoResult (*GetRights)(MojoHandle handle, MojoHandleRights* rights);
 };
 #pragma pack(pop)
 
@@ -159,6 +160,7 @@
       MojoGetDataPipeConsumerOptions,
       MojoSetDataPipeProducerOptions,
       MojoGetDataPipeProducerOptions,
+      MojoGetRights,
   };
   return system_thunks;
 }