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]
>