Mercurial > illumos > git > illumos-omnios
changeset 23873:22572d9a12ab
13345 loader: xdr_array is missing count
Reviewed by: Andy Fiddaman <andy@omnios.org>
Approved by: Robert Mustacchi <rm@fingolfin.org>
author | Toomas Soome <tsoome@me.com> |
---|---|
date | Fri, 04 Dec 2020 00:03:18 +0200 |
parents | bbce4fbe98af |
children | e0d07b298524 |
files | usr/src/boot/Makefile.version usr/src/boot/lib/libstand/zfs/nvlist.c |
diffstat | 2 files changed, 187 insertions(+), 64 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/boot/Makefile.version Mon Nov 30 00:15:45 2020 +0000 +++ b/usr/src/boot/Makefile.version Fri Dec 04 00:03:18 2020 +0200 @@ -34,4 +34,4 @@ # Use date like formatting here, YYYY.MM.DD.XX, without leading zeroes. # The version is processed from left to right, the version number can only # be increased. -BOOT_VERSION = $(LOADER_VERSION)-2020.12.04.1 +BOOT_VERSION = $(LOADER_VERSION)-2020.12.04.2
--- a/usr/src/boot/lib/libstand/zfs/nvlist.c Mon Nov 30 00:15:45 2020 +0000 +++ b/usr/src/boot/lib/libstand/zfs/nvlist.c Fri Dec 04 00:03:18 2020 +0200 @@ -90,6 +90,38 @@ return (sizeof (int)); } +static int +_getint_mem(struct xdr *xdr, int *ip) +{ + *ip = *(int *)xdr->xdr_idx; + return (sizeof (int)); +} + +static int +_putint_mem(struct xdr *xdr, int i) +{ + int *ip = (int *)xdr->xdr_idx; + + *ip = i; + return (sizeof (int)); +} + +static int +_getuint_mem(struct xdr *xdr, unsigned *ip) +{ + *ip = *(unsigned *)xdr->xdr_idx; + return (sizeof (unsigned)); +} + +static int +_putuint_mem(struct xdr *xdr, unsigned i) +{ + unsigned *up = (unsigned *)xdr->xdr_idx; + + *up = i; + return (sizeof (int)); +} + /* * XDR data translations. */ @@ -182,8 +214,6 @@ static bool xdr_int64(xdr_t *xdr, int64_t *lp) { - int hi; - unsigned lo; bool rv = false; if (xdr->xdr_idx + sizeof (int64_t) > xdr->xdr_buf + xdr->xdr_buf_size) @@ -192,18 +222,21 @@ switch (xdr->xdr_op) { case XDR_OP_ENCODE: /* Encode value *lp, store to buf */ - hi = *lp >> 32; - lo = *lp & UINT32_MAX; - xdr->xdr_idx += xdr->xdr_putint(xdr, hi); - xdr->xdr_idx += xdr->xdr_putint(xdr, lo); + if (xdr->xdr_putint == _putint) + *(int64_t *)xdr->xdr_idx = htobe64(*lp); + else + *(int64_t *)xdr->xdr_idx = *lp; + xdr->xdr_idx += sizeof (int64_t); rv = true; break; case XDR_OP_DECODE: /* Decode buf, return value to *ip */ - xdr->xdr_idx += xdr->xdr_getint(xdr, &hi); - xdr->xdr_idx += xdr->xdr_getuint(xdr, &lo); - *lp = (((int64_t)hi) << 32) | lo; + if (xdr->xdr_getint == _getint) + *lp = be64toh(*(int64_t *)xdr->xdr_idx); + else + *lp = *(int64_t *)xdr->xdr_idx; + xdr->xdr_idx += sizeof (int64_t); rv = true; } return (rv); @@ -212,7 +245,6 @@ static bool xdr_uint64(xdr_t *xdr, uint64_t *lp) { - unsigned hi, lo; bool rv = false; if (xdr->xdr_idx + sizeof (uint64_t) > xdr->xdr_buf + xdr->xdr_buf_size) @@ -221,18 +253,21 @@ switch (xdr->xdr_op) { case XDR_OP_ENCODE: /* Encode value *ip, store to buf */ - hi = *lp >> 32; - lo = *lp & UINT32_MAX; - xdr->xdr_idx += xdr->xdr_putint(xdr, hi); - xdr->xdr_idx += xdr->xdr_putint(xdr, lo); + if (xdr->xdr_putint == _putint) + *(uint64_t *)xdr->xdr_idx = htobe64(*lp); + else + *(uint64_t *)xdr->xdr_idx = *lp; + xdr->xdr_idx += sizeof (uint64_t); rv = true; break; case XDR_OP_DECODE: /* Decode buf, return value to *ip */ - xdr->xdr_idx += xdr->xdr_getuint(xdr, &hi); - xdr->xdr_idx += xdr->xdr_getuint(xdr, &lo); - *lp = (((uint64_t)hi) << 32) | lo; + if (xdr->xdr_getuint == _getuint) + *lp = be64toh(*(uint64_t *)xdr->xdr_idx); + else + *lp = *(uint64_t *)xdr->xdr_idx; + xdr->xdr_idx += sizeof (uint64_t); rv = true; } return (rv); @@ -288,6 +323,10 @@ xdr_array(xdr_t *xdr, const unsigned nelem, const xdrproc_t elproc) { bool rv = true; + unsigned c = nelem; + + if (!xdr_u_int(xdr, &c)) + return (false); for (unsigned i = 0; i < nelem; i++) { if (!elproc(xdr, xdr->xdr_idx)) @@ -1119,15 +1158,19 @@ uint8_t *ptr; size_t namelen; int decoded_size, encoded_size; - xdr_t xdr; + xdr_t xdr = { + .xdr_op = XDR_OP_ENCODE, + .xdr_putint = _putint_mem, + .xdr_putuint = _putuint_mem, + .xdr_buf = nvl->nv_data, + .xdr_idx = nvl->nv_data, + .xdr_buf_size = nvl->nv_size + }; nvs = (nvs_data_t *)nvl->nv_data; if (nvs->nvl_nvflag & NV_UNIQUE_NAME) (void) nvlist_remove(nvl, name, type); - xdr.xdr_buf = nvl->nv_data; - xdr.xdr_idx = nvl->nv_data; - xdr.xdr_buf_size = nvl->nv_size; if (!nvlist_size_native(&xdr, &nvl->nv_size)) return (EINVAL); @@ -1164,63 +1207,109 @@ hp = (nvp_header_t *)nvl->nv_idx; *hp = head; nvl->nv_idx += sizeof (*hp); - *(unsigned *)nvl->nv_idx = namelen; - nvl->nv_idx += sizeof (unsigned); - strlcpy((char *)nvl->nv_idx, name, namelen + 1); - nvl->nv_idx += NV_ALIGN4(namelen); - *(unsigned *)nvl->nv_idx = type; - nvl->nv_idx += sizeof (unsigned); - *(unsigned *)nvl->nv_idx = nelem; - nvl->nv_idx += sizeof (unsigned); + + xdr.xdr_buf = nvl->nv_data; + xdr.xdr_idx = nvl->nv_idx; + + xdr.xdr_idx += xdr.xdr_putuint(&xdr, namelen); + strlcpy((char *)xdr.xdr_idx, name, namelen + 1); + xdr.xdr_idx += NV_ALIGN4(namelen); + xdr.xdr_idx += xdr.xdr_putuint(&xdr, type); + xdr.xdr_idx += xdr.xdr_putuint(&xdr, nelem); switch (type) { case DATA_TYPE_BOOLEAN: break; + case DATA_TYPE_BYTE_ARRAY: *(unsigned *)nvl->nv_idx = encoded_size; nvl->nv_idx += sizeof (unsigned); bcopy(data, nvl->nv_idx, nelem); nvl->nv_idx += encoded_size; break; + case DATA_TYPE_STRING: encoded_size = strlen(data); - *(unsigned *)nvl->nv_idx = encoded_size; - nvl->nv_idx += sizeof (unsigned); - strlcpy((char *)nvl->nv_idx, data, encoded_size + 1); - nvl->nv_idx += NV_ALIGN4(encoded_size); + xdr.xdr_idx += xdr.xdr_putuint(&xdr, encoded_size); + strlcpy((char *)xdr.xdr_idx, data, encoded_size + 1); + xdr.xdr_idx += NV_ALIGN4(encoded_size); break; + case DATA_TYPE_STRING_ARRAY: for (uint32_t i = 0; i < nelem; i++) { encoded_size = strlen(((char **)data)[i]); - *(unsigned *)nvl->nv_idx = encoded_size; - nvl->nv_idx += sizeof (unsigned); - strlcpy((char *)nvl->nv_idx, ((char **)data)[i], + xdr.xdr_idx += xdr.xdr_putuint(&xdr, encoded_size); + strlcpy((char *)xdr.xdr_idx, ((char **)data)[i], encoded_size + 1); - nvl->nv_idx += NV_ALIGN4(encoded_size); + xdr.xdr_idx += NV_ALIGN4(encoded_size); } break; + case DATA_TYPE_BYTE: case DATA_TYPE_INT8: case DATA_TYPE_UINT8: + xdr_char(&xdr, (char *)data); + break; + case DATA_TYPE_INT8_ARRAY: case DATA_TYPE_UINT8_ARRAY: - for (uint32_t i = 0; i < nelem; i++) { - *(unsigned *)nvl->nv_idx = ((uint8_t *)data)[i]; - nvl->nv_idx += sizeof (unsigned); - } + xdr_array(&xdr, nelem, (xdrproc_t)xdr_char); + break; + + case DATA_TYPE_INT16: + xdr_short(&xdr, (short *)data); break; - case DATA_TYPE_INT16: + case DATA_TYPE_UINT16: + xdr_u_short(&xdr, (unsigned short *)data); + break; + case DATA_TYPE_INT16_ARRAY: + xdr_array(&xdr, nelem, (xdrproc_t)xdr_short); + break; + case DATA_TYPE_UINT16_ARRAY: - for (uint32_t i = 0; i < nelem; i++) { - *(unsigned *)nvl->nv_idx = ((uint16_t *)data)[i]; - nvl->nv_idx += sizeof (unsigned); - } + xdr_array(&xdr, nelem, (xdrproc_t)xdr_u_short); + break; + + case DATA_TYPE_BOOLEAN_VALUE: + case DATA_TYPE_INT32: + xdr_int(&xdr, (int *)data); + break; + + case DATA_TYPE_UINT32: + xdr_u_int(&xdr, (unsigned int *)data); + break; + + case DATA_TYPE_BOOLEAN_ARRAY: + case DATA_TYPE_INT32_ARRAY: + xdr_array(&xdr, nelem, (xdrproc_t)xdr_int); + break; + + case DATA_TYPE_UINT32_ARRAY: + xdr_array(&xdr, nelem, (xdrproc_t)xdr_u_int); break; + + case DATA_TYPE_INT64: + xdr_int64(&xdr, (int64_t *)data); + break; + + case DATA_TYPE_UINT64: + xdr_uint64(&xdr, (uint64_t *)data); + break; + + case DATA_TYPE_INT64_ARRAY: + xdr_array(&xdr, nelem, (xdrproc_t)xdr_int64); + break; + + case DATA_TYPE_UINT64_ARRAY: + xdr_array(&xdr, nelem, (xdrproc_t)xdr_uint64); + break; + case DATA_TYPE_NVLIST: - bcopy(((nvlist_t *)data)->nv_data, nvl->nv_idx, encoded_size); + bcopy(((nvlist_t *)data)->nv_data, xdr.xdr_idx, encoded_size); break; + case DATA_TYPE_NVLIST_ARRAY: { uint8_t *buf = nvl->nv_idx; size_t size; @@ -1239,8 +1328,9 @@ } break; } + default: - bcopy(data, nvl->nv_idx, encoded_size); + bcopy(data, xdr.xdr_idx, encoded_size); } nvl->nv_size += head.encoded_size; @@ -1464,9 +1554,15 @@ nv_string_t *nvp_name; nv_pair_data_t *nvp_data; nvlist_t nvlist; - xdr_t xdr; - unsigned i, j, u; - uint64_t u64; + unsigned i, j; + xdr_t xdr = { + .xdr_op = XDR_OP_DECODE, + .xdr_getint = _getint_mem, + .xdr_getuint = _getuint_mem, + .xdr_buf = (const uint8_t *)nvp, + .xdr_idx = NULL, + .xdr_buf_size = nvp->encoded_size + }; nvp_name = (nv_string_t *)((uintptr_t)nvp + sizeof (*nvp)); nvp_data = (nv_pair_data_t *) @@ -1478,32 +1574,59 @@ printf("%s [%d] %.*s", typenames[nvp_data->nv_type], nvp_data->nv_nelem, nvp_name->nv_size, nvp_name->nv_data); + xdr.xdr_idx = nvp_data->nv_data; switch (nvp_data->nv_type) { case DATA_TYPE_BYTE: case DATA_TYPE_INT8: - case DATA_TYPE_UINT8: - bcopy(nvp_data->nv_data, &u, sizeof (u)); - printf(" = 0x%x\n", (unsigned char)u); + case DATA_TYPE_UINT8: { + char c; + + if (xdr_char(&xdr, &c)) + printf(" = 0x%x\n", c); break; + } case DATA_TYPE_INT16: - case DATA_TYPE_UINT16: - bcopy(nvp_data->nv_data, &u, sizeof (u)); - printf(" = 0x%hx\n", (unsigned short)u); + case DATA_TYPE_UINT16: { + unsigned short u; + + if (xdr_u_short(&xdr, &u)) + printf(" = 0x%hx\n", u); break; + } case DATA_TYPE_BOOLEAN_VALUE: case DATA_TYPE_INT32: - case DATA_TYPE_UINT32: - bcopy(nvp_data->nv_data, &u, sizeof (u)); - printf(" = 0x%x\n", u); + case DATA_TYPE_UINT32: { + unsigned u; + + if (xdr_u_int(&xdr, &u)) + printf(" = 0x%x\n", u); break; + } case DATA_TYPE_INT64: - case DATA_TYPE_UINT64: - bcopy(nvp_data->nv_data, &u64, sizeof (u64)); - printf(" = 0x%jx\n", (uintmax_t)u64); + case DATA_TYPE_UINT64: { + uint64_t u; + + if (xdr_uint64(&xdr, &u)) + printf(" = 0x%jx\n", (uintmax_t)u); break; + } + + case DATA_TYPE_INT64_ARRAY: + case DATA_TYPE_UINT64_ARRAY: { + uint64_t *u; + if (xdr_array(&xdr, nvp_data->nv_nelem, + (xdrproc_t)xdr_uint64)) { + u = (uint64_t *)(nvp_data->nv_data + sizeof (unsigned)); + for (i = 0; i < nvp_data->nv_nelem; i++) + printf(" [%u] = 0x%jx", i, (uintmax_t)u[i]); + printf("\n"); + } + + break; + } case DATA_TYPE_STRING: case DATA_TYPE_STRING_ARRAY: