VirtualBox

Changeset 71660 in vbox for trunk/doc


Ignore:
Timestamp:
Apr 4, 2018 3:14:28 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
121689
Message:

Added a section about handling guest input to the general coding guidlines.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/VBox-CodingGuidelines.cpp

    r69500 r71660  
    133133 *        \#endif indicates what ended.  Only add these when there are more than
    134134 *        a few lines (6-10) of \#ifdef'ed code, otherwise they're just clutter.
     135 *
     136 *   <li> No 'else' after if block ending with 'return', 'break', or 'continue'.
     137 *
    135138 * </ul>
    136139 *
     
    325328 * </ul>
    326329 *
     330 *
    327331 * @subsection sec_vbox_guideline_compulsory_doxygen    Doxygen Comments
    328332 *
    329333 * As mentioned above, we shall use doxygen/javadoc style commenting of public
    330  * functions, typedefs, classes and such.  It is preferred to use this style in
    331  * as many places as possible.
     334 * functions, typedefs, classes and such.  It is mandatory to use this style
     335 * everywhere!
    332336 *
    333337 * A couple of hints on how to best write doxygen comments:
     
    359363 * See https://www.stack.nl/~dimitri/doxygen/manual/index.html for the official
    360364 * doxygen documention.
     365 *
     366 *
     367 *
     368 * @subsection sec_vbox_guideline_compulsory_guest  Handling of guest input
     369 *
     370 * First, guest input should ALWAYS be consider to be TOXIC and constructed with
     371 * MALICIOUS intent!  Max paranoia level!
     372 *
     373 * Second, when getting inputs from memory shared with the guest, be EXTREMELY
     374 * careful to not re-read input from shared memory after validating it, because
     375 * that will create TOCTOU problems. So, after reading input from shared memory
     376 * always use the RT_UNTRUSTED_NONVOLATILE_COPY_FENCE() macor.  For more details
     377 * on TOCTOU: https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use
     378 *
     379 * Thirdly, considering the recent speculation side channel issues, spectre v1
     380 * in particular, we would like to be ready for future screwups.   This means
     381 * having input validation in a separate block of code that ends with one (or
     382 * more) RT_UNTRUSTED_VALIDATED_FENCE().
     383 *
     384 * So the rules:
     385 *
     386 * <ul>
     387 *
     388 *   <li> Mark all pointers to shared memory with RT_UNTRUSTED_VOLATILE_GUEST.
     389 *
     390 *   <li> Copy volatile data into local variables or heap before validating
     391 *        them (see RT_COPY_VOLATILE() and RT_BCOPY_VOLATILE().
     392 *
     393 *   <li> Place RT_UNTRUSTED_NONVOLATILE_COPY_FENCE() after a block copying
     394 *        volatile data.
     395 *
     396 *   <li> Always validate untrusted inputs in a block ending with a
     397 *        RT_UNTRUSTED_VALIDATED_FENCE().
     398 *
     399 *   <li> Use the ASSERT_GUEST_XXXX macros from VBox/AssertGuest.h to validate
     400 *        guest input.  (Do NOT use iprt/assert.h macros.)
     401 *
     402 *   <li> Validation of an input B may require using another input A to look up
     403 *        some data, in which case its necessary to insert an
     404 *        RT_UNTRUSTED_VALIDATED_FENCE() after validating A and before A is used
     405 *        for the lookup.
     406 *
     407 *        For example A is a view identifier, idView, and B is an offset into
     408 *        the view's framebuffer area, offView.  To validate offView (B) it is
     409 *        necessary to get the size of the views framebuffer region:
     410 *        @code
     411 *              uint32_t const idView  = pReq->idView;   // A
     412 *              uint32_t const offView = pReq->offView;  // B
     413 *              RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
     414 *
     415 *              ASSERT_GUEST_RETURN(idView < pThis->cView,
     416 *                                  VERR_INVALID_PARAMETER);
     417 *              RT_UNTRUSTED_VALIDATED_FENCE();
     418 *              const MYVIEW *pView = &pThis->aViews[idView];
     419 *              ASSERT_GUEST_RETURN(offView < pView->cbFramebufferArea,
     420 *                                  VERR_OUT_OF_RANGE);
     421 *              RT_UNTRUSTED_VALIDATED_FENCE();
     422 *        @endcode
     423 *
     424 *   <li> Take care to make sure input check are not subject to integer overflow problems.
     425 *
     426 *        For instance when validating an area, you must not just add cbDst + offDst
     427 *        and check against pThis->offEnd or something like that.  Rather do:
     428 *        @code
     429 *              uint32_t const offDst = pReq->offDst;
     430 *              uint32_t const cbDst  = pReq->cbDst;
     431 *              RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
     432 *
     433 *              ASSERT_GUEST_RETURN(   cbDst  <= pThis->cbSrc
     434 *                                  && offDst < pThis->cbSrc - cbDst,
     435 *                                  VERR_OUT_OF_RANGE);
     436 *              RT_UNTRUSTED_VALIDATED_FENCE();
     437 *        @endcode
     438 *
     439 *   <li> Input validation does not only apply to shared data cases, but also to
     440 *        I/O port and MMIO handlers.
     441 *
     442 *   <li> Ditto for kernel drivers working with usermode inputs.
     443 *
     444 * </ul>
     445 *
     446 *
     447 * Problem patterns:
     448 *   - https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use
     449 *   - https://googleprojectzero.blogspot.de/2018/01/reading-privileged-memory-with-side.html
     450 *     (Variant 1 only).
     451 *   - https://en.wikipedia.org/wiki/Integer_overflow
     452 *
    361453 *
    362454 *
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