1// Copyright (c) 2006-2008 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 "sandbox/win/src/sync_interception.h"
6
7#include "sandbox/win/src/crosscall_client.h"
8#include "sandbox/win/src/ipc_tags.h"
9#include "sandbox/win/src/policy_params.h"
10#include "sandbox/win/src/policy_target.h"
11#include "sandbox/win/src/sandbox_factory.h"
12#include "sandbox/win/src/sandbox_nt_util.h"
13#include "sandbox/win/src/sharedmem_ipc_client.h"
14#include "sandbox/win/src/target_services.h"
15
16namespace sandbox {
17
18ResultCode ProxyCreateEvent(LPCWSTR name,
19                            BOOL initial_state,
20                            EVENT_TYPE event_type,
21                            void* ipc_memory,
22                            CrossCallReturn* answer) {
23  CountedParameterSet<NameBased> params;
24  params[NameBased::NAME] = ParamPickerMake(name);
25
26  if (!QueryBroker(IPC_CREATEEVENT_TAG, params.GetBase()))
27    return SBOX_ERROR_GENERIC;
28
29  SharedMemIPCClient ipc(ipc_memory);
30  ResultCode code = CrossCall(ipc, IPC_CREATEEVENT_TAG, name, event_type,
31                              initial_state, answer);
32  return code;
33}
34
35ResultCode ProxyOpenEvent(LPCWSTR name,
36                          ACCESS_MASK desired_access,
37                          void* ipc_memory,
38                          CrossCallReturn* answer) {
39  CountedParameterSet<OpenEventParams> params;
40  params[OpenEventParams::NAME] = ParamPickerMake(name);
41  params[OpenEventParams::ACCESS] = ParamPickerMake(desired_access);
42
43  if (!QueryBroker(IPC_OPENEVENT_TAG, params.GetBase()))
44    return SBOX_ERROR_GENERIC;
45
46  SharedMemIPCClient ipc(ipc_memory);
47  ResultCode code = CrossCall(ipc, IPC_OPENEVENT_TAG, name, desired_access,
48                              answer);
49
50  return code;
51}
52
53NTSTATUS WINAPI TargetNtCreateEvent(NtCreateEventFunction orig_CreateEvent,
54                                    PHANDLE event_handle,
55                                    ACCESS_MASK desired_access,
56                                    POBJECT_ATTRIBUTES object_attributes,
57                                    EVENT_TYPE event_type,
58                                    BOOLEAN initial_state) {
59  NTSTATUS status = orig_CreateEvent(event_handle, desired_access,
60                                     object_attributes, event_type,
61                                     initial_state);
62  if (status != STATUS_ACCESS_DENIED || !object_attributes)
63    return status;
64
65  // We don't trust that the IPC can work this early.
66  if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
67    return status;
68
69  do {
70    if (!ValidParameter(event_handle, sizeof(HANDLE), WRITE))
71      break;
72
73    void* memory = GetGlobalIPCMemory();
74    if (memory == NULL)
75      break;
76
77    OBJECT_ATTRIBUTES object_attribs_copy = *object_attributes;
78    // The RootDirectory points to BaseNamedObjects. We can ignore it.
79    object_attribs_copy.RootDirectory = NULL;
80
81    wchar_t* name = NULL;
82    uint32 attributes = 0;
83    NTSTATUS ret = AllocAndCopyName(&object_attribs_copy, &name, &attributes,
84                                    NULL);
85    if (!NT_SUCCESS(ret) || name == NULL)
86      break;
87
88    CrossCallReturn answer = {0};
89    answer.nt_status = status;
90    ResultCode code = ProxyCreateEvent(name, initial_state, event_type, memory,
91                                       &answer);
92    operator delete(name, NT_ALLOC);
93
94    if (code != SBOX_ALL_OK) {
95      status = answer.nt_status;
96      break;
97    }
98    __try {
99      *event_handle = answer.handle;
100      status = STATUS_SUCCESS;
101    } __except(EXCEPTION_EXECUTE_HANDLER) {
102      break;
103    }
104  } while (false);
105
106  return status;
107}
108
109NTSTATUS WINAPI TargetNtOpenEvent(NtOpenEventFunction orig_OpenEvent,
110                                  PHANDLE event_handle,
111                                  ACCESS_MASK desired_access,
112                                  POBJECT_ATTRIBUTES object_attributes) {
113  NTSTATUS status = orig_OpenEvent(event_handle, desired_access,
114                                   object_attributes);
115  if (status != STATUS_ACCESS_DENIED || !object_attributes)
116    return status;
117
118  // We don't trust that the IPC can work this early.
119  if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
120    return status;
121
122  do {
123    if (!ValidParameter(event_handle, sizeof(HANDLE), WRITE))
124      break;
125
126    void* memory = GetGlobalIPCMemory();
127    if (memory == NULL)
128      break;
129
130    OBJECT_ATTRIBUTES object_attribs_copy = *object_attributes;
131    // The RootDirectory points to BaseNamedObjects. We can ignore it.
132    object_attribs_copy.RootDirectory = NULL;
133
134    wchar_t* name = NULL;
135    uint32 attributes = 0;
136    NTSTATUS ret = AllocAndCopyName(&object_attribs_copy, &name, &attributes,
137                                    NULL);
138    if (!NT_SUCCESS(ret) || name == NULL)
139      break;
140
141    CrossCallReturn answer = {0};
142    answer.nt_status = status;
143    ResultCode code = ProxyOpenEvent(name, desired_access, memory, &answer);
144    operator delete(name, NT_ALLOC);
145
146    if (code != SBOX_ALL_OK) {
147      status = answer.nt_status;
148      break;
149    }
150    __try {
151      *event_handle = answer.handle;
152      status = STATUS_SUCCESS;
153    } __except(EXCEPTION_EXECUTE_HANDLER) {
154      break;
155    }
156  } while (false);
157
158  return status;
159}
160
161}  // namespace sandbox
162