On Fri, Jan 26, 2018 at 12:25:56AM +0100, Christian Weisgerber wrote:
> Fix TFTP reading of zero-size files in efiboot:
> 
> The AllocatePages EFI call returns an error when the allocation
> size is 0.  Skip allocating memory and actually transferring the
> file when it is empty.
> 
> Properly return the number of unread bytes so that a read() of n
> bytes does not return n if no bytes were read.
> 
> While here, disallow lseek() beyond the TFTP file buffer for SEEK_CUR
> as we already do for SEEK_SET.
> 
> ----
> 
> Tested on aarch64.  Can somebody test this on amd64?
> OK?

Works for me on amd64.

ok patrick@

> 
> Index: arch/amd64/stand/efiboot/conf.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/amd64/stand/efiboot/conf.c,v
> retrieving revision 1.12
> diff -u -p -r1.12 conf.c
> --- arch/amd64/stand/efiboot/conf.c   25 Nov 2017 19:02:07 -0000      1.12
> +++ arch/amd64/stand/efiboot/conf.c   25 Jan 2018 22:39:37 -0000
> @@ -39,7 +39,7 @@
>  #include "efidev.h"
>  #include "efipxe.h"
>  
> -const char version[] = "3.36";
> +const char version[] = "3.37";
>  
>  #ifdef EFI_DEBUG
>  int  debug = 0;
> Index: arch/amd64/stand/efiboot/efipxe.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/amd64/stand/efiboot/efipxe.c,v
> retrieving revision 1.2
> diff -u -p -r1.2 efipxe.c
> --- arch/amd64/stand/efiboot/efipxe.c 21 Jan 2018 21:37:01 -0000      1.2
> +++ arch/amd64/stand/efiboot/efipxe.c 25 Jan 2018 22:46:15 -0000
> @@ -143,6 +143,9 @@ tftp_open(char *path, struct open_file *
>       }
>       tftpfile->inbufsize = size;
>  
> +     if (tftpfile->inbufsize == 0)
> +             goto out;
> +
>       status = EFI_CALL(BS->AllocatePages, AllocateAnyPages, EfiLoaderData,
>           EFI_SIZE_TO_PAGES(tftpfile->inbufsize), &addr);
>       if (status != EFI_SUCCESS) {
> @@ -157,7 +160,7 @@ tftp_open(char *path, struct open_file *
>               free(tftpfile, sizeof(*tftpfile));
>               return ENXIO;
>       }
> -
> +out:
>       f->f_fsdata = tftpfile;
>       return 0;
>  }
> @@ -167,8 +170,9 @@ tftp_close(struct open_file *f)
>  {
>       struct tftp_handle *tftpfile = f->f_fsdata;
>  
> -     EFI_CALL(BS->FreePages, (paddr_t)tftpfile->inbuf,
> -         EFI_SIZE_TO_PAGES(tftpfile->inbufsize));
> +     if (tftpfile->inbuf != NULL)
> +             EFI_CALL(BS->FreePages, (paddr_t)tftpfile->inbuf,
> +                 EFI_SIZE_TO_PAGES(tftpfile->inbufsize));
>       free(tftpfile, sizeof(*tftpfile));
>       return 0;
>  }
> @@ -184,15 +188,11 @@ tftp_read(struct open_file *f, void *add
>       else
>               toread = size;
>  
> -     if (toread == 0) {
> -             if (resid != NULL)
> -                     *resid = 0;
> -             return (0);
> +     if (toread != 0) {
> +             memcpy(addr, tftpfile->inbuf + tftpfile->inbufoff, toread);
> +             tftpfile->inbufoff += toread;
>       }
>  
> -     memcpy(addr, tftpfile->inbuf + tftpfile->inbufoff, toread);
> -     tftpfile->inbufoff += toread;
> -
>       if (resid != NULL)
>               *resid = size - toread;
>       return 0;
> @@ -211,7 +211,8 @@ tftp_seek(struct open_file *f, off_t off
>  
>       switch(where) {
>       case SEEK_CUR:
> -             if (tftpfile->inbufoff + offset < 0) {
> +             if (tftpfile->inbufoff + offset < 0 ||
> +                 tftpfile->inbufoff + offset > tftpfile->inbufsize) {
>                       errno = EOFFSET;
>                       break;
>               }
> Index: arch/arm64/stand/efiboot/conf.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/arm64/stand/efiboot/conf.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 conf.c
> --- arch/arm64/stand/efiboot/conf.c   21 Jan 2018 21:35:34 -0000      1.10
> +++ arch/arm64/stand/efiboot/conf.c   25 Jan 2018 20:42:46 -0000
> @@ -36,7 +36,7 @@
>  #include "efidev.h"
>  #include "efipxe.h"
>  
> -const char version[] = "0.9";
> +const char version[] = "0.10";
>  int  debug = 0;
>  
>  struct fs_ops file_system[] = {
> Index: arch/arm64/stand/efiboot/efipxe.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/arm64/stand/efiboot/efipxe.c,v
> retrieving revision 1.1
> diff -u -p -r1.1 efipxe.c
> --- arch/arm64/stand/efiboot/efipxe.c 21 Jan 2018 21:35:34 -0000      1.1
> +++ arch/arm64/stand/efiboot/efipxe.c 25 Jan 2018 22:45:08 -0000
> @@ -139,6 +139,9 @@ tftp_open(char *path, struct open_file *
>       }
>       tftpfile->inbufsize = size;
>  
> +     if (tftpfile->inbufsize == 0)
> +             goto out;
> +
>       status = EFI_CALL(BS->AllocatePages, AllocateAnyPages, EfiLoaderData,
>           EFI_SIZE_TO_PAGES(tftpfile->inbufsize), &addr);
>       if (status != EFI_SUCCESS) {
> @@ -153,7 +156,7 @@ tftp_open(char *path, struct open_file *
>               free(tftpfile, sizeof(*tftpfile));
>               return ENXIO;
>       }
> -
> +out:
>       f->f_fsdata = tftpfile;
>       return 0;
>  }
> @@ -163,8 +166,9 @@ tftp_close(struct open_file *f)
>  {
>       struct tftp_handle *tftpfile = f->f_fsdata;
>  
> -     EFI_CALL(BS->FreePages, (paddr_t)tftpfile->inbuf,
> -         EFI_SIZE_TO_PAGES(tftpfile->inbufsize));
> +     if (tftpfile->inbuf != NULL)
> +             EFI_CALL(BS->FreePages, (paddr_t)tftpfile->inbuf,
> +                 EFI_SIZE_TO_PAGES(tftpfile->inbufsize));
>       free(tftpfile, sizeof(*tftpfile));
>       return 0;
>  }
> @@ -180,15 +184,11 @@ tftp_read(struct open_file *f, void *add
>       else
>               toread = size;
>  
> -     if (toread == 0) {
> -             if (resid != NULL)
> -                     *resid = 0;
> -             return (0);
> +     if (toread != 0) {
> +             memcpy(addr, tftpfile->inbuf + tftpfile->inbufoff, toread);
> +             tftpfile->inbufoff += toread;
>       }
>  
> -     memcpy(addr, tftpfile->inbuf + tftpfile->inbufoff, toread);
> -     tftpfile->inbufoff += toread;
> -
>       if (resid != NULL)
>               *resid = size - toread;
>       return 0;
> @@ -207,7 +207,8 @@ tftp_seek(struct open_file *f, off_t off
>  
>       switch(where) {
>       case SEEK_CUR:
> -             if (tftpfile->inbufoff + offset < 0) {
> +             if (tftpfile->inbufoff + offset < 0 ||
> +                 tftpfile->inbufoff + offset > tftpfile->inbufsize) {
>                       errno = EOFFSET;
>                       break;
>               }
> -- 
> Christian "naddy" Weisgerber                          [email protected]
> 

Reply via email to