All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jason Wang <jasowang@redhat.com>
To: Mauro Matteo Cascella <mcascell@redhat.com>
Cc: gaoning.pgn@antgroup.com, 330cjfdn@gmail.com,
	Dmitry Fleytman <dmitry.fleytman@gmail.com>,
	Laszlo Ersek <lersek@redhat.com>,
	QEMU Developers <qemu-devel@nongnu.org>
Subject: Re: [PATCH v2] net/e1000e_core: adjust count if RDH exceeds RDT in e1000e_ring_advance()
Date: Tue, 1 Dec 2020 13:42:01 +0800	[thread overview]
Message-ID: <201732a8-3d1e-0553-4812-b8e8885b896f@redhat.com> (raw)
In-Reply-To: <CAA8xKjU-ewhPaea8fg7YKxGTo8Da4YK+GpxzDvJOsTWraT1Edw@mail.gmail.com>


On 2020/11/30 下午10:12, Mauro Matteo Cascella wrote:
> On Mon, Nov 30, 2020 at 3:58 AM Jason Wang <jasowang@redhat.com> wrote:
>>
>> On 2020/11/27 下午10:49, Mauro Matteo Cascella wrote:
>>> On Fri, Nov 27, 2020 at 6:21 AM Jason Wang <jasowang@redhat.com> wrote:
>>>> On 2020/11/24 上午5:30, Mauro Matteo Cascella wrote:
>>>>> On Thu, Nov 19, 2020 at 6:57 AM Jason Wang <jasowang@redhat.com> wrote:
>>>>>> On 2020/11/18 下午4:53, Mauro Matteo Cascella wrote:
>>>>>>> On Wed, Nov 18, 2020 at 4:56 AM Jason Wang <jasowang@redhat.com> wrote:
>>>>>>>> On 2020/11/13 下午6:31, Mauro Matteo Cascella wrote:
>>>>>>>>> The e1000e_write_packet_to_guest() function iterates over a set of
>>>>>>>>> receive descriptors by advancing rx descriptor head register (RDH) from
>>>>>>>>> its initial value to rx descriptor tail register (RDT). The check in
>>>>>>>>> e1000e_ring_empty() is responsible for detecting whether RDH has reached
>>>>>>>>> RDT, terminating the loop if that's the case. Additional checks have
>>>>>>>>> been added in the past to deal with bogus values submitted by the guest
>>>>>>>>> to prevent possible infinite loop. This is done by "wrapping around" RDH
>>>>>>>>> at some point and detecting whether it assumes the original value during
>>>>>>>>> the loop.
>>>>>>>>>
>>>>>>>>> However, when e1000e is configured to use the packet split feature, RDH is
>>>>>>>>> incremented by two instead of one, as the packet split descriptors are
>>>>>>>>> 32 bytes while regular descriptors are 16 bytes. A malicious or buggy
>>>>>>>>> guest may set RDT to an odd value and transmit only null RX descriptors.
>>>>>>>>> This corner case would prevent RDH from ever matching RDT, leading to an
>>>>>>>>> infinite loop. This patch adds a check in e1000e_ring_advance() to make sure
>>>>>>>>> RDH does not exceed RDT in a single incremental step, adjusting the count
>>>>>>>>> value accordingly.
>>>>>>>> Can this patch solve this issue in another way?
>>>>>>>>
>>>>>>>> https://patchew.org/QEMU/20201111130636.2208620-1-ppandit@redhat.com/
>>>>>>>>
>>>>>>>> Thanks
>>>>>>>>
>>>>>>> Yes, it does work nicely. Still, I think this patch is useful to avoid
>>>>>>> possible inconsistent state in e1000e_ring_advance() when count > 1.
>>>>>> So if RDT is odd, it looks to me the following codes in
>>>>>> e1000e_write_packet_to_guest() needs to be fixed as well.
>>>>>>
>>>>>>
>>>>>>             base = e1000e_ring_head_descr(core, rxi);
>>>>>>
>>>>>>             pci_dma_read(d, base, &desc, core->rx_desc_len);
>>>>>>
>>>>>> Otherwise e1000e may try to read out of descriptor ring.
>>>>> Sorry, I'm not sure I understand what you mean. Isn't the base address
>>>>> computed from RDH? How can e1000e read out of the descriptor ring if
>>>>> RDT is odd?
>>>>>
>>>>>> Thanks
>>>>> On Thu, Nov 19, 2020 at 6:57 AM Jason Wang <jasowang@redhat.com> wrote:
>>>>>> On 2020/11/18 下午4:53, Mauro Matteo Cascella wrote:
>>>>>>> On Wed, Nov 18, 2020 at 4:56 AM Jason Wang <jasowang@redhat.com> wrote:
>>>>>>>> On 2020/11/13 下午6:31, Mauro Matteo Cascella wrote:
>>>>>>>>> The e1000e_write_packet_to_guest() function iterates over a set of
>>>>>>>>> receive descriptors by advancing rx descriptor head register (RDH) from
>>>>>>>>> its initial value to rx descriptor tail register (RDT). The check in
>>>>>>>>> e1000e_ring_empty() is responsible for detecting whether RDH has reached
>>>>>>>>> RDT, terminating the loop if that's the case. Additional checks have
>>>>>>>>> been added in the past to deal with bogus values submitted by the guest
>>>>>>>>> to prevent possible infinite loop. This is done by "wrapping around" RDH
>>>>>>>>> at some point and detecting whether it assumes the original value during
>>>>>>>>> the loop.
>>>>>>>>>
>>>>>>>>> However, when e1000e is configured to use the packet split feature, RDH is
>>>>>>>>> incremented by two instead of one, as the packet split descriptors are
>>>>>>>>> 32 bytes while regular descriptors are 16 bytes. A malicious or buggy
>>>>>>>>> guest may set RDT to an odd value and transmit only null RX descriptors.
>>>>>>>>> This corner case would prevent RDH from ever matching RDT, leading to an
>>>>>>>>> infinite loop. This patch adds a check in e1000e_ring_advance() to make sure
>>>>>>>>> RDH does not exceed RDT in a single incremental step, adjusting the count
>>>>>>>>> value accordingly.
>>>>>>>> Can this patch solve this issue in another way?
>>>>>>>>
>>>>>>>> https://patchew.org/QEMU/20201111130636.2208620-1-ppandit@redhat.com/
>>>>>>>>
>>>>>>>> Thanks
>>>>>>>>
>>>>>>> Yes, it does work nicely. Still, I think this patch is useful to avoid
>>>>>>> possible inconsistent state in e1000e_ring_advance() when count > 1.
>>>>>> So if RDT is odd, it looks to me the following codes in
>>>>>> e1000e_write_packet_to_guest() needs to be fixed as well.
>>>>>>
>>>>>>
>>>>>>             base = e1000e_ring_head_descr(core, rxi);
>>>>>>
>>>>>>             pci_dma_read(d, base, &desc, core->rx_desc_len);
>>>>>>
>>>>>> Otherwise e1000e may try to read out of descriptor ring.
>>>>>>
>>>>>> Thanks
>>>> Sorry, I meant RDH actually, when packet split descriptor is used, it
>>>> doesn't check whether DH exceeds DLEN?
>>>>
>>> When the packet split feature is used (i.e., count > 1) this patch
>>> basically sets RDH=RDT in case the increment would exceed RDT.
>>
>> Can software set RDH to an odd value? If not, I think we are probably fine.
>>
>> Thanks
>>
> Honestly I don't know the answer to your question, my guess is that it
> may be possible for a malicious/bogus guest to set RDH the same way as
> RDT.
>
> Thank you,
> --
> Mauro Matteo Cascella
> Red Hat Product Security
> PGP-Key ID: BB3410B0
>
>

Then I think we should fix that.

Thanks



      reply	other threads:[~2020-12-01  5:43 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-13 10:31 [PATCH v2] net/e1000e_core: adjust count if RDH exceeds RDT in e1000e_ring_advance() Mauro Matteo Cascella
2020-11-18  3:56 ` Jason Wang
2020-11-18  8:53   ` Mauro Matteo Cascella
2020-11-19  5:57     ` Jason Wang
2020-11-23 21:30       ` Mauro Matteo Cascella
2020-11-27  5:21         ` Jason Wang
2020-11-27 14:49           ` Mauro Matteo Cascella
2020-11-30  2:58             ` Jason Wang
2020-11-30 14:12               ` Mauro Matteo Cascella
2020-12-01  5:42                 ` Jason Wang [this message]

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=201732a8-3d1e-0553-4812-b8e8885b896f@redhat.com \
    --to=jasowang@redhat.com \
    --cc=330cjfdn@gmail.com \
    --cc=dmitry.fleytman@gmail.com \
    --cc=gaoning.pgn@antgroup.com \
    --cc=lersek@redhat.com \
    --cc=mcascell@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.