VirtualBox

Ignore:
Timestamp:
Mar 8, 2017 12:21:14 PM (8 years ago)
Author:
vboxsync
Message:

SharedFolders: additional check

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedFolders/vbsfpath.cpp

    r62790 r65993  
    363363
    364364
    365 /**
    366  * Check the given UTF-8 path for root escapes.
    367  *
    368  * Verify that the path is within the root directory of the mapping.  Count '..'
    369  * and other path components and check that we do not go over the root.
    370  *
    371  * @returns VBox status code.
    372  * @retval  VINF_SUCCESS
    373  * @retval  VERR_INVALID_NAME
    374  *
    375  * @param   pszPath         The (UTF-8) path to check.  Slashes has been convert
    376  *                          to host slashes by this time.
    377  *
    378  * @remarks This function assumes that the path will be appended to the root
    379  *          directory of the shared folder mapping.  Keep that in mind when
    380  *          checking absolute paths!
    381  */
    382 static int vbsfPathCheckRootEscape(const char *pszPath)
    383 {
    384     /*
    385      * Walk the path, component by component and check for escapes.
    386      */
    387 
    388     int cComponents = 0; /* How many normal path components. */
    389     int cParentDirs = 0; /* How many '..' components. */
    390 
    391     for (;;)
    392     {
    393         char ch;
    394 
    395         /* Skip leading path delimiters. */
    396         do
    397             ch = *pszPath++;
    398         while (RTPATH_IS_SLASH(ch));
    399         if (ch == '\0')
    400             return VINF_SUCCESS;
    401 
    402         /* Check if that is a dot component. */
    403         int cDots = 0;
    404         while (ch == '.')
    405         {
    406             cDots++;
    407             ch = *pszPath++;
    408         }
    409 
    410         if (   cDots >= 1
    411             && (ch == '\0' || RTPATH_IS_SLASH(ch)) )
    412         {
    413             if (cDots >= 2) /* Consider all multidots sequences as a 'parent dir'. */
    414             {
    415                 cParentDirs++;
    416 
    417                 /* Escaping? */
    418                 if (cParentDirs > cComponents)
    419                     return VERR_INVALID_NAME;
    420             }
    421             /* else: Single dot, nothing changes. */
    422         }
    423         else
    424         {
    425             /* Not a dot component, skip to the end of it. */
    426             while (ch != '\0' && !RTPATH_IS_SLASH(ch))
    427                 ch = *pszPath++;
    428             cComponents++;
    429         }
    430         Assert(cComponents >= cParentDirs);
    431 
    432         /* The end? */
    433         Assert(ch == '\0' || RTPATH_IS_SLASH(ch));
    434         if (ch == '\0')
    435             return VINF_SUCCESS;
    436     }
    437 }
    438 
    439365#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
    440366/* See MSDN "Naming Files, Paths, and Namespaces".
     
    609535         * Allocate enough memory to build the host full path from the root and the relative path.
    610536         */
    611         uint32_t cbFullPathAlloc = cbRootLen + 1 + cbGuestPath + 1; /* root + possible_slash + relative + 0 */
     537        const uint32_t cbFullPathAlloc = cbRootLen + 1 + cbGuestPath + 1; /* root + possible_slash + relative + 0 */
    612538        pszFullPath = (char *)RTMemAlloc(cbFullPathAlloc);
    613539        if (RT_LIKELY(pszFullPath != NULL))
    614540        {
    615             /* Copy the root. */
    616             memcpy(pszFullPath, pszRoot, cbRootLen);
    617             if (!RTPATH_IS_SLASH(pszFullPath[cbRootLen - 1]))
    618             {
    619                 pszFullPath[cbRootLen++] = RTPATH_SLASH;
    620             }
    621 
    622             /* Init the pointer for the relative path. */
    623             char *pchDst = &pszFullPath[cbRootLen];
    624 
    625             uint32_t cbSrc = cbGuestPath;
    626             const char *pchSrc = pchGuestPath;
    627 
    628             /* Strip leading delimiters from the path the guest specified. */
    629             while (   cbSrc > 0
    630                    && *pchSrc == pClient->PathDelimiter)
    631             {
    632                 ++pchSrc;
    633                 --cbSrc;
    634             }
    635 
    636             /*
    637              * Iterate the guest path components, verify each of them
    638              * and append to the host full path replacing delimiters with host slash.
    639              */
    640             bool fLastComponentHasWildcard = false;
    641             for (; cbSrc > 0; --cbSrc, ++pchSrc)
    642             {
    643                 if (RT_LIKELY(*pchSrc != pClient->PathDelimiter))
    644                 {
    645                     if (RT_LIKELY(vbsfPathIsValidNameChar(*pchSrc)))
     541            /* Buffer for the verified guest path. */
     542            char *pchVerifiedPath = (char *)RTMemAlloc(cbGuestPath + 1);
     543            if (RT_LIKELY(pchVerifiedPath != NULL))
     544            {
     545                /* Init the pointer for the guest relative path. */
     546                uint32_t cbSrc = cbGuestPath;
     547                const char *pchSrc = pchGuestPath;
     548
     549                /* Strip leading delimiters from the path the guest specified. */
     550                while (   cbSrc > 0
     551                       && *pchSrc == pClient->PathDelimiter)
     552                {
     553                    ++pchSrc;
     554                    --cbSrc;
     555                }
     556
     557                /*
     558                 * Iterate the guest path components, verify each of them replacing delimiters with the host slash.
     559                 */
     560                char *pchDst = pchVerifiedPath;
     561                bool fLastComponentHasWildcard = false;
     562                for (; cbSrc > 0; --cbSrc, ++pchSrc)
     563                {
     564                    if (RT_LIKELY(*pchSrc != pClient->PathDelimiter))
    646565                    {
    647                         if (pfu32PathFlags && vbsfPathIsWildcardChar(*pchSrc))
     566                        if (RT_LIKELY(vbsfPathIsValidNameChar(*pchSrc)))
    648567                        {
    649                             fLastComponentHasWildcard = true;
     568                            if (pfu32PathFlags && vbsfPathIsWildcardChar(*pchSrc))
     569                            {
     570                                fLastComponentHasWildcard = true;
     571                            }
     572
     573                            *pchDst++ = *pchSrc;
    650574                        }
    651 
    652                         *pchDst++ = *pchSrc;
     575                        else
     576                        {
     577                            rc = VERR_INVALID_NAME;
     578                            break;
     579                        }
    653580                    }
    654581                    else
    655582                    {
    656                         rc = VERR_INVALID_NAME;
    657                         break;
     583                        /* Replace with the host slash. */
     584                        *pchDst++ = RTPATH_SLASH;
     585
     586                        if (pfu32PathFlags && fLastComponentHasWildcard && cbSrc > 1)
     587                        {
     588                            /* Processed component has a wildcard and there are more characters in the path. */
     589                            *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_PREFIX;
     590                        }
     591                        fLastComponentHasWildcard = false;
    658592                    }
    659593                }
    660                 else
    661                 {
    662                     /* Replace with the host slash. */
    663                     *pchDst++ = RTPATH_SLASH;
    664 
    665                     if (pfu32PathFlags && fLastComponentHasWildcard && cbSrc > 1)
    666                     {
    667                         /* Processed component has a wildcard and there are more characters in the path. */
    668                         *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_PREFIX;
    669                     }
    670                     fLastComponentHasWildcard = false;
    671                 }
    672             }
    673 
    674             if (RT_SUCCESS(rc))
    675             {
    676                 const size_t cbFullPathLength = pchDst - &pszFullPath[0]; /* As strlen(pszFullPath). */
    677 
    678                 *pchDst++ = 0;
    679 
    680                 if (pfu32PathFlags && fLastComponentHasWildcard)
    681                 {
    682                     *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_LAST;
    683                 }
    684 
    685                 /* Check the appended path for root escapes. */
    686                 if (fu32Options & VBSF_O_PATH_CHECK_ROOT_ESCAPE)
    687                 {
    688                     rc = vbsfPathCheckRootEscape(&pszFullPath[cbRootLen]);
    689                 }
     594
    690595                if (RT_SUCCESS(rc))
    691596                {
    692                     /*
    693                      * When the host file system is case sensitive and the guest expects
    694                      * a case insensitive fs, then problems can occur.
    695                      */
    696                     if (    vbsfIsHostMappingCaseSensitive(hRoot)
    697                         && !vbsfIsGuestMappingCaseSensitive(hRoot))
    698                     {
    699                         bool fWildCard = RT_BOOL(fu32Options & VBSF_O_PATH_WILDCARD);
    700                         bool fPreserveLastComponent = RT_BOOL(fu32Options & VBSF_O_PATH_PRESERVE_LAST_COMPONENT);
    701                         rc = vbsfCorrectPathCasing(pClient, pszFullPath, cbFullPathLength, fWildCard, fPreserveLastComponent);
    702                     }
    703 
     597                    const size_t cbFullPathLength = pchDst - &pszFullPath[0]; /* As strlen(pszFullPath). */
     598                    *pchDst++ = 0;
     599
     600                    /* Construct the full host path removing '.' and '..'. */
     601                    rc = RTPathAbsEx(pszRoot, pchVerifiedPath, pszFullPath, cbFullPathAlloc);
    704602                    if (RT_SUCCESS(rc))
    705603                    {
    706                        LogFunc(("%s\n", pszFullPath));
    707 
    708                        /* Return the full host path. */
    709                        *ppszHostPath = pszFullPath;
    710 
    711                        if (pcbHostPathRoot)
    712                        {
    713                            *pcbHostPathRoot = cbRootLen - 1; /* Must index the path delimiter. */
    714                        }
     604                        if (pfu32PathFlags && fLastComponentHasWildcard)
     605                        {
     606                            *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_LAST;
     607                        }
     608
     609                        /* Check if the full path is still within the shared folder. */
     610                        if (fu32Options & VBSF_O_PATH_CHECK_ROOT_ESCAPE)
     611                        {
     612                            if (!RTPathStartsWith(pszFullPath, pszRoot))
     613                            {
     614                                rc = VERR_INVALID_NAME;
     615                            }
     616                        }
     617
     618                        if (RT_SUCCESS(rc))
     619                        {
     620                            /*
     621                             * If the host file system is case sensitive and the guest expects
     622                             * a case insensitive fs, then correct the path components casing.
     623                             */
     624                            if (    vbsfIsHostMappingCaseSensitive(hRoot)
     625                                && !vbsfIsGuestMappingCaseSensitive(hRoot))
     626                            {
     627                                const bool fWildCard = RT_BOOL(fu32Options & VBSF_O_PATH_WILDCARD);
     628                                const bool fPreserveLastComponent = RT_BOOL(fu32Options & VBSF_O_PATH_PRESERVE_LAST_COMPONENT);
     629                                rc = vbsfCorrectPathCasing(pClient, pszFullPath, cbFullPathLength,
     630                                                           fWildCard, fPreserveLastComponent);
     631                            }
     632
     633                            if (RT_SUCCESS(rc))
     634                            {
     635                               LogFlowFunc(("%s\n", pszFullPath));
     636
     637                               /* Return the full host path. */
     638                               *ppszHostPath = pszFullPath;
     639
     640                               if (pcbHostPathRoot)
     641                               {
     642                                   /* Return the length of the root path without the trailing slash. */
     643                                   *pcbHostPathRoot = RTPATH_IS_SLASH(pszFullPath[cbRootLen - 1]) ?
     644                                                          cbRootLen - 1 : /* pszRoot already had the trailing slash. */
     645                                                          cbRootLen; /* pszRoot did not have the trailing slash. */
     646                               }
     647                            }
     648                        }
    715649                    }
    716                 }
     650                    else
     651                    {
     652                        LogFunc(("RTPathAbsEx %Rrc\n", rc));
     653                    }
     654                }
     655
     656                RTMemFree(pchVerifiedPath);
     657            }
     658            else
     659            {
     660                rc = VERR_NO_MEMORY;
    717661            }
    718662        }
     
    738682    RTMemFree(pszFullPath);
    739683
     684    LogFunc(("%Rrc\n", rc));
    740685    return rc;
    741686}
Note: See TracChangeset for help on using the changeset viewer.

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