bug-grub
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[bug #38111] EFI TFTP packet corruption


From: Lingzhu Xiang
Subject: [bug #38111] EFI TFTP packet corruption
Date: Fri, 18 Jan 2013 04:25:55 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11

URL:
  <http://savannah.gnu.org/bugs/?38111>

                 Summary: EFI TFTP packet corruption
                 Project: GNU GRUB
            Submitted by: xlz
            Submitted on: Fri 18 Jan 2013 04:25:54 AM GMT
                Category: Network
                Severity: Major
                Priority: 5 - Normal
              Item Group: Software Error
                  Status: None
                 Privacy: Public
             Assigned to: None
         Originator Name: 
        Originator Email: 
             Open/Closed: Open
         Discussion Lock: Any
                 Release: 
                 Release: other
         Reproducibility: Every Time
         Planned Release: None

    _______________________________________________________

Details:

UEFI PXE boot fails and falls back to command line.

Packet capture shows it successfully loaded grub.cfg and a few files. Then it
sends two malformed packets of 60 zero bytes and no more packets are sent.
There are icmpv6 messages like router solicitation and listener report.

Version: Fedora's grub2-efi-2.00-15.fc18 based on grub-2.00.

Reproduced on Dell XPS 8500 (Firmware: EFI v2.31, likely a EDK2 mod), capable
of IPv4/6 PXE.

Adding random link delay between the booting machine and tftp server with
netem won't change the number and order of malformed packets. Malformed
packets are sent after certain tftp requests in a deterministic manner.

I added a printf in net/drivers/efi/efinet.c:

static grub_err_t
send_card_buffer (struct grub_net_card *dev,
                  struct grub_net_buff *pack)
{
...
  if (dev->txbusy)
    while (1)
      {
        void *txbuf = NULL;
        st = efi_call_3 (net->get_status, net, 0, &txbuf);
        if (st != GRUB_EFI_SUCCESS)
          return grub_error (GRUB_ERR_IO,
                             N_("couldn't send network packet"));
        if (txbuf == dev->txbuf)
          {
            dev->txbusy = 0;
            break;
          }
        if (txbuf)
            grub_printf("not my txbuf: txbuf=%p dev->txbuf=%p\n", txbuf,
dev->txbuf);
        if (limit_time < grub_get_time_ms ())
          return grub_error (GRUB_ERR_TIMEOUT, N_("couldn't send network
packet"));
      }

I got "not my txbuf: txbuf=0xd237a698 dev->txbuf=0xce9b6160" before falling
back into command line. I hasn't seen txbuf value other than 0xd237a698, but
dev->txbuf sometimes changes.

My guess is that the firmware's ipv6 stack sending icmpv6 messages gets into a
race condition with GetStatus by grub's efinet. GetStatus in SNP will remove
the returned txbuf from the "transmitted buffer queue" and indicate the txbuf
has finished transmission. The "not my txbuf" message probably shows grub
stole the txbuf of an icmpv6 router solicitation and couldn't get its own
txbuf any more. Hence the network stalls.

Grub's efinet uses SNP which only allows exclusive access for one application
while the firmware's (EDK2) IPv6 stack uses MNP which is an abstraction over
SNP to allow concurrent operation. This looks quite problematic.




    _______________________________________________________

Reply to this item at:

  <http://savannah.gnu.org/bugs/?38111>

_______________________________________________
  Message sent via/by Savannah
  http://savannah.gnu.org/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]