Home | History | Annotate | Download | only in proxy
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ipc/ipc_message.h"
      6 #include "ppapi/proxy/nacl_message_scanner.h"
      7 #include "ppapi/proxy/ppapi_messages.h"
      8 #include "ppapi/proxy/ppapi_proxy_test.h"
      9 #include "ppapi/proxy/serialized_handle.h"
     10 #include "ppapi/shared_impl/host_resource.h"
     11 
     12 namespace ppapi {
     13 namespace proxy {
     14 
     15 namespace {
     16 const PP_Resource kInvalidResource = 0;
     17 const PP_Resource kFileSystem = 1;
     18 const PP_Resource kFileIO = 2;
     19 const int64_t kQuotaReservationAmount = 100;
     20 }
     21 
     22 class NaClMessageScannerTest : public PluginProxyTest {
     23  public:
     24   NaClMessageScannerTest() {}
     25 
     26   NaClMessageScanner::FileSystem* FindFileSystem(
     27       const NaClMessageScanner& scanner,
     28       PP_Resource file_system) {
     29     NaClMessageScanner::FileSystemMap::const_iterator it =
     30         scanner.file_systems_.find(file_system);
     31     return (it != scanner.file_systems_.end()) ? it->second : NULL;
     32   }
     33 
     34   NaClMessageScanner::FileIO* FindFileIO(
     35       const NaClMessageScanner& scanner,
     36       PP_Resource file_io) {
     37     NaClMessageScanner::FileIOMap::const_iterator it =
     38         scanner.files_.find(file_io);
     39     return (it != scanner.files_.end()) ? it->second : NULL;
     40   }
     41 
     42   void OpenQuotaFile(NaClMessageScanner* scanner,
     43                      PP_Resource file_io,
     44                      PP_Resource file_system) {
     45     std::vector<SerializedHandle> unused_handles;
     46     ResourceMessageReplyParams fio_reply_params(file_io, 0);
     47     scoped_ptr<IPC::Message> new_msg_ptr;
     48     scanner->ScanMessage(
     49         PpapiPluginMsg_ResourceReply(
     50             fio_reply_params,
     51             PpapiPluginMsg_FileIO_OpenReply(file_system, 0)),
     52         PpapiPluginMsg_ResourceReply::ID,
     53         &unused_handles,
     54         &new_msg_ptr);
     55     EXPECT_FALSE(new_msg_ptr);
     56   }
     57 };
     58 
     59 TEST_F(NaClMessageScannerTest, FileOpenClose) {
     60   NaClMessageScanner test;
     61   std::vector<SerializedHandle> unused_handles;
     62   ResourceMessageCallParams fio_call_params(kFileIO, 0);
     63   ResourceMessageCallParams fs_call_params(kFileSystem, 0);
     64   ResourceMessageReplyParams fio_reply_params(kFileIO, 0);
     65   ResourceMessageReplyParams fs_reply_params(kFileSystem, 0);
     66   scoped_ptr<IPC::Message> new_msg_ptr;
     67 
     68   EXPECT_EQ(NULL, FindFileSystem(test, kFileSystem));
     69   EXPECT_EQ(NULL, FindFileIO(test, kFileIO));
     70 
     71   // Open a file, not in a quota file system.
     72   test.ScanMessage(
     73       PpapiPluginMsg_ResourceReply(
     74           fio_reply_params,
     75           PpapiPluginMsg_FileIO_OpenReply(kInvalidResource, 0)),
     76       PpapiPluginMsg_ResourceReply::ID,
     77       &unused_handles,
     78       &new_msg_ptr);
     79   EXPECT_FALSE(new_msg_ptr);
     80   EXPECT_FALSE(FindFileSystem(test, kFileSystem));
     81   EXPECT_FALSE(FindFileIO(test, kFileIO));
     82 
     83   // Open a file in a quota file system; info objects for it and its file system
     84   // should be created.
     85   OpenQuotaFile(&test, kFileIO, kFileSystem);
     86   NaClMessageScanner::FileSystem* fs = FindFileSystem(test, kFileSystem);
     87   NaClMessageScanner::FileIO* fio = FindFileIO(test, kFileIO);
     88   EXPECT_TRUE(fs);
     89   EXPECT_EQ(0, fs->reserved_quota());
     90   EXPECT_TRUE(fio);
     91   EXPECT_EQ(0, fio->max_written_offset());
     92 
     93   const int64_t kNewFileSize = 10;
     94   fio->SetMaxWrittenOffset(kNewFileSize);
     95 
     96   // We should not be able to under-report max_written_offset when closing.
     97   test.ScanUntrustedMessage(
     98       PpapiHostMsg_ResourceCall(
     99           fio_call_params,
    100           PpapiHostMsg_FileIO_Close(FileGrowth(0, 0))),
    101       &new_msg_ptr);
    102   EXPECT_TRUE(new_msg_ptr);
    103   ResourceMessageCallParams call_params;
    104   IPC::Message nested_msg;
    105   FileGrowth file_growth;
    106   EXPECT_TRUE(UnpackMessage<PpapiHostMsg_ResourceCall>(
    107                   *new_msg_ptr, &call_params, &nested_msg) &&
    108               UnpackMessage<PpapiHostMsg_FileIO_Close>(
    109                   nested_msg, &file_growth));
    110   new_msg_ptr.reset();
    111   EXPECT_EQ(kNewFileSize, file_growth.max_written_offset);
    112   EXPECT_FALSE(FindFileIO(test, kFileIO));
    113 
    114   // Reopen the file.
    115   OpenQuotaFile(&test, kFileIO, kFileSystem);
    116   fio = FindFileIO(test, kFileIO);
    117   fio->SetMaxWrittenOffset(kNewFileSize);
    118 
    119   // Close with correct max_written_offset.
    120   test.ScanUntrustedMessage(
    121       PpapiHostMsg_ResourceCall(
    122           fio_call_params,
    123           PpapiHostMsg_FileIO_Close(FileGrowth(kNewFileSize, 0))),
    124       &new_msg_ptr);
    125   EXPECT_FALSE(new_msg_ptr);
    126   EXPECT_FALSE(FindFileIO(test, kFileIO));
    127 
    128   // Destroy file system.
    129   test.ScanUntrustedMessage(
    130       PpapiHostMsg_ResourceCall(
    131           fs_call_params,
    132           PpapiHostMsg_ResourceDestroyed(kFileSystem)),
    133       &new_msg_ptr);
    134   EXPECT_FALSE(FindFileSystem(test, kFileSystem));
    135 }
    136 
    137 TEST_F(NaClMessageScannerTest, QuotaAuditing) {
    138   NaClMessageScanner test;
    139   std::vector<SerializedHandle> unused_handles;
    140   ResourceMessageCallParams fio_call_params(kFileIO, 0);
    141   ResourceMessageCallParams fs_call_params(kFileSystem, 0);
    142   ResourceMessageReplyParams fio_reply_params(kFileIO, 0);
    143   ResourceMessageReplyParams fs_reply_params(kFileSystem, 0);
    144   scoped_ptr<IPC::Message> new_msg_ptr;
    145 
    146   OpenQuotaFile(&test, kFileIO, kFileSystem);
    147   NaClMessageScanner::FileSystem* fs = FindFileSystem(test, kFileSystem);
    148   NaClMessageScanner::FileIO* fio = FindFileIO(test, kFileIO);
    149   EXPECT_TRUE(fs);
    150   EXPECT_EQ(0, fs->reserved_quota());
    151   EXPECT_TRUE(fio);
    152   EXPECT_EQ(0, fio->max_written_offset());
    153 
    154   // Without reserving quota, we should not be able to grow the file.
    155   EXPECT_FALSE(fio->Grow(1));
    156   EXPECT_EQ(0, fs->reserved_quota());
    157   EXPECT_EQ(0, fio->max_written_offset());
    158 
    159   // Receive reserved quota, and updated file sizes.
    160   const int64_t kNewFileSize = 10;
    161   FileSizeMap file_sizes;
    162   file_sizes[kFileIO] = kNewFileSize;
    163   test.ScanMessage(
    164       PpapiPluginMsg_ResourceReply(
    165           fs_reply_params,
    166           PpapiPluginMsg_FileSystem_ReserveQuotaReply(
    167               kQuotaReservationAmount,
    168               file_sizes)),
    169       PpapiPluginMsg_ResourceReply::ID,
    170       &unused_handles,
    171       &new_msg_ptr);
    172   EXPECT_FALSE(new_msg_ptr);
    173   EXPECT_EQ(kQuotaReservationAmount, fs->reserved_quota());
    174   EXPECT_EQ(kNewFileSize, fio->max_written_offset());
    175 
    176   // We should be able to grow the file within quota.
    177   EXPECT_TRUE(fio->Grow(1));
    178   EXPECT_EQ(kQuotaReservationAmount - 1, fs->reserved_quota());
    179   EXPECT_EQ(kNewFileSize + 1, fio->max_written_offset());
    180 
    181   // We should not be able to grow the file over quota.
    182   EXPECT_FALSE(fio->Grow(kQuotaReservationAmount));
    183   EXPECT_EQ(kQuotaReservationAmount - 1, fs->reserved_quota());
    184   EXPECT_EQ(kNewFileSize + 1, fio->max_written_offset());
    185 
    186   // Plugin should not under-report max written offsets when reserving quota.
    187   file_sizes[kFileIO] = 0;  // should be kNewFileSize + 1.
    188   test.ScanUntrustedMessage(
    189       PpapiHostMsg_ResourceCall(
    190           fio_call_params,
    191           PpapiHostMsg_FileSystem_ReserveQuota(
    192               kQuotaReservationAmount,
    193               FileSizeMapToFileGrowthMapForTesting(file_sizes))),
    194       &new_msg_ptr);
    195   EXPECT_TRUE(new_msg_ptr);
    196   ResourceMessageCallParams call_params;
    197   IPC::Message nested_msg;
    198   int64_t amount = 0;
    199   FileGrowthMap new_file_growths;
    200   EXPECT_TRUE(UnpackMessage<PpapiHostMsg_ResourceCall>(
    201                   *new_msg_ptr, &call_params, &nested_msg) &&
    202               UnpackMessage<PpapiHostMsg_FileSystem_ReserveQuota>(
    203                   nested_msg, &amount, &new_file_growths));
    204   new_msg_ptr.reset();
    205   EXPECT_EQ(kQuotaReservationAmount, amount);
    206   EXPECT_EQ(kNewFileSize + 1, new_file_growths[kFileIO].max_written_offset);
    207 }
    208 
    209 TEST_F(NaClMessageScannerTest, SetLength) {
    210   NaClMessageScanner test;
    211   std::vector<SerializedHandle> unused_handles;
    212   ResourceMessageCallParams fio_call_params(kFileIO, 0);
    213   ResourceMessageCallParams fs_call_params(kFileSystem, 0);
    214   ResourceMessageReplyParams fio_reply_params(kFileIO, 0);
    215   ResourceMessageReplyParams fs_reply_params(kFileSystem, 0);
    216   scoped_ptr<IPC::Message> new_msg_ptr;
    217 
    218   OpenQuotaFile(&test, kFileIO, kFileSystem);
    219   NaClMessageScanner::FileSystem* fs = FindFileSystem(test, kFileSystem);
    220   NaClMessageScanner::FileIO* fio = FindFileIO(test, kFileIO);
    221 
    222   // Receive reserved quota, and updated file sizes.
    223   const int64_t kNewFileSize = 10;
    224   FileSizeMap file_sizes;
    225   file_sizes[kFileIO] = 0;
    226   test.ScanMessage(
    227       PpapiPluginMsg_ResourceReply(
    228           fs_reply_params,
    229           PpapiPluginMsg_FileSystem_ReserveQuotaReply(
    230               kQuotaReservationAmount,
    231               file_sizes)),
    232       PpapiPluginMsg_ResourceReply::ID,
    233       &unused_handles,
    234       &new_msg_ptr);
    235 
    236   // We should be able to SetLength within quota.
    237   test.ScanUntrustedMessage(
    238       PpapiHostMsg_ResourceCall(
    239           fio_call_params,
    240           PpapiHostMsg_FileIO_SetLength(kNewFileSize)),
    241       &new_msg_ptr);
    242   EXPECT_FALSE(new_msg_ptr);
    243   EXPECT_EQ(kQuotaReservationAmount - kNewFileSize, fs->reserved_quota());
    244   EXPECT_EQ(kNewFileSize, fio->max_written_offset());
    245 
    246   // We shouldn't be able to SetLength beyond quota. The message should be
    247   // rewritten to fail with length == -1.
    248   test.ScanUntrustedMessage(
    249       PpapiHostMsg_ResourceCall(
    250           fio_call_params,
    251           PpapiHostMsg_FileIO_SetLength(kQuotaReservationAmount + 1)),
    252       &new_msg_ptr);
    253   EXPECT_TRUE(new_msg_ptr);
    254   ResourceMessageCallParams call_params;
    255   IPC::Message nested_msg;
    256   int64_t length = 0;
    257   EXPECT_TRUE(UnpackMessage<PpapiHostMsg_ResourceCall>(
    258                   *new_msg_ptr, &call_params, &nested_msg) &&
    259               UnpackMessage<PpapiHostMsg_FileIO_SetLength>(
    260                   nested_msg, &length));
    261   new_msg_ptr.reset();
    262   EXPECT_EQ(-1, length);
    263   EXPECT_EQ(kQuotaReservationAmount - kNewFileSize, fs->reserved_quota());
    264   EXPECT_EQ(kNewFileSize, fio->max_written_offset());
    265 }
    266 
    267 }  // namespace proxy
    268 }  // namespace ppapi
    269