VirtualBox

source: vbox/trunk/src/VBox/Main/include/MediumImpl.h

Last change on this file was 98846, checked in by vboxsync, 14 months ago

Main/Medium+VirtualBox: If Medium::close() and VirtualBox::i_registerMedium()
are running concurrently they can wrestle over the media tree lock and
end up registering a medium which is in the process of being closed. If
both of the respective threads are operating on the same medium then there
is a window of opportunity when Medium::i_close() drops the media tree
lock before calling Medium::uninit() that VirtualBox::i_registerMedium()
can grab the lock and register the medium. The fix is to check whether
the medium is in the process of being closed inside i_registerMedium()
and bail out if so to maintain media registry consistency. bugref:6447

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.8 KB
Line 
1/* $Id: MediumImpl.h 98846 2023-03-06 18:56:23Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2008-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#ifndef MAIN_INCLUDED_MediumImpl_h
29#define MAIN_INCLUDED_MediumImpl_h
30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
34#include <VBox/vd.h>
35#include "MediumWrap.h"
36#include "VirtualBoxBase.h"
37#include "AutoCaller.h"
38#include "SecretKeyStore.h"
39class Progress;
40class MediumFormat;
41class MediumLockList;
42struct MediumCryptoFilterSettings;
43
44namespace settings
45{
46 struct Medium;
47}
48
49////////////////////////////////////////////////////////////////////////////////
50
51/**
52 * Medium component class for all media types.
53 */
54class ATL_NO_VTABLE Medium :
55 public MediumWrap
56{
57public:
58 DECLARE_COMMON_CLASS_METHODS(Medium)
59
60 HRESULT FinalConstruct();
61 void FinalRelease();
62
63 enum HDDOpenMode { OpenReadWrite, OpenReadOnly };
64 // have to use a special enum for the overloaded init() below;
65 // can't use AccessMode_T from XIDL because that's mapped to an int
66 // and would be ambiguous
67
68 // public initializer/uninitializer for internal purposes only
69
70 // initializer to create empty medium (VirtualBox::CreateMedium())
71 HRESULT init(VirtualBox *aVirtualBox,
72 const Utf8Str &aFormat,
73 const Utf8Str &aLocation,
74 const Guid &uuidMachineRegistry,
75 const DeviceType_T aDeviceType);
76
77 // initializer for opening existing media
78 // (VirtualBox::OpenMedium(); Machine::AttachDevice())
79 HRESULT init(VirtualBox *aVirtualBox,
80 const Utf8Str &aLocation,
81 HDDOpenMode enOpenMode,
82 bool fForceNewUuid,
83 DeviceType_T aDeviceType);
84
85 // initializer used when loading settings
86 HRESULT initOne(Medium *aParent,
87 DeviceType_T aDeviceType,
88 const Guid &uuidMachineRegistry,
89 const Utf8Str &strMachineFolder,
90 const settings::Medium &data);
91 static HRESULT initFromSettings(VirtualBox *aVirtualBox,
92 DeviceType_T aDeviceType,
93 const Guid &uuidMachineRegistry,
94 const Utf8Str &strMachineFolder,
95 const settings::Medium &data,
96 AutoWriteLock &mediaTreeLock,
97 std::list<std::pair<Guid, DeviceType_T> > &uIdsForNotify);
98
99 // initializer for host floppy/DVD
100 HRESULT init(VirtualBox *aVirtualBox,
101 DeviceType_T aDeviceType,
102 const Utf8Str &aLocation,
103 const Utf8Str &aDescription = Utf8Str::Empty);
104
105 void uninit();
106
107 void i_deparent();
108 void i_setParent(const ComObjPtr<Medium> &pParent);
109
110 // unsafe methods for internal purposes only (ensure there is
111 // a caller and a read lock before calling them!)
112 const ComObjPtr<Medium>& i_getParent() const;
113 const MediaList& i_getChildren() const;
114
115 const Guid& i_getId() const;
116 MediumState_T i_getState() const;
117 MediumVariant_T i_getVariant() const;
118 bool i_isHostDrive() const;
119 bool i_isClosing() const;
120 const Utf8Str& i_getLocationFull() const;
121 const Utf8Str& i_getFormat() const;
122 const ComObjPtr<MediumFormat> & i_getMediumFormat() const;
123 bool i_isMediumFormatFile() const;
124 uint64_t i_getSize() const;
125 uint64_t i_getLogicalSize() const;
126 DeviceType_T i_getDeviceType() const;
127 MediumType_T i_getType() const;
128 Utf8Str i_getName();
129
130 /* handles caller/locking itself */
131 bool i_addRegistry(const Guid &id);
132 bool i_addRegistryNoCallerCheck(const Guid &id);
133 /* handles caller/locking itself, caller is responsible for tree lock */
134 bool i_addRegistryAll(const Guid &id);
135 /* handles caller/locking itself */
136 bool i_removeRegistry(const Guid& id);
137 /* handles caller/locking itself, caller is responsible for tree lock */
138 bool i_removeRegistryAll(const Guid& id);
139 bool i_isInRegistry(const Guid& id);
140 bool i_getFirstRegistryMachineId(Guid &uuid) const;
141 void i_markRegistriesModified();
142
143 HRESULT i_setPropertyDirect(const Utf8Str &aName, const Utf8Str &aValue);
144
145 HRESULT i_addBackReference(const Guid &aMachineId,
146 const Guid &aSnapshotId = Guid::Empty);
147 HRESULT i_removeBackReference(const Guid &aMachineId,
148 const Guid &aSnapshotId = Guid::Empty);
149
150
151 const Guid* i_getFirstMachineBackrefId() const;
152 const Guid* i_getAnyMachineBackref(const Guid &aId) const;
153 const Guid* i_getFirstMachineBackrefSnapshotId() const;
154 size_t i_getMachineBackRefCount() const;
155
156#ifdef DEBUG
157 void i_dumpBackRefs();
158#endif
159
160 HRESULT i_updatePath(const Utf8Str &strOldPath, const Utf8Str &strNewPath);
161
162 /* handles caller/locking itself */
163 ComObjPtr<Medium> i_getBase(uint32_t *aLevel = NULL);
164 /* handles caller/locking itself */
165 uint32_t i_getDepth();
166
167 bool i_isReadOnly();
168 void i_updateId(const Guid &id);
169
170 void i_saveSettingsOne(settings::Medium &data,
171 const Utf8Str &strHardDiskFolder);
172 HRESULT i_saveSettings(settings::Medium &data,
173 const Utf8Str &strHardDiskFolder);
174
175 HRESULT i_createMediumLockList(bool fFailIfInaccessible,
176 Medium *pToLock,
177 bool fMediumLockWriteAll,
178 Medium *pToBeParent,
179 MediumLockList &mediumLockList);
180
181 HRESULT i_createDiffStorage(ComObjPtr<Medium> &aTarget,
182 MediumVariant_T aVariant,
183 MediumLockList *pMediumLockList,
184 ComObjPtr<Progress> *aProgress,
185 bool aWait,
186 bool aNotify);
187 Utf8Str i_getPreferredDiffFormat();
188 MediumVariant_T i_getPreferredDiffVariant();
189
190 HRESULT i_close(AutoCaller &autoCaller);
191 HRESULT i_unlockRead(MediumState_T *aState);
192 HRESULT i_unlockWrite(MediumState_T *aState);
193 HRESULT i_deleteStorage(ComObjPtr<Progress> *aProgress, bool aWait, bool aNotify);
194 HRESULT i_markForDeletion();
195 HRESULT i_unmarkForDeletion();
196 HRESULT i_markLockedForDeletion();
197 HRESULT i_unmarkLockedForDeletion();
198
199 HRESULT i_queryPreferredMergeDirection(const ComObjPtr<Medium> &pOther,
200 bool &fMergeForward);
201
202 HRESULT i_prepareMergeTo(const ComObjPtr<Medium> &pTarget,
203 const Guid *aMachineId,
204 const Guid *aSnapshotId,
205 bool fLockMedia,
206 bool &fMergeForward,
207 ComObjPtr<Medium> &pParentForTarget,
208 MediumLockList * &aChildrenToReparent,
209 MediumLockList * &aMediumLockList);
210 HRESULT i_mergeTo(const ComObjPtr<Medium> &pTarget,
211 bool fMergeForward,
212 const ComObjPtr<Medium> &pParentForTarget,
213 MediumLockList *aChildrenToReparent,
214 MediumLockList *aMediumLockList,
215 ComObjPtr<Progress> *aProgress,
216 bool aWait,
217 bool aNotify);
218 void i_cancelMergeTo(MediumLockList *aChildrenToReparent,
219 MediumLockList *aMediumLockList);
220
221 HRESULT i_resize(uint64_t aLogicalSize,
222 MediumLockList *aMediumLockList,
223 ComObjPtr<Progress> *aProgress,
224 bool aWait,
225 bool aNotify);
226
227 HRESULT i_fixParentUuidOfChildren(MediumLockList *pChildrenToReparent);
228
229 HRESULT i_addRawToFss(const char *aFilename, SecretKeyStore *pKeyStore, RTVFSFSSTREAM hVfsFssDst,
230 const ComObjPtr<Progress> &aProgress, bool fSparse);
231
232 HRESULT i_exportFile(const char *aFilename,
233 const ComObjPtr<MediumFormat> &aFormat,
234 MediumVariant_T aVariant,
235 SecretKeyStore *pKeyStore,
236 RTVFSIOSTREAM hVfsIosDst,
237 const ComObjPtr<Progress> &aProgress);
238 HRESULT i_importFile(const char *aFilename,
239 const ComObjPtr<MediumFormat> &aFormat,
240 MediumVariant_T aVariant,
241 RTVFSIOSTREAM hVfsIosSrc,
242 const ComObjPtr<Medium> &aParent,
243 const ComObjPtr<Progress> &aProgress,
244 bool aNotify);
245
246 HRESULT i_cloneToEx(const ComObjPtr<Medium> &aTarget, MediumVariant_T aVariant,
247 const ComObjPtr<Medium> &aParent, IProgress **aProgress,
248 uint32_t idxSrcImageSame, uint32_t idxDstImageSame, bool aNotify);
249
250 const Utf8Str& i_getKeyId();
251
252 HRESULT i_openForIO(bool fWritable, SecretKeyStore *pKeyStore, PVDISK *ppHdd, MediumLockList *pMediumLockList,
253 struct MediumCryptoFilterSettings *pCryptoSettings);
254
255private:
256
257 // wrapped IMedium properties
258 HRESULT getId(com::Guid &aId);
259 HRESULT getDescription(AutoCaller &autoCaller, com::Utf8Str &aDescription);
260 HRESULT setDescription(AutoCaller &autoCaller, const com::Utf8Str &aDescription);
261 HRESULT getState(MediumState_T *aState);
262 HRESULT getVariant(std::vector<MediumVariant_T> &aVariant);
263 HRESULT getLocation(com::Utf8Str &aLocation);
264 HRESULT setLocation(const com::Utf8Str &aLocation);
265 HRESULT getName(com::Utf8Str &aName);
266 HRESULT getDeviceType(DeviceType_T *aDeviceType);
267 HRESULT getHostDrive(BOOL *aHostDrive);
268 HRESULT getSize(LONG64 *aSize);
269 HRESULT getFormat(com::Utf8Str &aFormat);
270 HRESULT getMediumFormat(ComPtr<IMediumFormat> &aMediumFormat);
271 HRESULT getType(AutoCaller &autoCaller, MediumType_T *aType);
272 HRESULT setType(AutoCaller &autoCaller, MediumType_T aType);
273 HRESULT getAllowedTypes(std::vector<MediumType_T> &aAllowedTypes);
274 HRESULT getParent(AutoCaller &autoCaller, ComPtr<IMedium> &aParent);
275 HRESULT getChildren(AutoCaller &autoCaller, std::vector<ComPtr<IMedium> > &aChildren);
276 HRESULT getBase(AutoCaller &autoCaller, ComPtr<IMedium> &aBase);
277 HRESULT getReadOnly(AutoCaller &autoCaller, BOOL *aReadOnly);
278 HRESULT getLogicalSize(LONG64 *aLogicalSize);
279 HRESULT getAutoReset(BOOL *aAutoReset);
280 HRESULT setAutoReset(BOOL aAutoReset);
281 HRESULT getLastAccessError(com::Utf8Str &aLastAccessError);
282 HRESULT getMachineIds(std::vector<com::Guid> &aMachineIds);
283
284 // wrapped IMedium methods
285 HRESULT setIds(AutoCaller &aAutoCaller,
286 BOOL aSetImageId,
287 const com::Guid &aImageId,
288 BOOL aSetParentId,
289 const com::Guid &aParentId);
290 HRESULT refreshState(AutoCaller &aAutoCaller,
291 MediumState_T *aState);
292 HRESULT getSnapshotIds(const com::Guid &aMachineId,
293 std::vector<com::Guid> &aSnapshotIds);
294 HRESULT lockRead(ComPtr<IToken> &aToken);
295 HRESULT lockWrite(ComPtr<IToken> &aToken);
296 HRESULT close(AutoCaller &aAutoCaller);
297 HRESULT getProperty(const com::Utf8Str &aName,
298 com::Utf8Str &aValue);
299 HRESULT setProperty(const com::Utf8Str &aName,
300 const com::Utf8Str &aValue);
301 HRESULT getProperties(const com::Utf8Str &aNames,
302 std::vector<com::Utf8Str> &aReturnNames,
303 std::vector<com::Utf8Str> &aReturnValues);
304 HRESULT setProperties(const std::vector<com::Utf8Str> &aNames,
305 const std::vector<com::Utf8Str> &aValues);
306 HRESULT createBaseStorage(LONG64 aLogicalSize,
307 const std::vector<MediumVariant_T> &aVariant,
308 ComPtr<IProgress> &aProgress);
309 HRESULT deleteStorage(ComPtr<IProgress> &aProgress);
310 HRESULT createDiffStorage(AutoCaller &autoCaller,
311 const ComPtr<IMedium> &aTarget,
312 const std::vector<MediumVariant_T> &aVariant,
313 ComPtr<IProgress> &aProgress);
314 HRESULT mergeTo(const ComPtr<IMedium> &aTarget,
315 ComPtr<IProgress> &aProgress);
316 HRESULT cloneTo(const ComPtr<IMedium> &aTarget,
317 const std::vector<MediumVariant_T> &aVariant,
318 const ComPtr<IMedium> &aParent,
319 ComPtr<IProgress> &aProgress);
320 HRESULT resizeAndCloneTo(const ComPtr<IMedium> &aTarget,
321 LONG64 aLogicalSize,
322 const std::vector<MediumVariant_T> &aVariant,
323 const ComPtr<IMedium> &aParent,
324 ComPtr<IProgress> &aProgress);
325 HRESULT cloneToBase(const ComPtr<IMedium> &aTarget,
326 const std::vector<MediumVariant_T> &aVariant,
327 ComPtr<IProgress> &aProgress);
328 HRESULT moveTo(AutoCaller &autoCaller,
329 const com::Utf8Str &aLocation,
330 ComPtr<IProgress> &aProgress);
331 HRESULT compact(ComPtr<IProgress> &aProgress);
332 HRESULT resize(LONG64 aLogicalSize,
333 ComPtr<IProgress> &aProgress);
334 HRESULT reset(AutoCaller &autoCaller, ComPtr<IProgress> &aProgress);
335 HRESULT changeEncryption(const com::Utf8Str &aCurrentPassword, const com::Utf8Str &aCipher,
336 const com::Utf8Str &aNewPassword, const com::Utf8Str &aNewPasswordId,
337 ComPtr<IProgress> &aProgress);
338 HRESULT getEncryptionSettings(AutoCaller &autoCaller, com::Utf8Str &aCipher, com::Utf8Str &aPasswordId);
339 HRESULT checkEncryptionPassword(const com::Utf8Str &aPassword);
340 HRESULT openForIO(BOOL aWritable, com::Utf8Str const &aPassword, ComPtr<IMediumIO> &aMediumIO);
341
342 // Private internal nmethods
343 HRESULT i_queryInfo(bool fSetImageId, bool fSetParentId, AutoCaller &autoCaller);
344 HRESULT i_canClose();
345 HRESULT i_unregisterWithVirtualBox();
346 HRESULT i_setStateError();
347 HRESULT i_setLocation(const Utf8Str &aLocation, const Utf8Str &aFormat = Utf8Str::Empty);
348 HRESULT i_setFormat(const Utf8Str &aFormat);
349 VDTYPE i_convertDeviceType();
350 DeviceType_T i_convertToDeviceType(VDTYPE enmType);
351 Utf8Str i_vdError(int aVRC);
352
353 bool i_isPropertyForFilter(const com::Utf8Str &aName);
354
355 HRESULT i_getFilterProperties(std::vector<com::Utf8Str> &aReturnNames,
356 std::vector<com::Utf8Str> &aReturnValues);
357
358 HRESULT i_preparationForMoving(const Utf8Str &aLocation);
359 bool i_isMoveOperation(const ComObjPtr<Medium> &pTarget) const;
360 bool i_resetMoveOperationData();
361 Utf8Str i_getNewLocationForMoving() const;
362
363 static DECLCALLBACK(void) i_vdErrorCall(void *pvUser, int vrc, RT_SRC_POS_DECL,
364 const char *pszFormat, va_list va);
365 static DECLCALLBACK(bool) i_vdConfigAreKeysValid(void *pvUser,
366 const char *pszzValid);
367 static DECLCALLBACK(int) i_vdConfigQuerySize(void *pvUser, const char *pszName,
368 size_t *pcbValue);
369 static DECLCALLBACK(int) i_vdConfigUpdate(void *pvUser, bool fCreate,
370 const char *pszName, const char *pszValue);
371
372 static DECLCALLBACK(int) i_vdConfigQuery(void *pvUser, const char *pszName,
373 char *pszValue, size_t cchValue);
374
375 static DECLCALLBACK(bool) i_vdCryptoConfigAreKeysValid(void *pvUser,
376 const char *pszzValid);
377 static DECLCALLBACK(int) i_vdCryptoConfigQuerySize(void *pvUser, const char *pszName,
378 size_t *pcbValue);
379 static DECLCALLBACK(int) i_vdCryptoConfigQuery(void *pvUser, const char *pszName,
380 char *pszValue, size_t cchValue);
381
382 static DECLCALLBACK(int) i_vdCryptoKeyRetain(void *pvUser, const char *pszId,
383 const uint8_t **ppbKey, size_t *pcbKey);
384 static DECLCALLBACK(int) i_vdCryptoKeyRelease(void *pvUser, const char *pszId);
385 static DECLCALLBACK(int) i_vdCryptoKeyStorePasswordRetain(void *pvUser, const char *pszId, const char **ppszPassword);
386 static DECLCALLBACK(int) i_vdCryptoKeyStorePasswordRelease(void *pvUser, const char *pszId);
387 static DECLCALLBACK(int) i_vdCryptoKeyStoreSave(void *pvUser, const void *pvKeyStore, size_t cbKeyStore);
388 static DECLCALLBACK(int) i_vdCryptoKeyStoreReturnParameters(void *pvUser, const char *pszCipher,
389 const uint8_t *pbDek, size_t cbDek);
390
391 class Task;
392 class CreateBaseTask;
393 class CreateDiffTask;
394 class CloneTask;
395 class MoveTask;
396 class CompactTask;
397 class ResizeTask;
398 class ResetTask;
399 class DeleteTask;
400 class MergeTask;
401 class ImportTask;
402 class EncryptTask;
403 friend class Task;
404 friend class CreateBaseTask;
405 friend class CreateDiffTask;
406 friend class CloneTask;
407 friend class MoveTask;
408 friend class CompactTask;
409 friend class ResizeTask;
410 friend class ResetTask;
411 friend class DeleteTask;
412 friend class MergeTask;
413 friend class ImportTask;
414 friend class EncryptTask;
415
416 HRESULT i_taskCreateBaseHandler(Medium::CreateBaseTask &task);
417 HRESULT i_taskCreateDiffHandler(Medium::CreateDiffTask &task);
418 HRESULT i_taskMergeHandler(Medium::MergeTask &task);
419 HRESULT i_taskCloneHandler(Medium::CloneTask &task);
420 HRESULT i_taskMoveHandler(Medium::MoveTask &task);
421 HRESULT i_taskDeleteHandler(Medium::DeleteTask &task);
422 HRESULT i_taskResetHandler(Medium::ResetTask &task);
423 HRESULT i_taskCompactHandler(Medium::CompactTask &task);
424 HRESULT i_taskResizeHandler(Medium::ResizeTask &task);
425 HRESULT i_taskImportHandler(Medium::ImportTask &task);
426 HRESULT i_taskEncryptHandler(Medium::EncryptTask &task);
427
428 void i_taskEncryptSettingsSetup(struct MediumCryptoFilterSettings *pSettings, const char *pszCipher,
429 const char *pszKeyStore, const char *pszPassword,
430 bool fCreateKeyStore);
431
432 struct Data; // opaque data struct, defined in MediumImpl.cpp
433 Data *m;
434};
435
436
437/**
438 * Settings for a crypto filter instance.
439 */
440struct MediumCryptoFilterSettings
441{
442 MediumCryptoFilterSettings()
443 : fCreateKeyStore(false),
444 pszPassword(NULL),
445 pszKeyStore(NULL),
446 pszKeyStoreLoad(NULL),
447 pbDek(NULL),
448 cbDek(0),
449 pszCipher(NULL),
450 pszCipherReturned(NULL)
451 { }
452
453 bool fCreateKeyStore;
454 const char *pszPassword;
455 char *pszKeyStore;
456 const char *pszKeyStoreLoad;
457
458 const uint8_t *pbDek;
459 size_t cbDek;
460 const char *pszCipher;
461
462 /** The cipher returned by the crypto filter. */
463 char *pszCipherReturned;
464
465 PVDINTERFACE vdFilterIfaces;
466
467 VDINTERFACECONFIG vdIfCfg;
468 VDINTERFACECRYPTO vdIfCrypto;
469};
470
471
472
473#endif /* !MAIN_INCLUDED_MediumImpl_h */
474
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use