VirtualBox

source: vbox/trunk/src/VBox/Main/src-all/SharedFolderImpl.cpp@ 92154

Last change on this file since 92154 was 88637, checked in by vboxsync, 3 years ago

Main/SharedFolderImpl.cpp: Reject shared folder paths which have a
filename as their final component by performing additional pathname
vetting in the createSharedFolder() API back-end routine
SharedFolder::i_protectedInit().

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.5 KB
Line 
1/* $Id: SharedFolderImpl.cpp 88637 2021-04-21 22:11:34Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_MAIN_SHAREDFOLDER
19#include "SharedFolderImpl.h"
20#if !defined(VBOX_COM_INPROC)
21# include "VirtualBoxImpl.h"
22# include "MachineImpl.h"
23#endif
24#include "ConsoleImpl.h"
25
26#include "AutoCaller.h"
27
28#include <iprt/param.h>
29#include <iprt/cpp/utils.h>
30#include <iprt/path.h>
31
32/////////////////////////////////////////////////////////////////////////////
33// SharedFolder::Data structure
34/////////////////////////////////////////////////////////////////////////////
35
36struct SharedFolder::Data
37{
38 Data()
39 : fWritable(false),
40 fAutoMount(false)
41 { }
42
43 const Utf8Str strName;
44 const Utf8Str strHostPath;
45 bool fWritable;
46 bool fAutoMount;
47 const Utf8Str strAutoMountPoint;
48 Utf8Str strLastAccessError;
49};
50
51// constructor / destructor
52/////////////////////////////////////////////////////////////////////////////
53
54SharedFolder::SharedFolder()
55 : mParent(NULL),
56#if !defined(VBOX_COM_INPROC)
57 mMachine(NULL),
58 mVirtualBox(NULL)
59#else
60 mConsole(NULL)
61#endif
62{
63 m = new Data;
64}
65
66SharedFolder::~SharedFolder()
67{
68 delete m;
69 m = NULL;
70}
71
72HRESULT SharedFolder::FinalConstruct()
73{
74 return BaseFinalConstruct();
75}
76
77void SharedFolder::FinalRelease()
78{
79 uninit();
80 BaseFinalRelease();
81}
82
83// public initializer/uninitializer for internal purposes only
84/////////////////////////////////////////////////////////////////////////////
85
86#if !defined(VBOX_COM_INPROC)
87/**
88 * Initializes the shared folder object.
89 *
90 * This variant initializes a machine instance that lives in the server address space.
91 *
92 * @param aMachine parent Machine object
93 * @param aName logical name of the shared folder
94 * @param aHostPath full path to the shared folder on the host
95 * @param aWritable writable if true, readonly otherwise
96 * @param aAutoMount if auto mounted by guest true, false otherwise
97 * @param aAutoMountPoint Where the guest should try auto mount it.
98 * @param fFailOnError Whether to fail with an error if the shared folder path is bad.
99 *
100 * @return COM result indicator
101 */
102HRESULT SharedFolder::init(Machine *aMachine,
103 const Utf8Str &aName,
104 const Utf8Str &aHostPath,
105 bool aWritable,
106 bool aAutoMount,
107 const Utf8Str &aAutoMountPoint,
108 bool fFailOnError)
109{
110 /* Enclose the state transition NotReady->InInit->Ready */
111 AutoInitSpan autoInitSpan(this);
112 AssertReturn(autoInitSpan.isOk(), E_FAIL);
113
114 unconst(mMachine) = aMachine;
115
116 HRESULT rc = i_protectedInit(aMachine, aName, aHostPath, aWritable, aAutoMount, aAutoMountPoint, fFailOnError);
117
118 /* Confirm a successful initialization when it's the case */
119 if (SUCCEEDED(rc))
120 autoInitSpan.setSucceeded();
121
122 return rc;
123}
124
125/**
126 * Initializes the shared folder object given another object
127 * (a kind of copy constructor). This object makes a private copy of data
128 * of the original object passed as an argument.
129 *
130 * @param aMachine parent Machine object
131 * @param aThat shared folder object to copy
132 *
133 * @return COM result indicator
134 */
135HRESULT SharedFolder::initCopy(Machine *aMachine, SharedFolder *aThat)
136{
137 ComAssertRet(aThat, E_INVALIDARG);
138
139 /* Enclose the state transition NotReady->InInit->Ready */
140 AutoInitSpan autoInitSpan(this);
141 AssertReturn(autoInitSpan.isOk(), E_FAIL);
142
143 unconst(mMachine) = aMachine;
144
145 HRESULT rc = i_protectedInit(aMachine,
146 aThat->m->strName,
147 aThat->m->strHostPath,
148 aThat->m->fWritable,
149 aThat->m->fAutoMount,
150 aThat->m->strAutoMountPoint,
151 false /* fFailOnError */ );
152
153 /* Confirm a successful initialization when it's the case */
154 if (SUCCEEDED(rc))
155 autoInitSpan.setSucceeded();
156
157 return rc;
158}
159
160# if 0
161
162/**
163 * Initializes the shared folder object.
164 *
165 * This variant initializes a global instance that lives in the server address space. It is not presently used.
166 *
167 * @param aVirtualBox VirtualBox parent object
168 * @param aName logical name of the shared folder
169 * @param aHostPath full path to the shared folder on the host
170 * @param aWritable writable if true, readonly otherwise
171 * @param aAutoMountPoint Where the guest should try auto mount it.
172 * @param fFailOnError Whether to fail with an error if the shared folder path is bad.
173 *
174 * @return COM result indicator
175 */
176HRESULT SharedFolder::init(VirtualBox *aVirtualBox,
177 const Utf8Str &aName,
178 const Utf8Str &aHostPath,
179 bool aWritable,
180 bool aAutoMount,
181 const Utf8Str &aAutoMountPoint
182 bool fFailOnError)
183{
184 /* Enclose the state transition NotReady->InInit->Ready */
185 AutoInitSpan autoInitSpan(this);
186 AssertReturn(autoInitSpan.isOk(), E_FAIL);
187
188 unconst(mVirtualBox) = aVirtualBox;
189
190 HRESULT rc = protectedInit(aVirtualBox, aName, aHostPath, aWritable, aAutoMount, aAutoMountPoint, fFailOnError);
191
192 /* Confirm a successful initialization when it's the case */
193 if (SUCCEEDED(rc))
194 autoInitSpan.setSucceeded();
195
196 return rc;
197}
198
199# endif
200
201#else
202
203/**
204 * Initializes the shared folder object.
205 *
206 * This variant initializes an instance that lives in the console address space.
207 *
208 * @param aConsole Console parent object
209 * @param aName logical name of the shared folder
210 * @param aHostPath full path to the shared folder on the host
211 * @param aWritable writable if true, readonly otherwise
212 * @param aAutoMountPoint Where the guest should try auto mount it.
213 * @param fFailOnError Whether to fail with an error if the shared folder path is bad.
214 *
215 * @return COM result indicator
216 */
217HRESULT SharedFolder::init(Console *aConsole,
218 const Utf8Str &aName,
219 const Utf8Str &aHostPath,
220 bool aWritable,
221 bool aAutoMount,
222 const Utf8Str &aAutoMountPoint,
223 bool fFailOnError)
224{
225 /* Enclose the state transition NotReady->InInit->Ready */
226 AutoInitSpan autoInitSpan(this);
227 AssertReturn(autoInitSpan.isOk(), E_FAIL);
228
229 unconst(mConsole) = aConsole;
230
231 HRESULT rc = i_protectedInit(aConsole, aName, aHostPath, aWritable, aAutoMount, aAutoMountPoint, fFailOnError);
232
233 /* Confirm a successful initialization when it's the case */
234 if (SUCCEEDED(rc))
235 autoInitSpan.setSucceeded();
236
237 return rc;
238}
239#endif
240
241/**
242 * Shared initialization code. Called from the other constructors.
243 *
244 * @note
245 * Must be called from under the object's lock!
246 */
247HRESULT SharedFolder::i_protectedInit(VirtualBoxBase *aParent,
248 const Utf8Str &aName,
249 const Utf8Str &aHostPath,
250 bool aWritable,
251 bool aAutoMount,
252 const Utf8Str &aAutoMountPoint,
253 bool fFailOnError)
254{
255 LogFlowThisFunc(("aName={%s}, aHostPath={%s}, aWritable={%d}, aAutoMount={%d}\n",
256 aName.c_str(), aHostPath.c_str(), aWritable, aAutoMount));
257
258 ComAssertRet(aParent && aName.isNotEmpty() && aHostPath.isNotEmpty(), E_INVALIDARG);
259
260 Utf8Str hostPath = aHostPath;
261 size_t hostPathLen = hostPath.length();
262
263 /* Remove the trailing slash unless it's a root directory
264 * (otherwise the comparison with the RTPathAbs() result will fail at least
265 * on Linux). Note that this isn't really necessary for the shared folder
266 * itself, since adding a mapping eventually results into a
267 * RTDirOpenFiltered() call (see HostServices/SharedFolders) that seems to
268 * accept both the slashified paths and not. */
269#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
270 if ( hostPathLen > 2
271 && RTPATH_IS_SEP(hostPath.c_str()[hostPathLen - 1])
272 && RTPATH_IS_VOLSEP(hostPath.c_str()[hostPathLen - 2]))
273 ;
274#else
275 if (hostPathLen == 1 && RTPATH_IS_SEP(hostPath[0]))
276 ;
277#endif
278 else
279 hostPath.stripTrailingSlash();
280
281 if (fFailOnError)
282 {
283 /* Check whether the path is full (absolute) */
284 char hostPathFull[RTPATH_MAX];
285 int vrc = RTPathAbs(hostPath.c_str(),
286 hostPathFull,
287 sizeof(hostPathFull));
288 if (RT_FAILURE(vrc))
289 return setErrorBoth(E_INVALIDARG, vrc, tr("Invalid shared folder path: '%s' (%Rrc)"), hostPath.c_str(), vrc);
290
291 if (RTPathCompare(hostPath.c_str(), hostPathFull) != 0)
292 return setError(E_INVALIDARG, tr("Shared folder path '%s' is not absolute"), hostPath.c_str());
293
294 RTFSOBJINFO ObjInfo;
295 vrc = RTPathQueryInfo(hostPathFull, &ObjInfo, RTFSOBJATTRADD_NOTHING);
296 if (RT_FAILURE(vrc))
297 return setError(E_INVALIDARG, tr("RTPathQueryInfo failed on shared folder path '%s': %Rrc"), hostPathFull, vrc);
298
299 if (!RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
300 return setError(E_INVALIDARG, tr("Shared folder path '%s' is not a directory"), hostPathFull);
301 }
302
303 unconst(mParent) = aParent;
304
305 unconst(m->strName) = aName;
306 unconst(m->strHostPath) = hostPath;
307 m->fWritable = aWritable;
308 m->fAutoMount = aAutoMount;
309 unconst(m->strAutoMountPoint) = aAutoMountPoint;
310
311 return S_OK;
312}
313
314/**
315 * Uninitializes the instance and sets the ready flag to FALSE.
316 * Called either from FinalRelease() or by the parent when it gets destroyed.
317 */
318void SharedFolder::uninit()
319{
320 LogFlowThisFunc(("\n"));
321
322 /* Enclose the state transition Ready->InUninit->NotReady */
323 AutoUninitSpan autoUninitSpan(this);
324 if (autoUninitSpan.uninitDone())
325 return;
326
327 unconst(mParent) = NULL;
328
329#if !defined(VBOX_COM_INPROC)
330 unconst(mMachine) = NULL;
331 unconst(mVirtualBox) = NULL;
332#else
333 unconst(mConsole) = NULL;
334#endif
335}
336
337// wrapped ISharedFolder properties
338/////////////////////////////////////////////////////////////////////////////
339HRESULT SharedFolder::getName(com::Utf8Str &aName)
340{
341 /* mName is constant during life time, no need to lock */
342 aName = m->strName;
343 return S_OK;
344}
345
346HRESULT SharedFolder::getHostPath(com::Utf8Str &aHostPath)
347{
348 /* mHostPath is constant during life time, no need to lock */
349 aHostPath = m->strHostPath;
350 return S_OK;
351}
352
353HRESULT SharedFolder::getAccessible(BOOL *aAccessible)
354{
355 /* mName and mHostPath are constant during life time, no need to lock */
356
357 /* check whether the host path exists */
358 Utf8Str hostPath = m->strHostPath;
359 char hostPathFull[RTPATH_MAX];
360 int vrc = RTPathExists(hostPath.c_str()) ? RTPathReal(hostPath.c_str(),
361 hostPathFull,
362 sizeof(hostPathFull))
363 : VERR_PATH_NOT_FOUND;
364 if (RT_SUCCESS(vrc))
365 {
366 *aAccessible = TRUE;
367 return S_OK;
368 }
369
370 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
371
372 m->strLastAccessError = Utf8StrFmt(tr("'%s' is not accessible (%Rrc)"),
373 m->strHostPath.c_str(),
374 vrc);
375
376 Log1WarningThisFunc(("m.lastAccessError=\"%s\"\n", m->strLastAccessError.c_str()));
377
378 *aAccessible = FALSE;
379
380 return S_OK;
381}
382
383HRESULT SharedFolder::getWritable(BOOL *aWritable)
384{
385 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
386 *aWritable = m->fWritable;
387 return S_OK;
388}
389
390HRESULT SharedFolder::setWritable(BOOL aWritable)
391{
392 RT_NOREF(aWritable);
393 return E_NOTIMPL;
394}
395
396HRESULT SharedFolder::getAutoMount(BOOL *aAutoMount)
397{
398 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
399 *aAutoMount = m->fAutoMount;
400 return S_OK;
401}
402
403HRESULT SharedFolder::setAutoMount(BOOL aAutoMount)
404{
405 RT_NOREF(aAutoMount);
406 return E_NOTIMPL;
407}
408
409HRESULT SharedFolder::getAutoMountPoint(com::Utf8Str &aAutoMountPoint)
410{
411 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
412 aAutoMountPoint = m->strAutoMountPoint;
413 return S_OK;
414}
415
416HRESULT SharedFolder::setAutoMountPoint(com::Utf8Str const &aAutoMountPoint)
417{
418 RT_NOREF(aAutoMountPoint);
419 return E_NOTIMPL;
420}
421
422HRESULT SharedFolder::getLastAccessError(com::Utf8Str &aLastAccessError)
423{
424 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
425 aLastAccessError = m->strLastAccessError;
426 return S_OK;
427}
428
429
430const Utf8Str& SharedFolder::i_getName() const
431{
432 return m->strName;
433}
434
435const Utf8Str& SharedFolder::i_getHostPath() const
436{
437 return m->strHostPath;
438}
439
440bool SharedFolder::i_isWritable() const
441{
442 return m->fWritable;
443}
444
445bool SharedFolder::i_isAutoMounted() const
446{
447 return m->fAutoMount;
448}
449
450const Utf8Str &SharedFolder::i_getAutoMountPoint() const
451{
452 return m->strAutoMountPoint;
453}
454
455/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use