From d90890ed6e363834686d5c3307a6c8688278e2b7 Mon Sep 17 00:00:00 2001 From: ASOU Masato Date: Sat, 7 Jan 2023 06:40:22 +0000 Subject: The maximum length of the value is extended to 64k bytes. ok yasuoka --- share/man/man4/pvbus.4 | 11 +++++++++-- sys/dev/pv/hypervic.c | 7 ++++--- sys/dev/pv/pvbus.c | 11 ++++++----- sys/dev/pv/pvvar.h | 4 +++- sys/dev/pv/vmt.c | 4 ++-- sys/dev/pv/xenstore.c | 13 +++++++++---- usr.sbin/hostctl/hostctl.c | 24 +++++++++++++++++++----- 7 files changed, 52 insertions(+), 22 deletions(-) diff --git a/share/man/man4/pvbus.4 b/share/man/man4/pvbus.4 index 8d67809e9c0..33b6a22ea26 100644 --- a/share/man/man4/pvbus.4 +++ b/share/man/man4/pvbus.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pvbus.4,v 1.14 2017/06/14 12:42:09 jmc Exp $ +.\" $OpenBSD: pvbus.4,v 1.15 2023/01/07 06:40:21 asou Exp $ .\" .\" Copyright (c) 2015 Reyk Floeter .\" Copyright (c) 2006 Jason McIntyre @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: June 14 2017 $ +.Dd $Mdocdate: January 7 2023 $ .Dt PVBUS 4 .Os .Sh NAME @@ -125,6 +125,13 @@ Read the value from .Fa pvr_key and return it in .Fa pvr_value . +If +.Fa pvr_valuelen +is not enough for the value, +the command will fail and +.Xr errno 2 +is set to +.Er ERANGE . .It Dv PVBUSIOC_KVTYPE Return the type of the attached hypervisor interface as a string in .Fa pvr_key ; diff --git a/sys/dev/pv/hypervic.c b/sys/dev/pv/hypervic.c index 9c7f70dd96f..a7455d03e5b 100644 --- a/sys/dev/pv/hypervic.c +++ b/sys/dev/pv/hypervic.c @@ -1151,11 +1151,12 @@ hv_kvop(void *arg, int op, char *key, char *val, size_t vallen) kvpl = &kvp->kvp_pool[pool]; if (strlen(key) == 0) { for (next = 0; next < MAXPOOLENTS; next++) { - if ((val + vallen < vp + HV_KVP_MAX_KEY_SIZE / 2) || - kvp_pool_keys(kvpl, next, vp, &keylen)) + if (val + vallen < vp + HV_KVP_MAX_KEY_SIZE / 2) + return (ERANGE); + if (kvp_pool_keys(kvpl, next, vp, &keylen)) goto out; if (strlcat(val, "\n", vallen) >= vallen) - goto out; + return (ERANGE); vp += keylen; } out: diff --git a/sys/dev/pv/pvbus.c b/sys/dev/pv/pvbus.c index 5f7c4b57fe0..2f4cdd31849 100644 --- a/sys/dev/pv/pvbus.c +++ b/sys/dev/pv/pvbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pvbus.c,v 1.26 2022/12/08 05:45:36 yasuoka Exp $ */ +/* $OpenBSD: pvbus.c,v 1.27 2023/01/07 06:40:21 asou Exp $ */ /* * Copyright (c) 2015 Reyk Floeter @@ -399,13 +399,14 @@ pvbusgetstr(size_t srclen, const char *src, char **dstp) /* * Reject size that is too short or obviously too long: - * - at least one byte for the nul terminator. - * - PAGE_SIZE is an arbitrary value, but known pv backends seem - * to have a hard (PAGE_SIZE - x) limit in their messaging. + * - Known pv backends other than vmware have a hard limit smaller than + * PVBUS_KVOP_MAXSIZE in their messaging. vmware has a software + * limit at 1MB, but current open-vm-tools has a limit at 64KB + * (=PVBUS_KVOP_MAXSIZE). */ if (srclen < 1) return (EINVAL); - else if (srclen > PAGE_SIZE) + else if (srclen > PVBUS_KVOP_MAXSIZE) return (ENAMETOOLONG); *dstp = dst = malloc(srclen + 1, M_TEMP, M_WAITOK | M_ZERO); diff --git a/sys/dev/pv/pvvar.h b/sys/dev/pv/pvvar.h index 4e23ae52bd5..d2ba273a45a 100644 --- a/sys/dev/pv/pvvar.h +++ b/sys/dev/pv/pvvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pvvar.h,v 1.10 2017/06/22 06:21:12 jmatthew Exp $ */ +/* $OpenBSD: pvvar.h,v 1.11 2023/01/07 06:40:21 asou Exp $ */ /* * Copyright (c) 2015 Reyk Floeter @@ -30,6 +30,8 @@ struct pvbus_req { #define PVBUSIOC_KVWRITE _IOWR('V', 2, struct pvbus_req) #define PVBUSIOC_TYPE _IOWR('V', 3, struct pvbus_req) +#define PVBUS_KVOP_MAXSIZE (64 * 1024) + #ifdef _KERNEL enum { PVBUS_KVM, diff --git a/sys/dev/pv/vmt.c b/sys/dev/pv/vmt.c index c2c1cd3fa5c..569b8600b03 100644 --- a/sys/dev/pv/vmt.c +++ b/sys/dev/pv/vmt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmt.c,v 1.29 2022/12/28 10:11:36 asou Exp $ */ +/* $OpenBSD: vmt.c,v 1.30 2023/01/07 06:40:21 asou Exp $ */ /* * Copyright (c) 2007 David Crawshaw @@ -547,7 +547,7 @@ vmt_kvop(void *arg, int op, char *key, char *value, size_t valuelen) if (rlen > 0) { if (rlen + 1 > valuelen) { - error = EMSGSIZE; + error = ERANGE; goto close; } diff --git a/sys/dev/pv/xenstore.c b/sys/dev/pv/xenstore.c index 494eb40bfb0..1f4c2307bdd 100644 --- a/sys/dev/pv/xenstore.c +++ b/sys/dev/pv/xenstore.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xenstore.c,v 1.47 2022/11/10 02:47:52 asou Exp $ */ +/* $OpenBSD: xenstore.c,v 1.48 2023/01/07 06:40:21 asou Exp $ */ /* * Copyright (c) 2015 Mike Belopuhov @@ -1116,11 +1116,16 @@ xs_kvop(void *xsc, int op, char *key, char *value, size_t valuelen) /* FALLTHROUGH */ case XS_LIST: for (i = 0; i < iov_cnt; i++) { - if (i && strlcat(value, "\n", valuelen) >= valuelen) + if (i > 0 && strlcat(value, "\n", valuelen) >= + valuelen) { + error = ERANGE; break; + } if (strlcat(value, iovp[i].iov_base, - valuelen) >= valuelen) + valuelen) >= valuelen) { + error = ERANGE; break; + } } xs_resfree(&xst, iovp, iov_cnt); break; @@ -1128,5 +1133,5 @@ xs_kvop(void *xsc, int op, char *key, char *value, size_t valuelen) break; } - return (0); + return (error); } diff --git a/usr.sbin/hostctl/hostctl.c b/usr.sbin/hostctl/hostctl.c index f0639dd55f3..a6b6c72ea67 100644 --- a/usr.sbin/hostctl/hostctl.c +++ b/usr.sbin/hostctl/hostctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hostctl.c,v 1.5 2019/06/28 13:32:47 deraadt Exp $ */ +/* $OpenBSD: hostctl.c,v 1.6 2023/01/07 06:40:21 asou Exp $ */ /* * Copyright (c) 2016 Reyk Floeter @@ -178,15 +178,29 @@ main(int argc, char *argv[]) usage(); /* Re-open read-writable */ - if (cmd == PVBUSIOC_KVWRITE) { + if (cmd != PVBUSIOC_KVREAD) { close(fd); if ((fd = open(path_pvbus, O_RDWR)) == -1) err(1, "open: %s", path_pvbus); + if ((ret = ioctl(fd, cmd, &pvr, sizeof(pvr))) == -1) + err(1, "ioctl"); + } else { + while (1) { + if ((ret = ioctl(fd, cmd, &pvr, sizeof(pvr))) == 0) + break; + if (errno == ERANGE && + pvr.pvr_valuelen < PVBUS_KVOP_MAXSIZE) { + /* the buffer is not enough, expand it */ + pvr.pvr_valuelen *= 2; + if ((pvr.pvr_value = realloc(pvr.pvr_value, + pvr.pvr_valuelen)) == NULL) + err(1, "realloc"); + continue; + } + err(1, "ioctl"); + } } - if ((ret = ioctl(fd, cmd, &pvr, sizeof(pvr))) == -1) - err(1, "ioctl"); - if (!qflag && strlen(pvr.pvr_value)) { /* * The value can contain newlines and basically anything; -- cgit v1.2.3