VirtualBox

Changeset 104286 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Apr 11, 2024 1:56:27 AM (9 months ago)
Author:
vboxsync
Message:

IPRT/log,Main: Open the parent directory of the log file on Windows before we opening the log file and do any log rotating to prevent reparse hacks. bugref:10632

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/log/log.cpp

    r103685 r104286  
    4949#include <iprt/mp.h>
    5050#ifdef IN_RING3
     51# ifdef RT_OS_WINDOWS
     52#  include <iprt/dir.h>
     53# endif
    5154# include <iprt/env.h>
    5255# include <iprt/file.h>
     
    227230    PCRTLOGOUTPUTIF         pOutputIf;
    228231    /** Opaque user data passed to the callbacks in the output interface. */
    229     void                    *pvOutputIfUser;
     232    void                   *pvOutputIfUser;
     233    /** Opaque directory context.
     234     * This is kept open while we have an open log file. */
     235    void                   *pvDirCtx;
    230236
    231237    /** Handle to log file (if open) - only used by the default output interface to avoid additional layers of indirection. */
     
    259265
    260266/** The revision of the internal logger structure. */
    261 # define RTLOGGERINTERNAL_REV    UINT32_C(13)
     267# define RTLOGGERINTERNAL_REV    UINT32_C(14)
    262268
    263269AssertCompileMemberAlignment(RTLOGGERINTERNAL, cbRingBufUnflushed, sizeof(uint64_t));
     
    267273#endif
    268274
    269 
    270275/** Pointer to internal logger bits. */
    271276typedef struct RTLOGGERINTERNAL *PRTLOGGERINTERNAL;
     277
     278
    272279/**
    273280 * Arguments passed to the output function.
     
    760767
    761768#ifdef IN_RING3
    762 static DECLCALLBACK(int) rtLogOutputIfDefOpen(PCRTLOGOUTPUTIF pIf, void *pvUser, const char *pszFilename, uint32_t fFlags)
    763 {
    764     RT_NOREF(pIf);
     769# ifdef RT_OS_WINDOWS
     770#  define RTLOG_DIR_CTX_IS_PARENT_DIR
     771# endif
     772
     773/**
     774 * @callback_method_impl{RTLOGOUTPUTIF,pfnDirCtxOpen}
     775 */
     776static DECLCALLBACK(int) rtLogOutputIfDefDirCtxOpen(PCRTLOGOUTPUTIF pIf, void *pvUser, const char *pszFilename, void **ppvDirCtx)
     777{
     778    RT_NOREF(pIf, pvUser);
     779# ifdef RTLOG_DIR_CTX_IS_PARENT_DIR
     780    /* Open the parent directory to make sure it is a real directory and not
     781       object directory placed there by someone with evil intent. @bugref{10632} */
     782    RTDIR hDir = NIL_RTDIR;
     783    int rc = RTDirOpenFiltered(&hDir, pszFilename, RTDIRFILTER_WINNT, 0);
     784    if (RT_FAILURE(rc))
     785        return rc;
     786    AssertCompile(sizeof(*ppvDirCtx) == sizeof(hDir));
     787    *ppvDirCtx = hDir;
     788# else
     789    RT_NOREF(pIf, pvUser, pszFilename);
     790    *ppvDirCtx = (void *)(intptr_t)42;
     791# endif
     792    return VINF_SUCCESS;
     793}
     794
     795
     796/**
     797 * @callback_method_impl{RTLOGOUTPUTIF,pfnDirCtxClose}
     798 */
     799static DECLCALLBACK(int) rtLogOutputIfDefDirCtxClose(PCRTLOGOUTPUTIF pIf, void *pvUser, void *pvDirCtx)
     800{
     801    RT_NOREF(pIf, pvUser);
     802# ifdef RTLOG_DIR_CTX_IS_PARENT_DIR
     803    RTDIR hDir = (RTDIR)pvDirCtx;
     804    int rc = RTDirClose(hDir);
     805    AssertRC(rc);
     806    return rc;
     807# else
     808    Assert((intptr_t)pvDirCtx == 42);
     809    RT_NOREF(pvDirCtx);
     810    return VINF_SUCCESS;
     811# endif
     812}
     813
     814
     815/**
     816 * @callback_method_impl{RTLOGOUTPUTIF,pfnDelete}
     817 */
     818static DECLCALLBACK(int) rtLogOutputIfDefDelete(PCRTLOGOUTPUTIF pIf, void *pvUser, void *pvDirCtx, const char *pszFilename)
     819{
     820    RT_NOREF(pIf, pvUser, pvDirCtx);
     821# ifdef RTLOG_DIR_CTX_IS_PARENT_DIR
     822    /** @todo use RTDirRelPathUnlink when it adds any improvements. */
     823# else
     824    Assert((intptr_t)pvDirCtx == 42);
     825# endif
     826
     827    return RTFileDelete(pszFilename);
     828}
     829
     830
     831/**
     832 * @callback_method_impl{RTLOGOUTPUTIF,pfnRename}
     833 */
     834static DECLCALLBACK(int) rtLogOutputIfDefRename(PCRTLOGOUTPUTIF pIf, void *pvUser, void *pvDirCtx,
     835                                                const char *pszFilenameOld, const char *pszFilenameNew, uint32_t fFlags)
     836{
     837    RT_NOREF(pIf, pvUser, pvDirCtx);
     838# ifdef RTLOG_DIR_CTX_IS_PARENT_DIR
     839    /** @todo use RTDirRelPathRename when it adds any improvements. */
     840# else
     841    Assert((intptr_t)pvDirCtx == 42);
     842# endif
     843    return RTFileRename(pszFilenameOld, pszFilenameNew, fFlags);
     844}
     845
     846
     847/**
     848 * @callback_method_impl{RTLOGOUTPUTIF,pfnOpen}
     849 */
     850static DECLCALLBACK(int) rtLogOutputIfDefOpen(PCRTLOGOUTPUTIF pIf, void *pvUser, void *pvDirCtx,
     851                                              const char *pszFilename, uint32_t fFlags)
     852{
    765853    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pvUser;
     854    RT_NOREF(pIf, pvDirCtx);
     855# ifdef RTLOG_DIR_CTX_IS_PARENT_DIR
     856    /** @todo use RTDirRelFileOpen */
     857# else
     858    Assert((intptr_t)pvDirCtx == 42);
     859# endif
    766860
    767861    return RTFileOpen(&pLoggerInt->hFile, pszFilename, fFlags);
     
    769863
    770864
     865/**
     866 * @callback_method_impl{RTLOGOUTPUTIF,pfnClose}
     867 */
    771868static DECLCALLBACK(int) rtLogOutputIfDefClose(PCRTLOGOUTPUTIF pIf, void *pvUser)
    772869{
     
    783880
    784881
    785 static DECLCALLBACK(int) rtLogOutputIfDefDelete(PCRTLOGOUTPUTIF pIf, void *pvUser, const char *pszFilename)
    786 {
    787     RT_NOREF(pIf, pvUser);
    788     return RTFileDelete(pszFilename);
    789 }
    790 
    791 
    792 static DECLCALLBACK(int) rtLogOutputIfDefRename(PCRTLOGOUTPUTIF pIf, void *pvUser, const char *pszFilenameOld,
    793                                                 const char *pszFilenameNew, uint32_t fFlags)
    794 {
    795     RT_NOREF(pIf, pvUser);
    796     return RTFileRename(pszFilenameOld, pszFilenameNew, fFlags);
    797 }
    798 
    799 
     882/**
     883 * @callback_method_impl{RTLOGOUTPUTIF,pfnQuerySize}
     884 */
    800885static DECLCALLBACK(int) rtLogOutputIfDefQuerySize(PCRTLOGOUTPUTIF pIf, void *pvUser, uint64_t *pcbSize)
    801886{
     
    811896
    812897
     898/**
     899 * @callback_method_impl{RTLOGOUTPUTIF,pfnWrite}
     900 */
    813901static DECLCALLBACK(int) rtLogOutputIfDefWrite(PCRTLOGOUTPUTIF pIf, void *pvUser, const void *pvBuf,
    814902                                               size_t cbWrite, size_t *pcbWritten)
     
    824912
    825913
     914/**
     915 * @callback_method_impl{RTLOGOUTPUTIF,pfnFlush}
     916 */
    826917static DECLCALLBACK(int) rtLogOutputIfDefFlush(PCRTLOGOUTPUTIF pIf, void *pvUser)
    827918{
     
    841932static const RTLOGOUTPUTIF g_LogOutputIfDef =
    842933{
     934    rtLogOutputIfDefDirCtxOpen,
     935    rtLogOutputIfDefDirCtxClose,
     936    rtLogOutputIfDefDelete,
     937    rtLogOutputIfDefRename,
    843938    rtLogOutputIfDefOpen,
    844939    rtLogOutputIfDefClose,
    845     rtLogOutputIfDefDelete,
    846     rtLogOutputIfDefRename,
    847940    rtLogOutputIfDefQuerySize,
    848941    rtLogOutputIfDefWrite,
    849942    rtLogOutputIfDefFlush
    850943};
    851 #endif
     944
     945#endif /* IN_RING3 */
    852946
    853947
     
    14921586            }
    14931587# ifdef IN_RING3
    1494             pLoggerInt->pOutputIf->pfnClose(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser);
    1495 # endif
     1588            if (pLoggerInt->fLogOpened)
     1589            {
     1590                pLoggerInt->pOutputIf->pfnClose(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser);
     1591                pLoggerInt->pOutputIf->pfnDirCtxClose(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, pLoggerInt->pvDirCtx);
     1592                pLoggerInt->pvDirCtx = NULL;
     1593            }
     1594#endif
    14961595# if defined(RT_ARCH_X86) && !defined(LOG_USE_C99) && 0 /* retired */
    14971596            if (pLoggerInt->Core.pfnLogger)
     
    15801679            rc = rc2;
    15811680        pLoggerInt->fLogOpened = false;
     1681
     1682        pLoggerInt->pOutputIf->pfnDirCtxClose(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, pLoggerInt->pvDirCtx);
     1683        pLoggerInt->pvDirCtx = NULL;
    15821684    }
    15831685# endif
     
    26972799    else
    26982800    {
    2699         pLoggerInt->pOutputIf->pfnDelete(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser,
     2801        pLoggerInt->pOutputIf->pfnDelete(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, pLoggerInt->pvDirCtx,
    27002802                                         pLoggerInt->szFilename);
    27012803        fOpen |= RTFILE_O_CREATE;
     
    27072809
    27082810    unsigned cBackoff = 0;
    2709     int rc = pLoggerInt->pOutputIf->pfnOpen(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser,
     2811    int rc = pLoggerInt->pOutputIf->pfnOpen(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, pLoggerInt->pvDirCtx,
    27102812                                            pLoggerInt->szFilename, fOpen);
    27112813    while (   (   rc == VERR_SHARING_VIOLATION
     
    27152817        RTThreadSleep(g_acMsLogBackoff[cBackoff++]);
    27162818        if (!(pLoggerInt->fFlags & RTLOGFLAGS_APPEND))
    2717             pLoggerInt->pOutputIf->pfnDelete(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser,
     2819            pLoggerInt->pOutputIf->pfnDelete(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, pLoggerInt->pvDirCtx,
    27182820                                             pLoggerInt->szFilename);
    2719         rc = pLoggerInt->pOutputIf->pfnOpen(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser,
     2821        rc = pLoggerInt->pOutputIf->pfnOpen(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, pLoggerInt->pvDirCtx,
    27202822                                            pLoggerInt->szFilename, fOpen);
    27212823    }
     
    27992901        pLoggerInt->pOutputIf->pfnClose(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser);
    28002902    }
     2903    /*
     2904     * If the log file was closed and we're being called from rtR3LogOpenFileDestination
     2905     * we must open a log directory context before going on.
     2906     */
     2907    else if (!fFirst)
     2908    {
     2909        int rc = pLoggerInt->pOutputIf->pfnDirCtxOpen(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser,
     2910                                                      pLoggerInt->szFilename, &pLoggerInt->pvDirCtx);
     2911        if (RT_FAILURE(rc))
     2912            return;
     2913    }
    28012914
    28022915    if (cSavedHistory)
     
    28172930
    28182931            unsigned cBackoff = 0;
    2819             int rc = pLoggerInt->pOutputIf->pfnRename(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser,
     2932            int rc = pLoggerInt->pOutputIf->pfnRename(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, pLoggerInt->pvDirCtx,
    28202933                                                      szOldName, szNewName, RTFILEMOVE_FLAGS_REPLACE);
    28212934            while (   rc == VERR_SHARING_VIOLATION
     
    28232936            {
    28242937                RTThreadSleep(g_acMsLogBackoff[cBackoff++]);
    2825                 rc = pLoggerInt->pOutputIf->pfnRename(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser,
     2938                rc = pLoggerInt->pOutputIf->pfnRename(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, pLoggerInt->pvDirCtx,
    28262939                                                      szOldName, szNewName, RTFILEMOVE_FLAGS_REPLACE);
    28272940            }
    28282941
    28292942            if (rc == VERR_FILE_NOT_FOUND)
    2830                 pLoggerInt->pOutputIf->pfnDelete(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, szNewName);
     2943                pLoggerInt->pOutputIf->pfnDelete(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, pLoggerInt->pvDirCtx,
     2944                                                 szNewName);
    28312945        }
    28322946
     
    28382952            char szExcessName[sizeof(pLoggerInt->szFilename) + 32];
    28392953            RTStrPrintf(szExcessName, sizeof(szExcessName), "%s.%u", pLoggerInt->szFilename, i);
    2840             int rc = pLoggerInt->pOutputIf->pfnDelete(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, szExcessName);
     2954            int rc = pLoggerInt->pOutputIf->pfnDelete(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, pLoggerInt->pvDirCtx,
     2955                                                      szExcessName);
    28412956            if (RT_FAILURE(rc))
    28422957                break;
     
    28642979    }
    28652980
    2866     /* Restore saved values. */
     2981    /*
     2982     * Close the context if we didn't get a log file, unless we're being
     2983     * called by rtR3LogOpenFileDestination.
     2984     */
     2985    if (!pLoggerInt->fLogOpened && !fFirst)
     2986    {
     2987        pLoggerInt->pOutputIf->pfnDirCtxClose(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, pLoggerInt->pvDirCtx);
     2988        pLoggerInt->pvDirCtx = NULL;
     2989    }
     2990
     2991    /*
     2992     * Restore saved values.
     2993     */
    28672994    pLoggerInt->cHistory = cSavedHistory;
    28682995    pLoggerInt->fFlags   = fSavedFlags;
     
    28823009static int rtR3LogOpenFileDestination(PRTLOGGERINTERNAL pLoggerInt, PRTERRINFO pErrInfo)
    28833010{
    2884     int rc;
    2885     if (pLoggerInt->fFlags & RTLOGFLAGS_APPEND)
    2886     {
    2887         rc = rtlogFileOpen(pLoggerInt, pErrInfo);
    2888 
    2889         /* Rotate in case of appending to a too big log file,
    2890            otherwise this simply doesn't do anything. */
    2891         rtlogRotate(pLoggerInt, 0, true /* fFirst */, pErrInfo);
    2892     }
    2893     else
    2894     {
    2895         /* Force rotation if it is configured. */
    2896         pLoggerInt->cbHistoryFileWritten = UINT64_MAX;
    2897         rtlogRotate(pLoggerInt, 0, true /* fFirst */, pErrInfo);
    2898 
    2899         /* If the file is not open then rotation is not set up. */
     3011    /*
     3012     * Open a log directory context so the output backend can better secure
     3013     * the log file opening, renaming and deleting. (See @bugref{10632}.)
     3014     */
     3015    Assert(!pLoggerInt->fLogOpened);
     3016    int rc = pLoggerInt->pOutputIf->pfnDirCtxOpen(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser,
     3017                                                  pLoggerInt->szFilename, &pLoggerInt->pvDirCtx);
     3018    if (RT_SUCCESS(rc))
     3019    {
     3020        if (pLoggerInt->fFlags & RTLOGFLAGS_APPEND)
     3021        {
     3022            rc = rtlogFileOpen(pLoggerInt, pErrInfo);
     3023
     3024            /* Rotate in case of appending to a too big log file,
     3025               otherwise this simply doesn't do anything. */
     3026            rtlogRotate(pLoggerInt, 0, true /* fFirst */, pErrInfo);
     3027        }
     3028        else
     3029        {
     3030            /* Force rotation if it is configured. */
     3031            pLoggerInt->cbHistoryFileWritten = UINT64_MAX;
     3032            rtlogRotate(pLoggerInt, 0, true /* fFirst */, pErrInfo);
     3033
     3034            /* If the file is not open then rotation is not set up. */
     3035            if (!pLoggerInt->fLogOpened)
     3036            {
     3037                pLoggerInt->cbHistoryFileWritten = 0;
     3038                rc = rtlogFileOpen(pLoggerInt, pErrInfo);
     3039            }
     3040            else
     3041                rc = VINF_SUCCESS;
     3042        }
     3043
     3044        /*
     3045         * Close the directory context if we failed to get open a log file.
     3046         * This gives the user a chance to make changes so it may succeed later.
     3047         */
    29003048        if (!pLoggerInt->fLogOpened)
    29013049        {
    2902             pLoggerInt->cbHistoryFileWritten = 0;
    2903             rc = rtlogFileOpen(pLoggerInt, pErrInfo);
    2904         }
    2905         else
    2906             rc = VINF_SUCCESS;
     3050            pLoggerInt->pOutputIf->pfnDirCtxClose(pLoggerInt->pOutputIf, pLoggerInt->pvOutputIfUser, pLoggerInt->pvDirCtx);
     3051            pLoggerInt->pvDirCtx = NULL;
     3052        }
    29073053    }
    29083054    return rc;
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