VirtualBox

Changeset 87169 in vbox


Ignore:
Timestamp:
Jan 4, 2021 4:54:47 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
142096
Message:

DevVirtualKD: Allocate the command buffer with guard pages. Untested. bugref:9895

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Misc/DevVirtualKD.cpp

    r82968 r87169  
    2727#include <VBox/log.h>
    2828#include <iprt/assert.h>
     29#include <iprt/mem.h>
    2930#include <iprt/path.h>
    3031
     
    4344typedef struct VKDREQUESTHDR
    4445{
    45     unsigned cbData;
    46     unsigned cbReplyMax;
     46    uint32_t cbData;
     47    uint32_t cbReplyMax;
    4748} VKDREQUESTHDR;
     49AssertCompileSize(VKDREQUESTHDR, 8);
    4850
    4951#pragma pack(1)
    5052typedef struct VKDREPLYHDR
    5153{
    52     unsigned cbData;
     54    uint32_t cbData;
    5355    char chOne;
    5456    char chSpace;
     
    6062{
    6163public:
    62     virtual unsigned OnRequest(const char *pRequestIncludingRpcHeader, unsigned RequestSizeWithRpcHeader, char **ppReply)=0;
     64    virtual unsigned OnRequest(const char *pRequestIncludingRpcHeader, unsigned RequestSizeWithRpcHeader, char **ppReply) = 0;
    6365    virtual ~IKDClient() {}
    6466};
     
    7274    RTLDRMOD hLib;
    7375    IKDClient *pKDClient;
    74     char abCmdBody[_256K];
     76    char *pbCmdBody;
     77    bool fFencedCmdBody;    /**< Set if pbCmdBody was allocated using RTMemPageAlloc rather than RTMemAlloc. */
    7578} VIRTUALKD;
     79
     80#define VIRTUALKB_CMDBODY_SIZE          _256K           /**< Size of buffer pointed to by VIRTUALKB::pbCmdBody */
     81#define VIRTUALKB_CMDBODY_PRE_FENCE     (PAGE_SIZE * 4) /**< Size of the eletrict fence before the command body. */
     82#define VIRTUALKB_CMDBODY_POST_FENCE    (PAGE_SIZE * 8) /**< Size of the eletrict fence after the command body. */
    7683
    7784
     
    102109    if (offPort == 1)
    103110    {
     111        /*
     112         * Read the request and request body.  Ignore empty requests.
     113         */
    104114        RTGCPHYS GCPhys = u32;
    105         VKDREQUESTHDR RequestHeader = {0, };
     115        VKDREQUESTHDR RequestHeader = { 0, 0 };
    106116        int rc = PDMDevHlpPhysRead(pDevIns, GCPhys, &RequestHeader, sizeof(RequestHeader));
    107         if (   !RT_SUCCESS(rc)
    108             || !RequestHeader.cbData)
    109             return VINF_SUCCESS;
    110 
    111         unsigned cbData = RT_MIN(RequestHeader.cbData, sizeof(pThis->abCmdBody));
    112         rc = PDMDevHlpPhysRead(pDevIns, GCPhys + sizeof(RequestHeader), pThis->abCmdBody, cbData);
    113         if (!RT_SUCCESS(rc))
    114             return VINF_SUCCESS;
    115 
    116         char *pReply = NULL;
    117         unsigned cbReply = pThis->pKDClient->OnRequest(pThis->abCmdBody, cbData, &pReply);
    118 
    119         if (!pReply)
    120             cbReply = 0;
    121 
    122         /** @todo r=bird: RequestHeader.cbReplyMax is not taking into account here. */
    123         VKDREPLYHDR ReplyHeader;
    124         ReplyHeader.cbData = cbReply + 2;
    125         ReplyHeader.chOne = '1';
    126         ReplyHeader.chSpace = ' ';
    127         rc = PDMDevHlpPhysWrite(pDevIns, GCPhys, &ReplyHeader, sizeof(ReplyHeader));
    128         if (!RT_SUCCESS(rc))
    129             return VINF_SUCCESS;
    130         if (cbReply)
     117        if (   RT_SUCCESS(rc)
     118            && RequestHeader.cbData > 0)
    131119        {
    132             rc = PDMDevHlpPhysWrite(pDevIns, GCPhys + sizeof(ReplyHeader), pReply, cbReply);
    133             if (!RT_SUCCESS(rc))
    134                 return VINF_SUCCESS;
     120            uint32_t cbData = RT_MIN(RequestHeader.cbData, VIRTUALKB_CMDBODY_SIZE);
     121            rc = PDMDevHlpPhysRead(pDevIns, GCPhys + sizeof(RequestHeader), pThis->pbCmdBody, cbData);
     122            if (RT_SUCCESS(rc))
     123            {
     124                /*
     125                 * Call the plugin module.
     126                 */
     127                char    *pbReply = NULL;
     128                unsigned cbReply;
     129                try
     130                {
     131                    cbReply = pThis->pKDClient->OnRequest(pThis->pbCmdBody, cbData, &pbReply);
     132                    if (!pbReply)
     133                        cbReply = 0;
     134                }
     135                catch (...)
     136                {
     137                    LogRel(("DevVirtualKB: OnRequest threw exception. sigh.\n"));
     138                    cbReply = 0;
     139                    pbReply = NULL;
     140                }
     141
     142                /*
     143                 * Write the reply to guest memory (overwriting the request):
     144                 */
     145                /** @todo r=bird: RequestHeader.cbReplyMax is not taken into account here! */
     146                VKDREPLYHDR ReplyHeader;
     147                ReplyHeader.cbData = cbReply + 2;
     148                ReplyHeader.chOne = '1';
     149                ReplyHeader.chSpace = ' ';
     150                rc = PDMDevHlpPhysWrite(pDevIns, GCPhys, &ReplyHeader, sizeof(ReplyHeader));
     151                if (cbReply && RT_SUCCESS(rc))
     152                    rc = PDMDevHlpPhysWrite(pDevIns, GCPhys + sizeof(ReplyHeader), pbReply, cbReply);
     153            }
    135154        }
    136155    }
     
    138157    {
    139158        Assert(offPort == 0);
    140         if (u32 == 0x564D5868)
     159        if (u32 == UINT32_C(0x564D5868) /* 'VMXh' */)
    141160            pThis->fOpenChannelDetected = true;
    142161        else
     
    158177    if (pThis->pKDClient)
    159178    {
     179        /** @todo r=bird: This interface is not safe as the object doesn't overload the
     180         *        delete operator, thus making our runtime free it rather than that of
     181         *        the plug-in module IIRC. */
    160182        delete pThis->pKDClient;
    161183        pThis->pKDClient = NULL;
     
    166188        RTLdrClose(pThis->hLib);
    167189        pThis->hLib = NIL_RTLDRMOD;
     190    }
     191
     192    if (pThis->pbCmdBody)
     193    {
     194        if (pThis->fFencedCmdBody)
     195            RTMemPageFree((uint8_t *)pThis->pbCmdBody - RT_ALIGN_Z(VIRTUALKB_CMDBODY_PRE_FENCE, PAGE_SIZE),
     196                            RT_ALIGN_Z(VIRTUALKB_CMDBODY_PRE_FENCE,  PAGE_SIZE)
     197                          + RT_ALIGN_Z(VIRTUALKB_CMDBODY_SIZE,       PAGE_SIZE)
     198                          + RT_ALIGN_Z(VIRTUALKB_CMDBODY_POST_FENCE, PAGE_SIZE));
     199        else
     200            RTMemFree(pThis->pbCmdBody);
     201        pThis->pbCmdBody = NULL;
    168202    }
    169203
     
    185219    pThis->hLib = NIL_RTLDRMOD;
    186220    pThis->pKDClient = NULL;
    187 
     221    pThis->pbCmdBody = NULL;
     222    pThis->fFencedCmdBody = false;
    188223
    189224    PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "Path", "");
     
    197232        return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to get the \"Path\" value"));
    198233
    199     rc = RTPathAppend(szPath, sizeof(szPath), HC_ARCH_BITS == 64 ?  "kdclient64.dll" : "kdclient.dll");
     234    rc = RTPathAppend(szPath, sizeof(szPath), HC_ARCH_BITS == 64 ? "kdclient64.dll" : "kdclient.dll");
    200235    AssertRCReturn(rc, rc);
    201236    rc = RTLdrLoad(szPath, &pThis->hLib);
     
    209244            if (pThis->pKDClient)
    210245            {
     246                /* We allocate a fenced buffer for reasons of paranoia. */
     247                uint8_t *pbCmdBody = (uint8_t *)RTMemPageAlloc(  RT_ALIGN_Z(VIRTUALKB_CMDBODY_PRE_FENCE,  PAGE_SIZE)
     248                                                               + RT_ALIGN_Z(VIRTUALKB_CMDBODY_SIZE,       PAGE_SIZE)
     249                                                               + RT_ALIGN_Z(VIRTUALKB_CMDBODY_POST_FENCE, PAGE_SIZE));
     250                if (pbCmdBody)
     251                {
     252                    rc = RTMemProtect(pbCmdBody, RT_ALIGN_Z(VIRTUALKB_CMDBODY_PRE_FENCE, PAGE_SIZE), RTMEM_PROT_NONE);
     253                    pbCmdBody += RT_ALIGN_Z(VIRTUALKB_CMDBODY_PRE_FENCE, PAGE_SIZE);
     254
     255                    pThis->fFencedCmdBody = true;
     256                    pThis->pbCmdBody = (char *)pbCmdBody;
     257                    rc = RTMemProtect(pbCmdBody, RT_ALIGN_Z(VIRTUALKB_CMDBODY_SIZE, PAGE_SIZE), RTMEM_PROT_READ | RTMEM_PROT_WRITE);
     258                    AssertLogRelRC(rc);
     259                    pbCmdBody += RT_ALIGN_Z(VIRTUALKB_CMDBODY_SIZE, PAGE_SIZE);
     260
     261                    rc = RTMemProtect(pbCmdBody, RT_ALIGN_Z(VIRTUALKB_CMDBODY_PRE_FENCE, PAGE_SIZE), RTMEM_PROT_NONE);
     262                    AssertLogRelRC(rc);
     263                }
     264                else
     265                {
     266                    LogRel(("VirtualKB: RTMemPageAlloc failed, falling back on regular alloc.\n"));
     267                    pThis->pbCmdBody = (char *)RTMemAllocZ(VIRTUALKB_CMDBODY_SIZE);
     268                    AssertLogRelReturn(pThis->pbCmdBody, VERR_NO_MEMORY);
     269                }
     270
    211271                IOMIOPORTHANDLE hIoPorts;
    212272                rc = PDMDevHlpIoPortCreateAndMap(pDevIns, 0x5658 /*uPort*/, 2 /*cPorts*/, vkdPortWrite, vkdPortRead,
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