ioctl_private.cpp
Go to the documentation of this file.
1 //
2 // Bareflank Hypervisor
3 //
4 // Copyright (C) 2015 Assured Information Security, Inc.
5 // Author: Rian Quinn <quinnr@ainfosec.com>
6 // Author: Brendan Kerrigan <kerriganb@ainfosec.com>
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 #include <gsl/gsl>
23 
24 #include <exception.h>
25 #include <ioctl_private.h>
26 #include <driver_entry_interface.h>
27 
28 #include <SetupAPI.h>
29 
30 // -----------------------------------------------------------------------------
31 // Unit Test Seems
32 // -----------------------------------------------------------------------------
33 
34 HANDLE
36 {
37  HANDLE hDevInfo;
38  SP_INTERFACE_DEVICE_DETAIL_DATA *deviceDetailData = nullptr;
39 
40  SP_DEVINFO_DATA devInfo;
41  devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
42 
43  SP_INTERFACE_DEVICE_DATA ifInfo;
44  ifInfo.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
45 
46  hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_bareflank, 0, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
47  if (hDevInfo == INVALID_HANDLE_VALUE)
48  return hDevInfo;
49 
50  if (SetupDiEnumDeviceInfo(hDevInfo, 0, &devInfo) == false)
51  return INVALID_HANDLE_VALUE;
52 
53  if (SetupDiEnumDeviceInterfaces(hDevInfo, &devInfo, &(GUID_DEVINTERFACE_bareflank), 0, &ifInfo) == false)
54  return INVALID_HANDLE_VALUE;
55 
56  DWORD requiredSize = 0;
57 
58  if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &ifInfo, NULL, 0, &requiredSize, NULL) == true)
59  return INVALID_HANDLE_VALUE;
60 
61  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
62  return INVALID_HANDLE_VALUE;
63 
64  deviceDetailData = static_cast<SP_INTERFACE_DEVICE_DETAIL_DATA *>(malloc(requiredSize));
65 
66  if (deviceDetailData == nullptr)
67  return INVALID_HANDLE_VALUE;
68 
69  auto ___ = gsl::finally([&]
70  { free(deviceDetailData); });
71 
72  deviceDetailData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
73 
74  if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &ifInfo, deviceDetailData, requiredSize, NULL, NULL) == false)
75  return INVALID_HANDLE_VALUE;
76 
77  return CreateFile(deviceDetailData->DevicePath,
78  GENERIC_READ | GENERIC_WRITE,
79  0,
80  NULL,
81  CREATE_ALWAYS,
82  FILE_ATTRIBUTE_NORMAL,
83  NULL);
84 }
85 
86 int64_t
87 bf_send_ioctl(HANDLE fd, DWORD request)
88 {
89  if (!DeviceIoControl(fd, request, NULL, 0, NULL, 0, NULL, NULL))
90  return BF_IOCTL_FAILURE;
91 
92  return 0;
93 }
94 
95 int64_t
96 bf_read_ioctl(HANDLE fd, DWORD request, void *data, DWORD size)
97 {
98  if (!DeviceIoControl(fd, request, NULL, 0, data, size, NULL, NULL))
99  return BF_IOCTL_FAILURE;
100 
101  return 0;
102 }
103 
104 int64_t
105 bf_write_ioctl(HANDLE fd, DWORD request, const void *data, DWORD size)
106 {
107  if (!DeviceIoControl(fd, request, const_cast<void *>(data), size, NULL, 0, NULL, NULL))
108  return BF_IOCTL_FAILURE;
109 
110  return 0;
111 }
112 
113 int64_t
114 bf_read_write_ioctl(HANDLE fd, DWORD request, void *data, DWORD size)
115 {
116  if (!DeviceIoControl(fd, request, data, size, data, size, NULL, NULL))
117  return BF_IOCTL_FAILURE;
118 
119  return 0;
120 }
121 
122 // -----------------------------------------------------------------------------
123 // Implementation
124 // -----------------------------------------------------------------------------
125 
127  fd(INVALID_HANDLE_VALUE)
128 {
129 }
130 
132 {
133  if (fd != INVALID_HANDLE_VALUE)
134  CloseHandle(fd);
135 }
136 
137 void
139 {
140  if ((fd = bf_ioctl_open()) == INVALID_HANDLE_VALUE)
141  throw driver_inaccessible();
142 }
143 
144 #pragma GCC diagnostic push
145 #pragma GCC diagnostic ignored "-Wconversion"
146 #pragma GCC diagnostic ignored "-Wsign-conversion"
147 
148 void
149 ioctl_private::call_ioctl_add_module(gsl::not_null<module_data_type> data, module_len_type len)
150 {
151  expects(len > 0);
152 
153  if (bf_write_ioctl(fd, IOCTL_ADD_MODULE, data, len) == BF_IOCTL_FAILURE)
154  throw ioctl_failed(IOCTL_ADD_MODULE);
155 }
156 
157 void
159 {
160  if (bf_send_ioctl(fd, IOCTL_LOAD_VMM) == BF_IOCTL_FAILURE)
161  throw ioctl_failed(IOCTL_LOAD_VMM);
162 }
163 
164 void
166 {
167  if (bf_send_ioctl(fd, IOCTL_UNLOAD_VMM) == BF_IOCTL_FAILURE)
168  throw ioctl_failed(IOCTL_UNLOAD_VMM);
169 }
170 
171 void
173 {
174  if (bf_send_ioctl(fd, IOCTL_START_VMM) == BF_IOCTL_FAILURE)
175  throw ioctl_failed(IOCTL_START_VMM);
176 }
177 
178 void
180 {
181  if (bf_send_ioctl(fd, IOCTL_STOP_VMM) == BF_IOCTL_FAILURE)
182  throw ioctl_failed(IOCTL_STOP_VMM);
183 }
184 
185 void
186 ioctl_private::call_ioctl_dump_vmm(gsl::not_null<drr_pointer> drr, vcpuid_type vcpuid)
187 {
188  if (bf_write_ioctl(fd, IOCTL_SET_VCPUID, &vcpuid, sizeof(vcpuid)) == BF_IOCTL_FAILURE)
189  throw ioctl_failed(IOCTL_SET_VCPUID);
190 
191  if (bf_read_ioctl(fd, IOCTL_DUMP_VMM, drr, sizeof(*drr)) == BF_IOCTL_FAILURE)
192  throw ioctl_failed(IOCTL_DUMP_VMM);
193 }
194 
195 void
196 ioctl_private::call_ioctl_vmm_status(gsl::not_null<status_pointer> status)
197 {
198  if (bf_read_ioctl(fd, IOCTL_VMM_STATUS, status, sizeof(*status)) == BF_IOCTL_FAILURE)
199  throw ioctl_failed(IOCTL_VMM_STATUS);
200 }
201 
202 void
203 ioctl_private::call_ioctl_vmcall(gsl::not_null<registers_pointer> regs, cpuid_type cpuid)
204 {
205  if (bf_write_ioctl(fd, IOCTL_SET_CPUID, &cpuid, sizeof(cpuid)) == BF_IOCTL_FAILURE)
206  throw ioctl_failed(IOCTL_SET_CPUID);
207 
208  if (bf_read_write_ioctl(fd, IOCTL_VMCALL, regs, sizeof(*regs)) == BF_IOCTL_FAILURE)
209  throw ioctl_failed(IOCTL_VMCALL);
210 }
211 
212 #pragma GCC diagnostic pop
virtual void call_ioctl_stop_vmm()
expects(rbx)
int64_t unsigned long request
int64_t bf_read_ioctl(int64_t fd, unsigned long request, void *data)
void free(void *ptr)
Definition: syscall.cpp:370
int64_t bf_ioctl_open()
virtual void call_ioctl_load_vmm()
int64_t unsigned long void * data
void * malloc(size_t size)
Definition: syscall.cpp:364
int64_t bf_read_write_ioctl(HANDLE fd, DWORD request, void *data, DWORD size)
Definition: vcpuid.h:29
virtual void call_ioctl_vmm_status(gsl::not_null< status_pointer > status)
debug_ring_resources_t * drr
constexpr const auto size
virtual void call_ioctl_start_vmm()
virtual void call_ioctl_dump_vmm(gsl::not_null< drr_pointer > drr, vcpuid_type vcpuid)
#define driver_inaccessible(a)
Definition: exception.h:242
#define BF_IOCTL_FAILURE
Definition: error_codes.h:122
int64_t bf_write_ioctl(int64_t fd, unsigned long request, const void *data)
#define ioctl_failed(a)
Definition: exception.h:262
~ioctl_private() override
virtual void call_ioctl_vmcall(gsl::not_null< registers_pointer > regs, cpuid_type cpuid)
virtual void call_ioctl_add_module(gsl::not_null< module_data_type > data)
size_t module_len_type
Definition: ioctl_private.h:31
virtual void open()
int64_t bf_send_ioctl(int64_t fd, unsigned long request)
virtual void call_ioctl_unload_vmm()