Index: lib/libsecureboot/vectx.c =================================================================== --- lib/libsecureboot/vectx.c +++ lib/libsecureboot/vectx.c @@ -211,6 +211,7 @@ vectx_read(struct vectx *ctx, void *buf, size_t nbytes) { unsigned char *bp = buf; + int d; int n; int delta; int x; @@ -221,23 +222,30 @@ off = 0; do { - n = read(ctx->vec_fd, &bp[off], nbytes - off); - if (n < 0) + /* + * Do this in reasonable chunks so + * we don't timeout if doing tftp + */ + x = nbytes - off; + x = MIN(PAGE_SIZE, x); + d = n = read(ctx->vec_fd, &bp[off], x); + if (n < 0) { return (n); - if (n > 0) { + } + if (d > 0) { /* we may have seeked backwards! */ delta = ctx->vec_hashed - ctx->vec_off; if (delta > 0) { - x = MIN(delta, n); + x = MIN(delta, d); off += x; - n -= x; + d -= x; ctx->vec_off += x; } - if (n > 0) { - ctx->vec_md->update(&ctx->vec_ctx.vtable, &bp[off], n); - off += n; - ctx->vec_off += n; - ctx->vec_hashed += n; + if (d > 0) { + ctx->vec_md->update(&ctx->vec_ctx.vtable, &bp[off], d); + off += d; + ctx->vec_off += d; + ctx->vec_hashed += d; } } } while (n > 0 && off < nbytes); Index: stand/libsa/pkgfs.c =================================================================== --- stand/libsa/pkgfs.c +++ stand/libsa/pkgfs.c @@ -60,7 +60,7 @@ }; #define PKG_BUFSIZE 512 -#define PKG_MAXCACHESZ 16384 +#define PKG_MAXCACHESZ (16384 * 3) #define PKG_FILEEXT ".tgz" @@ -132,6 +132,7 @@ static struct package *package = NULL; static int new_package(int, struct package **); +static int cache_data(struct tarfile *tf, int); void pkgfs_cleanup(void) @@ -282,6 +283,9 @@ return (EBADF); } + if (!tf->tf_cachesz) + cache_data(tf, 1); + fp = tf->tf_fp; p = buf; sz = 0; @@ -311,16 +315,6 @@ fp += sz; p += sz; size -= sz; - - if (tf->tf_cachesz != 0) - continue; - - tf->tf_cachesz = (sz <= PKG_MAXCACHESZ) ? sz : PKG_MAXCACHESZ; - tf->tf_cache = malloc(tf->tf_cachesz); - if (tf->tf_cache != NULL) - memcpy(tf->tf_cache, buf, tf->tf_cachesz); - else - tf->tf_cachesz = 0; } tf->tf_fp = fp; @@ -484,8 +478,20 @@ return (0); } +/** + * @brief + * cache data of a tarfile + * + * @param[in] tf + * tarfile pointer + * + * @param[in] force + * If file size > PKG_MAXCACHESZ, cache that much + * + * @return 0, -1 (errno set to error value) + */ static int -cache_data(struct tarfile *tf) +cache_data(struct tarfile *tf, int force) { struct package *pkg; size_t sz; @@ -503,21 +509,28 @@ return (-1); } + if (tf->tf_cachesz) { + DBG(("%s: data already cached\n", __func__)); + errno = EINVAL; + return (-1); + } + if (tf->tf_ofs != pkg->pkg_ofs) { - DBG(("%s: caching after partial read of file %s?\n", + DBG(("%s: caching after force read of file %s?\n", __func__, tf->tf_hdr.ut_name)); errno = EINVAL; return (-1); } /* We don't cache everything... */ - if (tf->tf_size > PKG_MAXCACHESZ) { - errno = ENOMEM; + if (tf->tf_size > PKG_MAXCACHESZ && !force) { + errno = ENOBUFS; return (-1); } + sz = tf->tf_size < PKG_MAXCACHESZ ? tf->tf_size : PKG_MAXCACHESZ; /* All files are padded to a multiple of 512 bytes. */ - sz = (tf->tf_size + 0x1ff) & ~0x1ff; + sz = (sz + 0x1ff) & ~0x1ff; tf->tf_cache = malloc(sz); if (tf->tf_cache == NULL) { @@ -741,7 +754,7 @@ if (ofs != pkg->pkg_ofs) { if (last != NULL && pkg->pkg_ofs == last->tf_ofs) { - if (cache_data(last) == -1) + if (cache_data(last, 0) == -1) return (NULL); } else { sz = ofs - pkg->pkg_ofs; Index: stand/libsa/tftp.c =================================================================== --- stand/libsa/tftp.c +++ stand/libsa/tftp.c @@ -100,11 +100,13 @@ * Jumbo frames in the future. */ #define TFTP_MAX_BLKSIZE 9008 +#define TFTP_TRIES 2 struct tftp_handle { struct iodesc *iodesc; int currblock; /* contents of lastdata */ - int islastblock; /* flag */ + int islastblock:1; /* flag */ + int tries:4; /* number of read attempts */ int validsize; int off; char *path; /* saved for re-requests */ @@ -530,7 +532,14 @@ #ifdef TFTP_DEBUG printf("tftp: read error\n"); #endif - return (rc); + if (tftpfile->tries > TFTP_TRIES) { + return (rc); + } else { + tftpfile->tries++; + tftp_makereq(tftpfile); + } + } else { + tftpfile->tries = 0; } if (tftpfile->islastblock) break;