VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/ClientToken.cpp@ 57485

Last change on this file since 57485 was 55401, checked in by vboxsync, 10 years ago

added a couple of missing Id headers

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.1 KB
Line 
1/* $Id: ClientToken.cpp 55401 2015-04-23 10:03:17Z vboxsync $ */
2/** @file
3 *
4 * VirtualBox API client session crash token handling
5 */
6
7/*
8 * Copyright (C) 2004-2013 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include <iprt/asm.h>
20#include <iprt/assert.h>
21#include <iprt/log.h>
22#include <iprt/semaphore.h>
23#include <iprt/process.h>
24
25#ifdef VBOX_WITH_SYS_V_IPC_SESSION_WATCHER
26# include <errno.h>
27# include <sys/types.h>
28# include <sys/stat.h>
29# include <sys/ipc.h>
30# include <sys/sem.h>
31#endif
32
33#include <VBox/com/defs.h>
34
35#include <vector>
36
37#include "VirtualBoxBase.h"
38#include "AutoCaller.h"
39#include "ClientToken.h"
40#include "MachineImpl.h"
41
42Machine::ClientToken::ClientToken()
43{
44 AssertReleaseFailed();
45}
46
47Machine::ClientToken::~ClientToken()
48{
49#if defined(RT_OS_WINDOWS)
50 if (mClientToken)
51 ::CloseHandle(mClientToken);
52#elif defined(RT_OS_OS2)
53 if (mClientToken != NULLHANDLE)
54 ::DosCloseMutexSem(mClientToken);
55#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
56 if (mClientToken >= 0)
57 ::semctl(mClientToken, 0, IPC_RMID);
58# ifdef VBOX_WITH_NEW_SYS_V_KEYGEN
59 mClientTokenId = "0";
60# endif /* VBOX_WITH_NEW_SYS_V_KEYGEN */
61#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
62 /* release the token, uses reference counting */
63 if (mClientToken)
64 {
65 if (!mClientTokenPassed)
66 mClientToken->Release();
67 mClientToken = NULL;
68 }
69#else
70# error "Port me!"
71#endif
72 mClientToken = CTTOKENARG;
73}
74
75Machine::ClientToken::ClientToken(const ComObjPtr<Machine> &pMachine,
76 SessionMachine *pSessionMachine) :
77 mMachine(pMachine)
78{
79#if defined(RT_OS_WINDOWS)
80 NOREF(pSessionMachine);
81 Bstr tokenId = pMachine->mData->m_strConfigFileFull;
82 for (size_t i = 0; i < tokenId.length(); i++)
83 if (tokenId.raw()[i] == '\\')
84 tokenId.raw()[i] = '/';
85 mClientToken = ::CreateMutex(NULL, FALSE, tokenId.raw());
86 mClientTokenId = tokenId;
87 AssertMsg(mClientToken,
88 ("Cannot create token '%s', err=%d",
89 mClientTokenId.c_str(), ::GetLastError()));
90#elif defined(RT_OS_OS2)
91 NOREF(pSessionMachine);
92 Utf8Str ipcSem = Utf8StrFmt("\\SEM32\\VBOX\\VM\\{%RTuuid}",
93 pMachine->mData->mUuid.raw());
94 mClientTokenId = ipcSem;
95 APIRET arc = ::DosCreateMutexSem((PSZ)ipcSem.c_str(), &mClientToken, 0, FALSE);
96 AssertMsg(arc == NO_ERROR,
97 ("Cannot create token '%s', arc=%ld",
98 ipcSem.c_str(), arc));
99#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
100 NOREF(pSessionMachine);
101# ifdef VBOX_WITH_NEW_SYS_V_KEYGEN
102# if defined(RT_OS_FREEBSD) && (HC_ARCH_BITS == 64)
103 /** @todo Check that this still works correctly. */
104 AssertCompileSize(key_t, 8);
105# else
106 AssertCompileSize(key_t, 4);
107# endif
108 key_t key;
109 mClientToken = -1;
110 mClientTokenId = "0";
111 for (uint32_t i = 0; i < 1 << 24; i++)
112 {
113 key = ((uint32_t)'V' << 24) | i;
114 int sem = ::semget(key, 1, S_IRUSR | S_IWUSR | IPC_CREAT | IPC_EXCL);
115 if (sem >= 0 || (errno != EEXIST && errno != EACCES))
116 {
117 mClientToken = sem;
118 if (sem >= 0)
119 mClientTokenId = BstrFmt("%u", key);
120 break;
121 }
122 }
123# else /* !VBOX_WITH_NEW_SYS_V_KEYGEN */
124 Utf8Str semName = pMachine->mData->m_strConfigFileFull;
125 char *pszSemName = NULL;
126 RTStrUtf8ToCurrentCP(&pszSemName, semName);
127 key_t key = ::ftok(pszSemName, 'V');
128 RTStrFree(pszSemName);
129
130 mClientToken = ::semget(key, 1, S_IRWXU | S_IRWXG | S_IRWXO | IPC_CREAT);
131# endif /* !VBOX_WITH_NEW_SYS_V_KEYGEN */
132
133 int errnoSave = errno;
134 if (mClientToken < 0 && errnoSave == ENOSYS)
135 {
136 mMachine->setError(E_FAIL,
137 tr("Cannot create IPC semaphore. Most likely your host kernel lacks "
138 "support for SysV IPC. Check the host kernel configuration for "
139 "CONFIG_SYSVIPC=y"));
140 mClientToken = CTTOKENARG;
141 return;
142 }
143 /* ENOSPC can also be the result of VBoxSVC crashes without properly freeing
144 * the token */
145 if (mClientToken < 0 && errnoSave == ENOSPC)
146 {
147#ifdef RT_OS_LINUX
148 mMachine->setError(E_FAIL,
149 tr("Cannot create IPC semaphore because the system limit for the "
150 "maximum number of semaphore sets (SEMMNI), or the system wide "
151 "maximum number of semaphores (SEMMNS) would be exceeded. The "
152 "current set of SysV IPC semaphores can be determined from "
153 "the file /proc/sysvipc/sem"));
154#else
155 mMachine->setError(E_FAIL,
156 tr("Cannot create IPC semaphore because the system-imposed limit "
157 "on the maximum number of allowed semaphores or semaphore "
158 "identifiers system-wide would be exceeded"));
159#endif
160 mClientToken = CTTOKENARG;
161 return;
162 }
163 AssertMsgReturnVoid(mClientToken >= 0, ("Cannot create token, errno=%d", errnoSave));
164 /* set the initial value to 1 */
165 int rv = ::semctl(mClientToken, 0, SETVAL, 1);
166 errnoSave = errno;
167 if (rv != 0)
168 {
169 ::semctl(mClientToken, 0, IPC_RMID);
170 mClientToken = CTTOKENARG;
171 AssertMsgFailedReturnVoid(("Cannot init token, errno=%d", errnoSave));
172 }
173#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
174 ComObjPtr<MachineToken> pToken;
175 HRESULT rc = pToken.createObject();
176 if (SUCCEEDED(rc))
177 {
178 rc = pToken->init(pSessionMachine);
179 if (SUCCEEDED(rc))
180 {
181 mClientToken = pToken;
182 if (mClientToken)
183 {
184 rc = mClientToken->AddRef();
185 if (FAILED(rc))
186 mClientToken = NULL;
187 }
188 }
189 }
190 pToken.setNull();
191 mClientTokenPassed = false;
192 /* mClientTokenId isn't really used */
193 mClientTokenId = pMachine->mData->m_strConfigFileFull;
194 AssertMsg(mClientToken,
195 ("Cannot create token '%s', rc=%Rhrc",
196 mClientTokenId.c_str(), rc));
197#else
198# error "Port me!"
199#endif
200}
201
202bool Machine::ClientToken::isReady()
203{
204 return mClientToken != CTTOKENARG;
205}
206
207void Machine::ClientToken::getId(Utf8Str &strId)
208{
209 strId = mClientTokenId;
210}
211
212CTTOKENTYPE Machine::ClientToken::getToken()
213{
214#ifdef VBOX_WITH_GENERIC_SESSION_WATCHER
215 mClientTokenPassed = true;
216#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
217 return mClientToken;
218}
219
220#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
221bool Machine::ClientToken::release()
222{
223 bool terminated = false;
224
225#if defined(RT_OS_WINDOWS)
226 AssertMsg(mClientToken, ("semaphore must be created"));
227
228 /* release the token */
229 ::ReleaseMutex(mClientToken);
230 terminated = true;
231#elif defined(RT_OS_OS2)
232 AssertMsg(mClientToken, ("semaphore must be created"));
233
234 /* release the token */
235 ::DosReleaseMutexSem(mClientToken);
236 terminated = true;
237#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
238 AssertMsg(mClientToken >= 0, ("semaphore must be created"));
239 int val = ::semctl(mClientToken, 0, GETVAL);
240 if (val > 0)
241 {
242 /* the semaphore is signaled, meaning the session is terminated */
243 terminated = true;
244 }
245#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
246 /** @todo r=klaus never tested, this code is not reached */
247 AssertMsg(mClientToken, ("token must be created"));
248 /* release the token, uses reference counting */
249 if (mClientToken)
250 {
251 if (!mClientTokenPassed)
252 mClientToken->Release();
253 mClientToken = NULL;
254 }
255 terminated = true;
256#else
257# error "Port me!"
258#endif
259 return terminated;
260}
261#endif /* !VBOX_WITH_GENERIC_SESSION_WATCHER */
262
263/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette