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
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
|
/* $Id: VBoxServiceControl.h $ */
/** @file
* VBoxServiceControl.h - Internal guest control definitions.
*/
/*
* Copyright (C) 2013-2019 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#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 szName[RTPATH_MAX];
/** The file handle on the guest. */
RTFILE hFile;
/** File handle to identify this file. */
uint32_t uHandle;
/** Context ID. */
uint32_t uContextID;
} VBOXSERVICECTRLFILE;
/** Pointer to thread data. */
typedef VBOXSERVICECTRLFILE *PVBOXSERVICECTRLFILE;
typedef struct VBOXSERVICECTRLSESSIONSTARTUPINFO
{
/** The session's protocol version to use. */
uint32_t uProtocol;
/** The session's ID. */
uint32_t uSessionID;
/** User name (account) to start the guest session under. */
char szUser[GUESTPROCESS_MAX_USER_LEN];
/** Password of specified user name (account). */
char szPassword[GUESTPROCESS_MAX_PASSWORD_LEN];
/** Domain of the user account. */
char szDomain[GUESTPROCESS_MAX_DOMAIN_LEN];
/** Session creation flags.
* @sa VBOXSERVICECTRLSESSIONSTARTUPFLAG_* flags. */
uint32_t fFlags;
} VBOXSERVICECTRLSESSIONSTARTUPINFO;
/** Pointer to thread data. */
typedef VBOXSERVICECTRLSESSIONSTARTUPINFO *PVBOXSERVICECTRLSESSIONSTARTUPINFO;
/**
* 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. */
VBOXSERVICECTRLSESSIONSTARTUPINFO StartupInfo;
/** 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;
/** 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. */
VBOXSERVICECTRLSESSIONSTARTUPINFO
StartupInfo;
/** List of active guest process threads
* (VBOXSERVICECTRLPROCESS). */
RTLISTANCHOR lstProcesses;
/** List of guest control files (VBOXSERVICECTRLFILE). */
RTLISTANCHOR lstFiles;
/** 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 holding information for starting a guest
* process.
*/
typedef struct VBOXSERVICECTRLPROCSTARTUPINFO
{
/** Full qualified path of process to start (without arguments). */
char szCmd[GUESTPROCESS_MAX_CMD_LEN];
/** Process execution flags. @sa */
uint32_t uFlags;
/** Command line arguments. */
char szArgs[GUESTPROCESS_MAX_ARGS_LEN];
/** Number of arguments specified in pszArgs. */
uint32_t uNumArgs;
/** String of environment variables ("FOO=BAR") to pass to the process
* to start. */
char szEnv[GUESTPROCESS_MAX_ENV_LEN];
/** Size (in bytes) of environment variables block. */
uint32_t cbEnv;
/** Number of environment variables specified in pszEnv. */
uint32_t uNumEnvVars;
/** User name (account) to start the process under. */
char szUser[GUESTPROCESS_MAX_USER_LEN];
/** Password of specified user name (account). */
char szPassword[GUESTPROCESS_MAX_PASSWORD_LEN];
/** Domain to be used for authenticating the specified user name (account). */
char szDomain[GUESTPROCESS_MAX_DOMAIN_LEN];
/** Time limit (in ms) of the process' life time. */
uint32_t uTimeLimitMS;
/** Process priority. */
uint32_t uPriority;
/** Process affinity. At the moment we support
* up to 4 * 64 = 256 CPUs. */
uint64_t uAffinity[4];
/** Number of used process affinity blocks. */
uint32_t uNumAffinity;
} VBOXSERVICECTRLPROCSTARTUPINFO;
/** Pointer to a guest process block. */
typedef VBOXSERVICECTRLPROCSTARTUPINFO *PVBOXSERVICECTRLPROCSTARTUPINFO;
/**
* 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. */
VBOXSERVICECTRLPROCSTARTUPINFO
StartupInfo;
/** 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' stdout.*/
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 bool g_fControlSupportsOptimizations;
/** @name Guest session thread handling.
* @{ */
extern int VGSvcGstCtrlSessionThreadCreate(PRTLISTANCHOR pList, const PVBOXSERVICECTRLSESSIONSTARTUPINFO 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 *pbAllowed);
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 PVBOXSERVICECTRLPROCSTARTUPINFO 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 */
|