[syslinux] [PATCH] EFI TCP buffer reuse bug

Gene Cumm gene.cumm at gmail.com
Thu Nov 23 19:35:34 PST 2017


On Tue, Nov 21, 2017 at 4:55 PM, Joshua.Weage--- via Syslinux
<syslinux at zytor.com> wrote:
> The attached patch resolves a buffer reuse bug in the efi/tcp.c code. The bug can be triggered when multiple TCP connections are opened when using the EFI bootloader.
>
> Signed-off-by: Joshua Weage <joshua.weage at dell.com>
>
> ---

Re-ordering to help discussion.

> --- master/efi/tcp.c    2017-07-22 14:45:46.628674366 -0500
> +++ jw/efi/tcp.c        2017-07-24 09:24:37.072922478 -0500
> @@ -199,8 +199,6 @@ void core_tcp_close_file(struct inode *i
>      socket->net.efi.binding = NULL;
>  }-
>
> -static char databuf[8192];
> -
>  void core_tcp_fill_buffer(struct inode *inode)
>  {
>      struct pxe_pvt_inode *socket = PVT(inode);
> @@ -210,7 +208,6 @@ void core_tcp_fill_buffer(struct inode *
>      EFI_TCP4_FRAGMENT_DATA *frag;
>      EFI_STATUS status;
>      EFI_TCP4 *tcp = (EFI_TCP4 *)b->this;
> -    void *data;
>      size_t len;
>
>      memset(&iotoken, 0, sizeof(iotoken));
> @@ -223,10 +220,10 @@ void core_tcp_fill_buffer(struct inode *
>
>      iotoken.Packet.RxData = &rxdata;
>      rxdata.FragmentCount = 1;
> -    rxdata.DataLength = sizeof(databuf);
> +    rxdata.DataLength = sizeof(socket->tcp_databuf);
>      frag = &rxdata.FragmentTable[0];
> -    frag->FragmentBuffer = databuf;
> -    frag->FragmentLength = sizeof(databuf);
> +    frag->FragmentBuffer = socket->tcp_databuf;
> +    frag->FragmentLength = sizeof(socket->tcp_databuf);
>
>      status = uefi_call_wrapper(tcp->Receive, 2, tcp, &iotoken);
>      if (status == EFI_CONNECTION_FIN) {
> @@ -244,10 +241,8 @@ void core_tcp_fill_buffer(struct inode *
>      cb_status = -1;
>
>      len = frag->FragmentLength;
> -    memcpy(databuf, frag->FragmentBuffer, len);
> -    data = databuf;
>
> -    socket->tftp_dataptr = data;
> +    socket->tftp_dataptr = socket->tcp_databuf;
>      socket->tftp_filepos += len;
>      socket->tftp_bytesleft = len;

The idea of this makes a lot of sense: Don't potentially re-use the
same buffer across all of Syslinux when a concurrency issue might
arise.

> --- master/core/fs/pxe/pxe.h    2017-07-22 14:45:46.561674329 -0500
> +++ jw/core/fs/pxe/pxe.h        2017-07-23 19:44:46.466498950 -0500
> @@ -144,6 +144,7 @@ struct pxe_pvt_inode {
>      uint8_t  tftp_goteof;         /* 1 if the EOF packet received */
>      uint8_t  tftp_unused[3];      /* Currently unused */
>      char    *tftp_pktbuf;         /* Packet buffer */
> +    char     tcp_databuf[8192];   /* data buffer */
>      struct inode *ctl;           /* Control connection (for FTP) */
>      const struct pxe_conn_ops *ops;
>  };

Why are we forcibly allocating an 8kiB buffer in a struct that won't
be used on a non-lwIP PXELINUX?  Why not either re-use the existing
buffer pointer, perhaps renaming it more generically and storing its
length since we won't be using the same pxe_pvt_inode struct for a
TFTP transaction and a TCP transaction?

If you'd like, I can propose an alternative patch.

-- 
-Gene


More information about the Syslinux mailing list