1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
|
/* $Id: VBoxServiceControl.h $ */
/** @file
* VBoxServiceControl.h - Internal guest control definitions.
*/
/*
* Copyright (C) 2013-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#ifndef GA_INCLUDED_SRC_common_VBoxService_VBoxServiceControl_h
#define GA_INCLUDED_SRC_common_VBoxService_VBoxServiceControl_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include <iprt/critsect.h>
#include <iprt/list.h>
#include <iprt/req.h>
#include <VBox/VBoxGuestLib.h>
#include <VBox/GuestHost/GuestControl.h>
#include <VBox/HostServices/GuestControlSvc.h>
/**
* Pipe IDs for handling the guest process poll set.
*/
typedef enum VBOXSERVICECTRLPIPEID
{
VBOXSERVICECTRLPIPEID_UNKNOWN = 0,
VBOXSERVICECTRLPIPEID_STDIN = 10,
VBOXSERVICECTRLPIPEID_STDIN_WRITABLE = 11,
/** Pipe for reading from guest process' stdout. */
VBOXSERVICECTRLPIPEID_STDOUT = 40,
/** Pipe for reading from guest process' stderr. */
VBOXSERVICECTRLPIPEID_STDERR = 50,
/** Notification pipe for waking up the guest process
* control thread. */
VBOXSERVICECTRLPIPEID_IPC_NOTIFY = 100
} VBOXSERVICECTRLPIPEID;
/**
* Structure for one (opened) guest file.
*/
typedef struct VBOXSERVICECTRLFILE
{
/** Pointer to list archor of following
* list node.
* @todo Would be nice to have a RTListGetAnchor(). */
PRTLISTANCHOR pAnchor;
/** Node to global guest control file list. */
/** @todo Use a map later? */
RTLISTNODE Node;
/** The file name. */
char *pszName;
/** The file handle on the guest. */
RTFILE hFile;
/** File handle to identify this file. */
uint32_t uHandle;
/** Context ID. */
uint32_t uContextID;
/** RTFILE_O_XXX flags. */
uint64_t fOpen;
} VBOXSERVICECTRLFILE;
/** Pointer to thread data. */
typedef VBOXSERVICECTRLFILE *PVBOXSERVICECTRLFILE;
/**
* Structure for a guest session thread to
* observe/control the forked session instance from
* the VBoxService main executable.
*/
typedef struct VBOXSERVICECTRLSESSIONTHREAD
{
/** Node to global guest control session list. */
/** @todo Use a map later? */
RTLISTNODE Node;
/** The sessions's startup info. */
PVBGLR3GUESTCTRLSESSIONSTARTUPINFO
pStartupInfo;
/** Critical section for thread-safe use. */
RTCRITSECT CritSect;
/** The worker thread. */
RTTHREAD Thread;
/** Process handle for forked child. */
RTPROCESS hProcess;
/** Shutdown indicator; will be set when the thread
* needs (or is asked) to shutdown. */
bool volatile fShutdown;
/** Indicator set by the service thread exiting. */
bool volatile fStopped;
/** Whether the thread was started or not. */
bool fStarted;
#if 0 /* Pipe IPC not used yet. */
/** Pollset containing all the pipes. */
RTPOLLSET hPollSet;
RTPIPE hStdInW;
RTPIPE hStdOutR;
RTPIPE hStdErrR;
struct StdPipe
{
RTHANDLE hChild;
PRTHANDLE phChild;
} StdIn,
StdOut,
StdErr;
/** The notification pipe associated with this guest session.
* This is NIL_RTPIPE for output pipes. */
RTPIPE hNotificationPipeW;
/** The other end of hNotificationPipeW. */
RTPIPE hNotificationPipeR;
#endif
/** Pipe for handing the secret key to the session process. */
RTPIPE hKeyPipe;
/** Secret key. */
uint8_t abKey[_4K];
} VBOXSERVICECTRLSESSIONTHREAD;
/** Pointer to thread data. */
typedef VBOXSERVICECTRLSESSIONTHREAD *PVBOXSERVICECTRLSESSIONTHREAD;
/** Defines the prefix being used for telling our service executable that we're going
* to spawn a new (Guest Control) user session. */
#define VBOXSERVICECTRLSESSION_GETOPT_PREFIX "guestsession"
/** Flag indicating that this session has been spawned from
* the main executable. */
#define VBOXSERVICECTRLSESSION_FLAG_SPAWN RT_BIT(0)
/** Flag indicating that this session is anonymous, that is,
* it will run start guest processes with the same credentials
* as the main executable. */
#define VBOXSERVICECTRLSESSION_FLAG_ANONYMOUS RT_BIT(1)
/** Flag indicating that started guest processes will dump their
* stdout output to a separate file on disk. For debugging. */
#define VBOXSERVICECTRLSESSION_FLAG_DUMPSTDOUT RT_BIT(2)
/** Flag indicating that started guest processes will dump their
* stderr output to a separate file on disk. For debugging. */
#define VBOXSERVICECTRLSESSION_FLAG_DUMPSTDERR RT_BIT(3)
/**
* Structure for maintaining a guest session. This also
* contains all started threads (e.g. for guest processes).
*
* This structure can act in two different ways:
* - For legacy guest control handling (protocol version < 2)
* this acts as a per-guest process structure containing all
* the information needed to get a guest process up and running.
* - For newer guest control protocols (>= 2) this structure is
* part of the forked session child, maintaining all guest
* control objects under it.
*/
typedef struct VBOXSERVICECTRLSESSION
{
/* The session's startup information. */
VBGLR3GUESTCTRLSESSIONSTARTUPINFO
StartupInfo;
/** List of active guest process threads
* (VBOXSERVICECTRLPROCESS). */
RTLISTANCHOR lstProcesses;
/** Number of guest processes in the process list. */
uint32_t cProcesses;
/** List of guest control files (VBOXSERVICECTRLFILE). */
RTLISTANCHOR lstFiles;
/** Number of guest files in the file list. */
uint32_t cFiles;
/** The session's critical section. */
RTCRITSECT CritSect;
/** Internal session flags, not related
* to StartupInfo stuff.
* @sa VBOXSERVICECTRLSESSION_FLAG_* flags. */
uint32_t fFlags;
/** How many processes do we allow keeping around at a time? */
uint32_t uProcsMaxKept;
} VBOXSERVICECTRLSESSION;
/** Pointer to guest session. */
typedef VBOXSERVICECTRLSESSION *PVBOXSERVICECTRLSESSION;
/**
* Structure for holding data for one (started) guest process.
*/
typedef struct VBOXSERVICECTRLPROCESS
{
/** Node. */
RTLISTNODE Node;
/** Process handle. */
RTPROCESS hProcess;
/** Number of references using this struct. */
uint32_t cRefs;
/** The worker thread. */
RTTHREAD Thread;
/** The session this guest process
* is bound to. */
PVBOXSERVICECTRLSESSION pSession;
/** Shutdown indicator; will be set when the thread
* needs (or is asked) to shutdown. */
bool volatile fShutdown;
/** Whether the guest process thread was stopped or not. */
bool volatile fStopped;
/** Whether the guest process thread was started or not. */
bool fStarted;
/** Context ID. */
uint32_t uContextID;
/** Critical section for thread-safe use. */
RTCRITSECT CritSect;
/** Process startup information. */
PVBGLR3GUESTCTRLPROCSTARTUPINFO
pStartupInfo;
/** The process' PID assigned by the guest OS. */
uint32_t uPID;
/** The process' request queue to handle requests
* from the outside, e.g. the session. */
RTREQQUEUE hReqQueue;
/** Our pollset, used for accessing the process'
* std* pipes + the notification pipe. */
RTPOLLSET hPollSet;
/** StdIn pipe for addressing writes to the
* guest process' stdin.*/
RTPIPE hPipeStdInW;
/** StdOut pipe for addressing reads from
* guest process' stdout.*/
RTPIPE hPipeStdOutR;
/** StdOut pipe for addressing reads from
* guest process' stderr.*/
RTPIPE hPipeStdErrR;
/** The write end of the notification pipe that is used to poke the thread
* monitoring the process.
* This is NIL_RTPIPE for output pipes. */
RTPIPE hNotificationPipeW;
/** The other end of hNotificationPipeW, read by vgsvcGstCtrlProcessProcLoop(). */
RTPIPE hNotificationPipeR;
} VBOXSERVICECTRLPROCESS;
/** Pointer to thread data. */
typedef VBOXSERVICECTRLPROCESS *PVBOXSERVICECTRLPROCESS;
RT_C_DECLS_BEGIN
extern RTLISTANCHOR g_lstControlSessionThreads;
extern VBOXSERVICECTRLSESSION g_Session;
extern uint32_t g_idControlSvcClient;
extern uint64_t g_fControlHostFeatures0;
extern bool g_fControlSupportsOptimizations;
/** @name Guest session thread handling.
* @{ */
extern int VGSvcGstCtrlSessionThreadCreate(PRTLISTANCHOR pList, const PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pSessionStartupInfo, PVBOXSERVICECTRLSESSIONTHREAD *ppSessionThread);
extern int VGSvcGstCtrlSessionThreadDestroy(PVBOXSERVICECTRLSESSIONTHREAD pSession, uint32_t uFlags);
extern int VGSvcGstCtrlSessionThreadDestroyAll(PRTLISTANCHOR pList, uint32_t uFlags);
extern int VGSvcGstCtrlSessionThreadTerminate(PVBOXSERVICECTRLSESSIONTHREAD pSession);
extern RTEXITCODE VGSvcGstCtrlSessionSpawnInit(int argc, char **argv);
/** @} */
/** @name Per-session functions.
* @{ */
extern PVBOXSERVICECTRLPROCESS VGSvcGstCtrlSessionRetainProcess(PVBOXSERVICECTRLSESSION pSession, uint32_t uPID);
extern int VGSvcGstCtrlSessionClose(PVBOXSERVICECTRLSESSION pSession);
extern int VGSvcGstCtrlSessionDestroy(PVBOXSERVICECTRLSESSION pSession);
extern int VGSvcGstCtrlSessionInit(PVBOXSERVICECTRLSESSION pSession, uint32_t uFlags);
extern int VGSvcGstCtrlSessionHandler(PVBOXSERVICECTRLSESSION pSession, uint32_t uMsg, PVBGLR3GUESTCTRLCMDCTX pHostCtx, void *pvScratchBuf, size_t cbScratchBuf, volatile bool *pfShutdown);
extern int VGSvcGstCtrlSessionProcessAdd(PVBOXSERVICECTRLSESSION pSession, PVBOXSERVICECTRLPROCESS pProcess);
extern int VGSvcGstCtrlSessionProcessRemove(PVBOXSERVICECTRLSESSION pSession, PVBOXSERVICECTRLPROCESS pProcess);
extern int VGSvcGstCtrlSessionProcessStartAllowed(const PVBOXSERVICECTRLSESSION pSession, bool *pfAllowed);
extern int VGSvcGstCtrlSessionReapProcesses(PVBOXSERVICECTRLSESSION pSession);
/** @} */
/** @name Per-guest process functions.
* @{ */
extern int VGSvcGstCtrlProcessFree(PVBOXSERVICECTRLPROCESS pProcess);
extern int VGSvcGstCtrlProcessHandleInput(PVBOXSERVICECTRLPROCESS pProcess, PVBGLR3GUESTCTRLCMDCTX pHostCtx, bool fPendingClose, void *pvBuf, uint32_t cbBuf);
extern int VGSvcGstCtrlProcessHandleOutput(PVBOXSERVICECTRLPROCESS pProcess, PVBGLR3GUESTCTRLCMDCTX pHostCtx, uint32_t uHandle, uint32_t cbToRead, uint32_t uFlags);
extern int VGSvcGstCtrlProcessHandleTerm(PVBOXSERVICECTRLPROCESS pProcess);
extern void VGSvcGstCtrlProcessRelease(PVBOXSERVICECTRLPROCESS pProcess);
extern int VGSvcGstCtrlProcessStart(const PVBOXSERVICECTRLSESSION pSession, const PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo, uint32_t uContext);
extern int VGSvcGstCtrlProcessStop(PVBOXSERVICECTRLPROCESS pProcess);
extern int VGSvcGstCtrlProcessWait(const PVBOXSERVICECTRLPROCESS pProcess, RTMSINTERVAL msTimeout, int *pRc);
/** @} */
RT_C_DECLS_END
#endif /* !GA_INCLUDED_SRC_common_VBoxService_VBoxServiceControl_h */
|