security/sandbox/win/src/sharedmem_ipc_client.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 #ifndef SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__
michael@0 6 #define SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__
michael@0 7
michael@0 8 #include "sandbox/win/src/crosscall_params.h"
michael@0 9 #include "sandbox/win/src/sandbox.h"
michael@0 10
michael@0 11 // IPC transport implementation that uses shared memory.
michael@0 12 // This is the client side
michael@0 13 //
michael@0 14 // The shared memory is divided on blocks called channels, and potentially
michael@0 15 // it can perform as many concurrent IPC calls as channels. The IPC over
michael@0 16 // each channel is strictly synchronous for the client.
michael@0 17 //
michael@0 18 // Each channel as a channel control section associated with. Each control
michael@0 19 // section has two kernel events (known as ping and pong) and a integer
michael@0 20 // variable that maintains a state
michael@0 21 //
michael@0 22 // this is the state diagram of a channel:
michael@0 23 //
michael@0 24 // locked in service
michael@0 25 // kFreeChannel---------->BusyChannel-------------->kAckChannel
michael@0 26 // ^ |
michael@0 27 // |_________________________________________________|
michael@0 28 // answer ready
michael@0 29 //
michael@0 30 // The protocol is as follows:
michael@0 31 // 1) client finds a free channel: state = kFreeChannel
michael@0 32 // 2) does an atomic compare-and-swap, now state = BusyChannel
michael@0 33 // 3) client writes the data into the channel buffer
michael@0 34 // 4) client signals the ping event and waits (blocks) on the pong event
michael@0 35 // 5) eventually the server signals the pong event
michael@0 36 // 6) the client awakes and reads the answer from the same channel
michael@0 37 // 7) the client updates its InOut parameters with the new data from the
michael@0 38 // shared memory section.
michael@0 39 // 8) the client atomically sets the state = kFreeChannel
michael@0 40 //
michael@0 41 // In the shared memory the layout is as follows:
michael@0 42 //
michael@0 43 // [ channel count ]
michael@0 44 // [ channel control 0]
michael@0 45 // [ channel control 1]
michael@0 46 // [ channel control N]
michael@0 47 // [ channel buffer 0 ] 1024 bytes
michael@0 48 // [ channel buffer 1 ] 1024 bytes
michael@0 49 // [ channel buffer N ] 1024 bytes
michael@0 50 //
michael@0 51 // By default each channel buffer is 1024 bytes
michael@0 52 namespace sandbox {
michael@0 53
michael@0 54 // the possible channel states as described above
michael@0 55 enum ChannelState {
michael@0 56 // channel is free
michael@0 57 kFreeChannel = 1,
michael@0 58 // IPC in progress client side
michael@0 59 kBusyChannel,
michael@0 60 // IPC in progress server side
michael@0 61 kAckChannel,
michael@0 62 // not used right now
michael@0 63 kReadyChannel,
michael@0 64 // IPC abandoned by client side
michael@0 65 kAbandonnedChannel
michael@0 66 };
michael@0 67
michael@0 68 // The next two constants control the time outs for the IPC.
michael@0 69 const DWORD kIPCWaitTimeOut1 = 1000; // Milliseconds.
michael@0 70 const DWORD kIPCWaitTimeOut2 = 50; // Milliseconds.
michael@0 71
michael@0 72 // the channel control structure
michael@0 73 struct ChannelControl {
michael@0 74 // points to be beginning of the channel buffer, where data goes
michael@0 75 size_t channel_base;
michael@0 76 // maintains the state from the ChannelState enumeration
michael@0 77 volatile LONG state;
michael@0 78 // the ping event is signaled by the client when the IPC data is ready on
michael@0 79 // the buffer
michael@0 80 HANDLE ping_event;
michael@0 81 // the client waits on the pong event for the IPC answer back
michael@0 82 HANDLE pong_event;
michael@0 83 // the IPC unique identifier
michael@0 84 uint32 ipc_tag;
michael@0 85 };
michael@0 86
michael@0 87 struct IPCControl {
michael@0 88 // total number of channels available, some might be busy at a given time
michael@0 89 size_t channels_count;
michael@0 90 // handle to a shared mutex to detect when the server is dead
michael@0 91 HANDLE server_alive;
michael@0 92 // array of channel control structures
michael@0 93 ChannelControl channels[1];
michael@0 94 };
michael@0 95
michael@0 96 // the actual shared memory IPC implementation class. This object is designed
michael@0 97 // to be lightweight so it can be constructed on-site (at the calling place)
michael@0 98 // wherever an IPC call is needed.
michael@0 99 class SharedMemIPCClient {
michael@0 100 public:
michael@0 101 // Creates the IPC client.
michael@0 102 // as parameter it takes the base address of the shared memory
michael@0 103 explicit SharedMemIPCClient(void* shared_mem);
michael@0 104
michael@0 105 // locks a free channel and returns the channel buffer memory base. This call
michael@0 106 // blocks until there is a free channel
michael@0 107 void* GetBuffer();
michael@0 108
michael@0 109 // releases the lock on the channel, for other to use. call this if you have
michael@0 110 // called GetBuffer and you want to abort but have not called yet DoCall()
michael@0 111 void FreeBuffer(void* buffer);
michael@0 112
michael@0 113 // Performs the actual IPC call.
michael@0 114 // params: The blob of packed input parameters.
michael@0 115 // answer: upon IPC completion, it contains the server answer to the IPC.
michael@0 116 // If the return value is not SBOX_ERROR_CHANNEL_ERROR, the caller has to free
michael@0 117 // the channel.
michael@0 118 // returns ALL_OK if the IPC mechanism successfully delivered. You still need
michael@0 119 // to check on the answer structure to see the actual IPC result.
michael@0 120 ResultCode DoCall(CrossCallParams* params, CrossCallReturn* answer);
michael@0 121
michael@0 122 private:
michael@0 123 // Returns the index of the first free channel. It sets 'severe_failure'
michael@0 124 // to true if there is an unrecoverable error that does not allow to
michael@0 125 // find a channel.
michael@0 126 size_t LockFreeChannel(bool* severe_failure);
michael@0 127 // Return the channel index given the address of the buffer.
michael@0 128 size_t ChannelIndexFromBuffer(const void* buffer);
michael@0 129 IPCControl* control_;
michael@0 130 // point to the first channel base
michael@0 131 char* first_base_;
michael@0 132 };
michael@0 133
michael@0 134 } // namespace sandbox
michael@0 135
michael@0 136 #endif // SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__

mercurial