qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Berger <stefanb@linux.ibm.com>
To: P J P <ppandit@redhat.com>
Cc: "QEMU Developers" <qemu-devel@nongnu.org>,
	"Marc-André Lureau" <marcandre.lureau@gmail.com>,
	"Stefan Berger" <stefanb@linux.vnet.ibm.com>,
	"Cheng Feng" <PSIRT@huawei.com>
Subject: Re: [Qemu-devel] [PATCH v1] tpm: check localities index
Date: Wed, 21 Nov 2018 08:36:07 -0500	[thread overview]
Message-ID: <00888856-0af3-7b1a-4622-3edbac9fe77f@linux.ibm.com> (raw)
In-Reply-To: <nycvar.YSQ.7.76.1811202318190.17923@xnncv>

On 11/20/18 1:06 PM, P J P wrote:
>    Hello Stefan,
>
> +-- On Tue, 20 Nov 2018, Stefan Berger wrote --+
> | On 11/20/18 2:22 AM, P J P wrote:
> | > From: Prasad J Pandit <pjp@fedoraproject.org>
> | >
> | > While performing mmio device r/w operations, guest could set 'addr'
> | > parameter such that 'locty' index exceeds TPM_TIS_NUM_LOCALITIES=5
> | > after setting new 'locty' via 'tpm_tis_new_active_locality'.
> | > Add check to avoid OOB access.
> |
> | Do you have test code that can set the memory to such a locality or is this
> | purely hypothetical at the moment?
>
> It's not hypothetical, reporter used tpm-emulator below
>
>    -> https://github.com/PeterHuewe/tpm-emulator
>
> with an old version of QEMU. I shared the details with Marc-Andre earlier
> today.
>
> | We are registering this MMIO area:
> |
> |     memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops,
> |                           s, "tpm-tis-mmio",
> |                           TPM_TIS_NUM_LOCALITIES <<
> | TPM_TIS_LOCALITY_SHIFT);
> |
> | #define TPM_TIS_NUM_LOCALITIES      5
> |
> | #define TPM_TIS_LOCALITY_SHIFT      12
> |
> | --> 5 << 12 = 0x5000, thus we get memory locations [0 .. 0x4fff]
> |
> |
> | We have the following code to get from an address to the locality:
> |
> | static uint8_t tpm_tis_locality_from_addr(hwaddr addr)
> | {
> |     return (uint8_t)((addr >> TPM_TIS_LOCALITY_SHIFT) & 0x7);
> | }
> |
> | With this we would get localities of [0x0 .. 0x4] following the memory
> | locations [0 .. 0x4fff] above.
>
>    Right. IIUC mmio r/w routines called with 'addr' value like 0x07000 may set
> 'locty' to > TPM_TIS_NUM_LOCALITIES. Also in mmio_write at one point,

offsets >= 0x5000 would never reach the tpm_tis emulator. If 0x7000 was 
to reach it, why not 0x70000 also or any other offset ?


> 'active_locty' is set to TPM_TIS_NO_LOCALITY(=0xff), which may be used to set
> 'new_locty'.

There's no 'new_locty'. These variables are critical, so which one do 
you mean?

I audited all functions yesterday and my proposed patches are on the 
mailing list. The abort related ones seem most critical but they are all 
passed values they can handle. I do not think that an out-of-bounds 
access can occur with the current code.


I concur with Marc's comments that an 
'assert(TPM_TIS_IS_VALID_LOCTY(locty));' on a preceding ' uint8_t locty 
= tpm_tis_locality_from_addr(addr);' isn't necessary unless something in 
the core code is seriously broken. tpm_tis covers address offsets of 
[0x0 .. 0x4fff] from its base address , which maps to localities 0..4.

>   
>
> tpm_tis_mmio_write
>     ...
>     active_locty = TPM_TIS_NO_LOCALITY(=0xff);
>     ...
>     tpm_tis_new_active_locality(s, active_locty);

And this particular function can handle active_locty = 0xff:

static void tpm_tis_new_active_locality(TPMState *s, uint8_t 
new_active_locty)
{
     bool change = (s->active_locty != new_active_locty);
     bool is_seize;
     uint8_t mask;

     if (change && TPM_TIS_IS_VALID_LOCTY(s->active_locty)) {
         is_seize = TPM_TIS_IS_VALID_LOCTY(new_active_locty) &&
                    s->loc[new_active_locty].access & TPM_TIS_ACCESS_SEIZE;

         if (is_seize) {
             mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY);
         } else {
             mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY|
                      TPM_TIS_ACCESS_REQUEST_USE);
         }
         /* reset flags on the old active locality */
         s->loc[s->active_locty].access &= mask;

         if (is_seize) {
             s->loc[s->active_locty].access |= TPM_TIS_ACCESS_BEEN_SEIZED;
         }
     }

     s->active_locty = new_active_locty;

     trace_tpm_tis_new_active_locality(s->active_locty);

     if (TPM_TIS_IS_VALID_LOCTY(new_active_locty)) {
         /* set flags on the new active locality */
         s->loc[new_active_locty].access |= TPM_TIS_ACCESS_ACTIVE_LOCALITY;
         s->loc[new_active_locty].access &= ~(TPM_TIS_ACCESS_REQUEST_USE |
TPM_TIS_ACCESS_SEIZE);
     }

     if (change) {
         tpm_tis_raise_irq(s, s->active_locty, 
TPM_TIS_INT_LOCALITY_CHANGED);
     }
}

There's no out-of-bounds access possible in this function if 
new_active_locty = 0xff. tpm_tis_raise_irq is protecting itself.

  The function may set the active_locty to 0xff, meaning there's no 
active locality. From what I can see all functions using active_locty 
with 0xff afterwards can handle it.


>
>
> tpm_tis_new_active_locality(TPMState *s, uint8_t new_active_locty)
>     ...
>     s->active_locty = new_active_locty;
>
>
> Thank you.
> --
> Prasad J Pandit / Red Hat Product Security Team
> 47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F

  parent reply	other threads:[~2018-11-21 13:36 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-20  7:22 [Qemu-devel] [PATCH v1] tpm: check localities index P J P
2018-11-20  8:02 ` Marc-André Lureau
2018-11-20 11:23   ` Marc-André Lureau
2018-11-20 15:52 ` Stefan Berger
2018-11-20 18:06   ` P J P
2018-11-21 11:52     ` P J P
2018-11-21 13:36     ` Stefan Berger [this message]
2018-11-22 10:11       ` P J P
2018-11-21 15:41 ` Stefan Berger
2018-11-21 16:26 ` no-reply
2018-11-21 17:54   ` Stefan Berger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=00888856-0af3-7b1a-4622-3edbac9fe77f@linux.ibm.com \
    --to=stefanb@linux.ibm.com \
    --cc=PSIRT@huawei.com \
    --cc=marcandre.lureau@gmail.com \
    --cc=ppandit@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanb@linux.vnet.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).