VirtualBox

Changeset 96757 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Sep 16, 2022 12:41:19 AM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
153645
Message:

IPRT/ldrELF: Added some basic linux kernel signature support, completely untested. Should make some of the RTSignTool commands work with kmods when debugged. bugref:10287

Location:
trunk/src/VBox/Runtime/common/ldr
Files:
2 edited

Legend:

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

    r96407 r96757  
    4343#include "internal/iprt.h"
    4444
    45 #include <iprt/alloc.h>
     45#include <iprt/alloca.h>
     46#include <iprt/asm.h>
    4647#include <iprt/assert.h>
    4748#include <iprt/dbg.h>
    4849#include <iprt/string.h>
    4950#include <iprt/log.h>
     51#include <iprt/mem.h>
    5052#include <iprt/err.h>
     53#include <iprt/crypto/digest.h>
    5154#include <iprt/formats/elf32.h>
    5255#include <iprt/formats/elf64.h>
     
    6972
    7073
     74/*********************************************************************************************************************************
     75*   Structures and Typedefs                                                                                                      *
     76*********************************************************************************************************************************/
     77/** Magic string for RTLDRLNXMODSIG::achMagic   */
     78#define RTLDRLNXMODSIG_MAGIC "~Module signature appended~\n"
     79AssertCompile(sizeof(RTLDRLNXMODSIG_MAGIC) == 29);
     80
     81/**
     82 * Linux kernel module signature footer - found at the end of the file.
     83 */
     84typedef struct RTLDRLNXMODSIG
     85{
     86    /** Zero. */
     87    uint8_t         bAlgo;
     88    /** Zero. */
     89    uint8_t         bHash;
     90    /** Signature type (RTLDRLNXMODSIG_TYPE_PKCS7). */
     91    uint8_t         bType;
     92    /** Zero. */
     93    uint8_t         cbSignerName;
     94    /** Zero. */
     95    uint8_t         cbKeyId;
     96    /** Zero padding. */
     97    uint8_t         abReserved[3];
     98    /** The length of the signature preceeding this footer structure. */
     99    uint32_t        cbSignature;
     100    /** Magic value identifying this structure.   */
     101    char            achMagic[sizeof(RTLDRLNXMODSIG_MAGIC) - 1];
     102} RTLDRLNXMODSIG;
     103typedef RTLDRLNXMODSIG *PRTLDRLNXMODSIG;
     104typedef RTLDRLNXMODSIG const *PCRTLDRLNXMODSIG;
     105/** Signature type.   */
     106#define RTLDRLNXMODSIG_TYPE_PKCS7   2
     107
     108
    71109
    72110/*********************************************************************************************************************************
    73111*   Internal Functions                                                                                                           *
    74112*********************************************************************************************************************************/
     113static int rtLdrELFLnxKModQueryPropIsSigned(PRTLDRREADER pReader, bool *pfRet);
     114static int rtLdrELFLnxKModQueryPropPkcs7SignedData(PRTLDRREADER pReader, void *pvBuf, size_t cbBuf, size_t *pcbRet);
     115static DECLCALLBACK(int) rtldrELFLnxKModHashImage(PRTLDRMODINTERNAL pMod, RTDIGESTTYPE enmDigest, uint8_t *pabHash, size_t cbHash);
    75116#ifdef LOG_ENABLED
    76117static const char *rtldrElfGetShdrType(uint32_t iType);
     
    152193#endif /* LOG_ENABLED*/
    153194
     195/**
     196 * Reads in what migt be a linux kernel module signature footer.
     197 */
     198static int rtLdrELFLnxKModReadFooter(PRTLDRREADER pReader, PRTLDRLNXMODSIG pSigFooter, uint64_t *pcbFile)
     199{
     200    /*
     201     * Look for the linux module signature at the end of the file.
     202     * This should be safe to read w/o any size checking as it is smaller than the elf header.
     203     */
     204    uint64_t cbFile = pReader->pfnSize(pReader);
     205    *pcbFile = cbFile;
     206
     207    AssertCompile(sizeof(*pSigFooter) <= sizeof(Elf32_Ehdr));
     208    return pReader->pfnRead(pReader, pSigFooter, sizeof(*pSigFooter), cbFile - sizeof(*pSigFooter));
     209}
     210
     211
     212/**
     213 * Check that a linux kernel module signature footer is valid.
     214 */
     215static bool rtLdrELFLnxKModIsFooterValid(PCRTLDRLNXMODSIG pSigFooter, uint64_t cbFile)
     216{
     217    if (memcmp(pSigFooter->achMagic, RTLDRLNXMODSIG_MAGIC, sizeof(pSigFooter->achMagic)) == 0)
     218    {
     219        uint32_t const cbSignature = RT_N2H_U32(pSigFooter->cbSignature);
     220        if (cbSignature > 32 && cbSignature + sizeof(*pSigFooter) < cbFile)
     221            return pSigFooter->bAlgo        == 0
     222                && pSigFooter->bHash        == 0
     223                && pSigFooter->cbSignerName == 0
     224                && pSigFooter->cbKeyId      == 0;
     225    }
     226    return false;
     227}
     228
     229
     230/**
     231 * Handles the linux kernel module signature part of RTLDRPROP_IS_SIGNED
     232 * queries.
     233 */
     234static int rtLdrELFLnxKModQueryPropIsSigned(PRTLDRREADER pReader, bool *pfRet)
     235{
     236    *pfRet = false;
     237    AssertReturn(pReader, VERR_INVALID_STATE);
     238
     239    uint64_t       cbFile;
     240    RTLDRLNXMODSIG SigFooter;
     241    int rc = rtLdrELFLnxKModReadFooter(pReader, &SigFooter, &cbFile);
     242    if (RT_SUCCESS(rc))
     243        *pfRet = rtLdrELFLnxKModIsFooterValid(&SigFooter, cbFile);
     244    return rc;
     245}
     246
     247
     248/**
     249 * Handles the linux kernel module signature part of RTLDRPROP_IS_SIGNED
     250 * queries.
     251 */
     252static int rtLdrELFLnxKModQueryPropPkcs7SignedData(PRTLDRREADER pReader, void *pvBuf, size_t cbBuf, size_t *pcbRet)
     253{
     254    AssertReturn(pReader, VERR_INVALID_STATE);
     255
     256    uint64_t       cbFile;
     257    RTLDRLNXMODSIG SigFooter;
     258    int rc = rtLdrELFLnxKModReadFooter(pReader, &SigFooter, &cbFile);
     259    if (RT_SUCCESS(rc))
     260    {
     261        if (   rtLdrELFLnxKModIsFooterValid(&SigFooter, cbFile)
     262            && SigFooter.bType == RTLDRLNXMODSIG_TYPE_PKCS7)
     263        {
     264            uint32_t const cbSignature = RT_N2H_U32(SigFooter.cbSignature);
     265            *pcbRet = cbSignature;
     266            if (cbSignature <= cbBuf)
     267                rc = pReader->pfnRead(pReader, pvBuf, cbSignature, cbFile - sizeof(SigFooter) - cbSignature);
     268            else
     269                rc = VERR_BUFFER_OVERFLOW;
     270        }
     271        else
     272            rc = VERR_NOT_FOUND;
     273    }
     274    return rc;
     275}
     276
     277
     278/**
     279 * @interface_method_impl{,pfnHashImage,
     280 * Handles the linux kernel module signatures.}
     281 */
     282static DECLCALLBACK(int) rtldrELFLnxKModHashImage(PRTLDRMODINTERNAL pMod, RTDIGESTTYPE enmDigest, uint8_t *pabHash, size_t cbHash)
     283{
     284    PRTLDRREADER pReader = pMod->pReader;
     285    AssertReturn(pReader, VERR_INVALID_STATE);
     286
     287    /*
     288     * Get the file size and subtract any linux kernel module signature from it
     289     * since it's not part of the hash.
     290     */
     291    uint64_t       cbFile;
     292    RTLDRLNXMODSIG SigFooter;
     293    int rc = rtLdrELFLnxKModReadFooter(pReader, &SigFooter, &cbFile);
     294    if (RT_SUCCESS(rc))
     295    {
     296        if (rtLdrELFLnxKModIsFooterValid(&SigFooter, cbFile))
     297            cbFile -= sizeof(SigFooter) - RT_N2H_U32(SigFooter.cbSignature);
     298
     299        /*
     300         * Now hash the file.
     301         */
     302        RTCRDIGEST hDigest;
     303        rc = RTCrDigestCreateByType(&hDigest, enmDigest);
     304        if (RT_SUCCESS(rc))
     305        {
     306            uint32_t cbBuf = _64K;
     307            void    *pvBuf = RTMemTmpAlloc(_64K);
     308            void    *pvBufFree = pvBuf;
     309            if (!pvBuf)
     310            {
     311                cbBuf = _4K;
     312                pvBuf = alloca(_4K);
     313            }
     314
     315            for (uint64_t offFile = 0; offFile < cbFile; )
     316            {
     317                uint64_t cbLeft = cbFile - offFile;
     318                uint32_t cbToRead = cbLeft >= cbBuf ? cbBuf : (uint32_t)cbLeft;
     319                rc = pReader->pfnRead(pReader, pvBuf, cbToRead, offFile);
     320                AssertRCBreak(rc);
     321
     322                rc = RTCrDigestUpdate(hDigest, pvBuf, cbToRead);
     323                offFile += cbToRead;
     324                AssertRCBreak(rc);
     325            }
     326
     327            RTMemTmpFree(pvBufFree);
     328
     329            if (RT_SUCCESS(rc))
     330                rc = RTCrDigestFinal(hDigest, pabHash, cbHash);
     331            RTCrDigestRelease(hDigest);
     332        }
     333    }
     334    return rc;
     335}
     336
    154337
    155338/**
  • trunk/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h

    r96407 r96757  
    17111711
    17121712
    1713 /** @interface_method_impl{RTLDROPS,pfnQueryProp} */
    1714 static DECLCALLBACK(int) RTLDRELF_NAME(QueryProp)(PRTLDRMODINTERNAL pMod, RTLDRPROP enmProp, void const *pvBits,
    1715                                                   void *pvBuf, size_t cbBuf, size_t *pcbRet)
    1716 {
    1717     PRTLDRMODELF pThis = (PRTLDRMODELF)pMod;
    1718 
    1719     if (enmProp != RTLDRPROP_BUILDID)
    1720         return VERR_NOT_FOUND;
    1721 
     1713/**
     1714 * Handles RTLDRPROP_BUILDID queries.
     1715 */
     1716static int RTLDRELF_NAME(QueryPropBuildId)(PRTLDRMODELF pThis, void *pvBuf, size_t cbBuf, size_t *pcbRet)
     1717{
    17221718    /*
    17231719     * Map the image bits if not already done and setup pointer into it.
     
    17611757    }
    17621758
    1763     NOREF(cbBuf);
    1764     RT_NOREF_PV(pvBits);
    17651759    return VERR_NOT_FOUND;
     1760}
     1761
     1762
     1763/** @interface_method_impl{RTLDROPS,pfnQueryProp} */
     1764static DECLCALLBACK(int) RTLDRELF_NAME(QueryProp)(PRTLDRMODINTERNAL pMod, RTLDRPROP enmProp, void const *pvBits,
     1765                                                  void *pvBuf, size_t cbBuf, size_t *pcbRet)
     1766{
     1767    PRTLDRMODELF pThis = (PRTLDRMODELF)pMod;
     1768    RT_NOREF(pvBits);
     1769    switch (enmProp)
     1770    {
     1771        case RTLDRPROP_BUILDID:
     1772            return RTLDRELF_NAME(QueryPropBuildId)(pThis, pvBuf, cbBuf, pcbRet);
     1773
     1774        case RTLDRPROP_IS_SIGNED:
     1775            *pcbRet = sizeof(bool);
     1776            return rtLdrELFLnxKModQueryPropIsSigned(pThis->Core.pReader, (bool *)pvBuf);
     1777
     1778        case RTLDRPROP_PKCS7_SIGNED_DATA:
     1779            *pcbRet = sizeof(bool);
     1780            return rtLdrELFLnxKModQueryPropPkcs7SignedData(pThis->Core.pReader, pvBuf, cbBuf, pcbRet);
     1781
     1782        default:
     1783            return VERR_NOT_FOUND;
     1784    }
    17661785}
    17671786
     
    18771896    RTLDRELF_NAME(QueryProp),
    18781897    NULL /*pfnVerifySignature*/,
    1879     NULL /*pfnHashImage*/,
     1898    rtldrELFLnxKModHashImage,
    18801899    RTLDRELF_NAME(UnwindFrame),
    18811900    42
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