VirtualBox

Changeset 79686 in vbox for trunk/src/VBox/Devices/PC


Ignore:
Timestamp:
Jul 11, 2019 8:49:11 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
132017
Message:

HPET: Avoid a potential division overflow whereby a malicious guest could -- the horror -- commit harakiri (see bugref:9463).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/DevHPET.cpp

    r76553 r79686  
    7575 */
    7676#define FS_PER_NS                   1000000
     77
     78/**
     79 * Femtoseconds in a day. Still fits within int64_t.
     80 */
     81#define FS_PER_DAY                  (1000000LL * 60 * 60 * 24 * FS_PER_NS)
     82
     83/**
     84 * Number of HPET ticks in 100 years, ICH9 frequency.
     85 */
     86#define HPET_TICKS_IN_100YR_ICH9    (FS_PER_DAY / HPET_CLK_PERIOD_ICH9 * 365 * 100)
     87
     88/**
     89 * Number of HPET ticks in 100 years, made-up PIIX frequency.
     90 */
     91#define HPET_TICKS_IN_100YR_PIIX    (FS_PER_DAY / HPET_CLK_PERIOD_PIIX * 365 * 100)
    7792
    7893/** @name Interrupt type
     
    385400
    386401
    387 static void hpetProgramTimer(HPETTIMER *pHpetTimer)
     402static void hpetProgramTimer(HPET *pThis, HPETTIMER *pHpetTimer)
    388403{
    389404    /* no wrapping on new timers */
     
    420435#endif
    421436
    422     Log4(("HPET: next IRQ in %lld ticks (%lld ns)\n", u64Diff, hpetTicksToNs(pHpetTimer->CTX_SUFF(pHpet), u64Diff)));
    423     TMTimerSetNano(pHpetTimer->CTX_SUFF(pTimer), hpetTicksToNs(pHpetTimer->CTX_SUFF(pHpet), u64Diff));
     437    uint64_t u64TickLimit = pThis->fIch9 ? HPET_TICKS_IN_100YR_ICH9 : HPET_TICKS_IN_100YR_PIIX;
     438    if (u64Diff <= u64TickLimit)
     439    {
     440        Log4(("HPET: next IRQ in %lld ticks (%lld ns)\n", u64Diff, hpetTicksToNs(pHpetTimer->CTX_SUFF(pHpet), u64Diff)));
     441        TMTimerSetNano(pHpetTimer->CTX_SUFF(pTimer), hpetTicksToNs(pHpetTimer->CTX_SUFF(pHpet), u64Diff));
     442    }
     443    else
     444    {
     445        LogRelMax(10, ("HPET: Not scheduling an interrupt more than 100 years in the future.\n"));
     446    }
    424447    hpetTimerSetFrequencyHint(pHpetTimer->CTX_SUFF(pHpet), pHpetTimer);
    425448}
     
    568591
    569592            if (pThis->u64HpetConfig & HPET_CFG_ENABLE)
    570                 hpetProgramTimer(pHpetTimer);
     593                hpetProgramTimer(pThis, pHpetTimer);
    571594            DEVHPET_UNLOCK_BOTH(pThis);
    572595            break;
     
    588611
    589612                if (pThis->u64HpetConfig & HPET_CFG_ENABLE)
    590                     hpetProgramTimer(pHpetTimer);
     613                    hpetProgramTimer(pThis, pHpetTimer);
    591614            }
    592615            DEVHPET_UNLOCK_BOTH(pThis);
     
    755778/** @todo Only get the time stamp once when reprogramming? */
    756779                /* Enable main counter and interrupt generation. */
    757                 pThis->u64HpetOffset = hpetTicksToNs(pThis, pThis->u64HpetCounter)
    758                                      - TMTimerGet(pThis->aTimers[0].CTX_SUFF(pTimer));
     780                uint64_t u64TickLimit = pThis->fIch9 ? HPET_TICKS_IN_100YR_ICH9 : HPET_TICKS_IN_100YR_PIIX;
     781                if (pThis->u64HpetCounter <= u64TickLimit)
     782                {
     783                    pThis->u64HpetOffset = hpetTicksToNs(pThis, pThis->u64HpetCounter)
     784                                         - TMTimerGet(pThis->aTimers[0].CTX_SUFF(pTimer));
     785                }
     786                else
     787                {
     788                    LogRelMax(10, ("HPET: Counter set more than 100 years in the future, reducing.\n"));
     789                    pThis->u64HpetOffset = 1000000LL * 60 * 60 * 24 * 365 * 100
     790                                         - TMTimerGet(pThis->aTimers[0].CTX_SUFF(pTimer));
     791                }
    759792                for (uint32_t i = 0; i < cTimers; i++)
    760793                    if (pThis->aTimers[i].u64Cmp != hpetInvalidValue(&pThis->aTimers[i]))
    761                         hpetProgramTimer(&pThis->aTimers[i]);
     794                        hpetProgramTimer(pThis, &pThis->aTimers[i]);
    762795            }
    763796            else if (hpetBitJustCleared(iOldValue, u32NewValue, HPET_CFG_ENABLE))
     
    10381071            u64Diff = hpetComputeDiff(pHpetTimer, u64CurTick);
    10391072
    1040             Log4(("HPET: periodic: next in %llu\n", hpetTicksToNs(pThis, u64Diff)));
    1041             TMTimerSetNano(pTimer, hpetTicksToNs(pThis, u64Diff));
     1073            uint64_t u64TickLimit = pThis->fIch9 ? HPET_TICKS_IN_100YR_ICH9 : HPET_TICKS_IN_100YR_PIIX;
     1074            if (u64Diff <= u64TickLimit)
     1075            {
     1076                Log4(("HPET: periodic: next in %llu\n", hpetTicksToNs(pThis, u64Diff)));
     1077                TMTimerSetNano(pTimer, hpetTicksToNs(pThis, u64Diff));
     1078            }
     1079            else
     1080            {
     1081                LogRelMax(10, ("HPET: Not scheduling periodic interrupt more than 100 years in the future.\n"));
     1082            }
    10421083        }
    10431084    }
     
    12681309        /* We can do all IRQs */
    12691310        uint32_t u32RoutingCap = 0xffffffff;
    1270         pHpetTimer->u64Config |= ((uint64_t)u32RoutingCap) << 32;
     1311        pHpetTimer->u64Config |= ((uint64_t)u32RoutingCap) << HPET_TN_INT_ROUTE_CAP_SHIFT;
    12711312        pHpetTimer->u64Period  = 0;
    12721313        pHpetTimer->u8Wrap     = 0;
Note: See TracChangeset for help on using the changeset viewer.

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