Hi,
The current VALUE length limit for the hostctl command for VMware is
fixed 4096 bytes. I want to pass a longer VALUE. I made a patch to
change it to variable length.
commane, ok?
Index: share/man/man4/pvbus.4
===================================================================
RCS file: /cvs/src/share/man/man4/pvbus.4,v
retrieving revision 1.14
diff -u -p -r1.14 pvbus.4
--- share/man/man4/pvbus.4 14 Jun 2017 12:42:09 -0000 1.14
+++ share/man/man4/pvbus.4 5 Oct 2022 03:23:00 -0000
@@ -102,13 +102,15 @@ struct pvbus_req {
char *pvr_key;
size_t pvr_valuelen;
char *pvr_value;
+ size_t *pvr_len;
};
.Ed
.Pp
The caller is responsible for attaching character buffers to the
-.Fa pvr_key
-and
+.Fa pvr_key ,
.Fa pvr_value
+and
+.Fa pvr_len
fields and to set their length in
.Fa pvr_keylen
and
@@ -136,6 +138,14 @@ Write the new value
to the key
.Fa pvr_key .
This command requires write permissions on the device file.
+.It Dv PVBUSIOC_GETVALUELEN
+Get the length of the value of
+.Fa pvr_key
+and return it in
+.Fa pvr_len .
+.It Dv PVBUSIOC_GETTYPELEN
+Get the length of the type and return it in
+.Fa pvr_len .
.El
.Sh FILES
.Bl -tag -width "/dev/pvbusX" -compact
Index: sys/dev/pv/hypervic.c
===================================================================
RCS file: /cvs/src/sys/dev/pv/hypervic.c,v
retrieving revision 1.17
diff -u -p -r1.17 hypervic.c
--- sys/dev/pv/hypervic.c 8 Sep 2022 10:22:06 -0000 1.17
+++ sys/dev/pv/hypervic.c 5 Oct 2022 03:23:01 -0000
@@ -105,7 +105,7 @@ int hv_heartbeat_attach(struct hv_ic_dev
void hv_heartbeat(void *);
int hv_kvp_attach(struct hv_ic_dev *);
void hv_kvp(void *);
-int hv_kvop(void *, int, char *, char *, size_t);
+int hv_kvop(void *, int, char *, size_t, char *, size_t, size_t *);
int hv_shutdown_attach(struct hv_ic_dev *);
void hv_shutdown(void *);
int hv_timesync_attach(struct hv_ic_dev *);
@@ -551,11 +551,10 @@ kvp_pool_init(struct kvp_pool *kvpl)
}
static int
-kvp_pool_insert(struct kvp_pool *kvpl, const char *key, const char *val,
- uint32_t vallen, uint32_t valtype)
+kvp_pool_insert(struct kvp_pool *kvpl, const char *key, size_t keylen,
+ const char *val, size_t vallen, uint32_t valtype)
{
struct kvp_entry *kpe;
- int keylen = strlen(key);
if (keylen > HV_KVP_MAX_KEY_SIZE / 2)
return (ERANGE);
@@ -592,11 +591,10 @@ kvp_pool_insert(struct kvp_pool *kvpl, c
}
static int
-kvp_pool_update(struct kvp_pool *kvpl, const char *key, const char *val,
- uint32_t vallen, uint32_t valtype)
+kvp_pool_update(struct kvp_pool *kvpl, const char *key, size_t keylen,
+ const char *val, size_t vallen, uint32_t valtype)
{
struct kvp_entry *kpe;
- int keylen = strlen(key);
if (keylen > HV_KVP_MAX_KEY_SIZE / 2)
return (ERANGE);
@@ -715,12 +713,13 @@ kvp_pool_remove(struct kvp_pool *kvpl, c
}
static int
-kvp_pool_extract(struct kvp_pool *kvpl, const char *key, char *val,
- uint32_t vallen)
+kvp_pool_extract(struct kvp_pool *kvpl, int op, const char *key, char *val,
+ size_t vallen, size_t *vlen)
{
struct kvp_entry *kpe;
+ char buf[128];
- if (vallen < HV_KVP_MAX_VAL_SIZE / 2)
+ if (vallen > SIZE_T_MAX)
return (ERANGE);
mtx_enter(&kvpl->kvp_lock);
@@ -734,18 +733,36 @@ kvp_pool_extract(struct kvp_pool *kvpl,
return (ENOENT);
}
- switch (kpe->kpe_valtype) {
- case HV_KVP_REG_SZ:
- strlcpy(val, kpe->kpe_val, HV_KVP_MAX_VAL_SIZE / 2);
- break;
- case HV_KVP_REG_U32:
- snprintf(val, HV_KVP_MAX_VAL_SIZE / 2, "%u",
- *(uint32_t *)kpe->kpe_val);
- break;
- case HV_KVP_REG_U64:
- snprintf(val, HV_KVP_MAX_VAL_SIZE / 2, "%llu",
- *(uint64_t *)kpe->kpe_val);
- break;
+ if (op == PVBUS_KVGETVALLEN) {
+ switch (kpe->kpe_valtype) {
+ case HV_KVP_REG_SZ:
+ *vlen = strlen(kpe->kpe_val);
+ break;
+ case HV_KVP_REG_U32:
+ snprintf(buf, HV_KVP_MAX_VAL_SIZE / 2, "%u",
+ *(uint32_t *)kpe->kpe_val);
+ *vlen = strlen(buf);
+ break;
+ case HV_KVP_REG_U64:
+ snprintf(buf, HV_KVP_MAX_VAL_SIZE / 2, "%llu",
+ *(uint64_t *)kpe->kpe_val);
+ *vlen = strlen(buf);
+ break;
+ }
+ } else {
+ switch (kpe->kpe_valtype) {
+ case HV_KVP_REG_SZ:
+ strlcpy(val, kpe->kpe_val, HV_KVP_MAX_VAL_SIZE / 2);
+ break;
+ case HV_KVP_REG_U32:
+ snprintf(val, HV_KVP_MAX_VAL_SIZE / 2, "%u",
+ *(uint32_t *)kpe->kpe_val);
+ break;
+ case HV_KVP_REG_U64:
+ snprintf(val, HV_KVP_MAX_VAL_SIZE / 2, "%llu",
+ *(uint64_t *)kpe->kpe_val);
+ break;
+ }
}
mtx_leave(&kvpl->kvp_lock);
@@ -777,6 +794,29 @@ kvp_pool_keys(struct kvp_pool *kvpl, int
return (-1);
}
+static int
+kvp_pool_keylen(struct kvp_pool *kvpl, int next, size_t *keylen)
+{
+ struct kvp_entry *kpe;
+ int iter = 0;
+
+ mtx_enter(&kvpl->kvp_lock);
+
+ TAILQ_FOREACH(kpe, &kvpl->kvp_entries, kpe_entry) {
+ if (iter++ < next)
+ continue;
+ *keylen = strlen(kpe->kpe_key);
+
+ mtx_leave(&kvpl->kvp_lock);
+
+ return (0);
+ }
+
+ mtx_leave(&kvpl->kvp_lock);
+
+ return (-1);
+}
+
int
hv_kvp_attach(struct hv_ic_dev *dv)
{
@@ -812,8 +852,9 @@ hv_kvp_attach(struct hv_ic_dev *dv)
/* Initialize 'Auto' pool */
for (i = 0; i < nitems(kvp_pool_auto); i++) {
if (kvp_pool_insert(&kvp->kvp_pool[HV_KVP_POOL_AUTO],
- kvp_pool_auto[i].keyname, kvp_pool_auto[i].value,
- strlen(kvp_pool_auto[i].value), HV_KVP_REG_SZ))
+ kvp_pool_auto[i].keyname, strlen(kvp_pool_auto[i].keyname),
+ kvp_pool_auto[i].value, strlen(kvp_pool_auto[i].value),
+ HV_KVP_REG_SZ))
DPRINTF("%s: failed to insert into 'Auto' pool\n",
sc->sc_dev.dv_xname);
}
@@ -1135,14 +1176,15 @@ kvp_poolname(char **key)
}
int
-hv_kvop(void *arg, int op, char *key, char *val, size_t vallen)
+hv_kvop(void *arg, int op, char *key, size_t klen, char *val, size_t vallen,
+ size_t *vlen)
{
struct hv_ic_dev *dv = arg;
struct hv_kvp *kvp = dv->dv_priv;
struct kvp_pool *kvpl;
int next, pool, error = 0;
char *vp = val;
- size_t keylen;
+ size_t keylen = 0;
pool = kvp_poolname(&key);
if (pool == -1)
@@ -1150,31 +1192,43 @@ hv_kvop(void *arg, int op, char *key, ch
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))
- goto out;
- if (strlcat(val, "\n", vallen) >= vallen)
- goto out;
- vp += keylen;
+ if (op == PVBUS_KVGETVALLEN) {
+ *vlen = 0;
+ for (next = 0; next < MAXPOOLENTS; next++) {
+ if (kvp_pool_keylen(kvpl, next, &keylen))
+ break;
+ /* `+ 1' means '\n' the end of the line */
+ *vlen += keylen + 1;
+ }
+ /* `+ 1' means '\0' the end of the line */
+ *vlen += 1;
+ } else {
+ for (next = 0; next < MAXPOOLENTS; next++) {
+ if ((val + vallen < vp) ||
+ kvp_pool_keys(kvpl, next, vp, &keylen))
+ break;
+ if (strlcat(val, "\n", vallen) >= vallen)
+ break;
+ vp += keylen;
+ }
+ if (vp > val)
+ *(vp - 1) = '\0';
}
- out:
- if (vp > val)
- *(vp - 1) = '\0';
return (0);
}
if (op == PVBUS_KVWRITE) {
+ keylen = strlen(key);
if (pool == HV_KVP_POOL_AUTO)
- error = kvp_pool_update(kvpl, key, val, vallen,
+ error = kvp_pool_update(kvpl, key, keylen, val, vallen,
HV_KVP_REG_SZ);
else if (pool == HV_KVP_POOL_GUEST)
- error = kvp_pool_insert(kvpl, key, val, vallen,
+ error = kvp_pool_insert(kvpl, key, keylen, val, vallen,
HV_KVP_REG_SZ);
else
error = EINVAL;
} else
- error = kvp_pool_extract(kvpl, key, val, vallen);
+ error = kvp_pool_extract(kvpl, op, key, val, vallen, vlen);
return (error);
}
Index: sys/dev/pv/pvbus.c
===================================================================
RCS file: /cvs/src/sys/dev/pv/pvbus.c,v
retrieving revision 1.25
diff -u -p -r1.25 pvbus.c
--- sys/dev/pv/pvbus.c 25 Aug 2022 17:38:16 -0000 1.25
+++ sys/dev/pv/pvbus.c 5 Oct 2022 03:23:01 -0000
@@ -400,12 +400,10 @@ pvbusgetstr(size_t srclen, const char *s
/*
* 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.
*/
if (srclen < 1)
return (EINVAL);
- else if (srclen > PAGE_SIZE)
+ else if (srclen > SIZE_T_MAX)
return (ENAMETOOLONG);
*dstp = dst = malloc(srclen + 1, M_TEMP|M_ZERO, M_WAITOK);
@@ -437,6 +435,9 @@ pvbusioctl(dev_t dev, u_long cmd, caddr_
case PVBUSIOC_KVWRITE:
if ((flags & FWRITE) == 0)
return (EPERM);
+ /* FALLTHROUGH */
+ case PVBUSIOC_GETVALUELEN:
+ /* FALLTHROUGH */
case PVBUSIOC_KVREAD:
hv = &sc->pvbus_hv[hvid];
if (hv->hv_base == 0 || hv->hv_kvop == NULL)
@@ -449,6 +450,12 @@ pvbusioctl(dev_t dev, u_long cmd, caddr_
return (ENOMEM);
error = copyout(str, pvr->pvr_key, sz);
return (error);
+
+ case PVBUSIOC_GETTYPELEN:
+ sz = strlen(pvbus_types[hvid].name);
+ error = copyout(&sz, pvr->pvr_len, sizeof (*pvr->pvr_len));
+ return (error);
+
default:
return (ENOTTY);
}
@@ -457,6 +464,18 @@ pvbusioctl(dev_t dev, u_long cmd, caddr_
op = PVBUS_KVREAD;
switch (cmd) {
+ case PVBUSIOC_GETVALUELEN:
+ op = PVBUS_KVGETVALLEN;
+ keylen = pvr->pvr_keylen;
+ if ((error = pvbusgetstr(keylen, pvr->pvr_key, &key)) != 0)
+ break;
+ if ((error = (hv->hv_kvop)(hv->hv_arg, op,
+ key, keylen, value, valuelen, &sz)) != 0)
+ break;
+ if ((error = copyout(&sz, pvr->pvr_len,
+ sizeof (*pvr->pvr_len))) != 0)
+ break;
+ break;
case PVBUSIOC_KVWRITE:
str = pvr->pvr_value;
op = PVBUS_KVWRITE;
@@ -473,7 +492,7 @@ pvbusioctl(dev_t dev, u_long cmd, caddr_
/* Call driver-specific callback */
if ((error = (hv->hv_kvop)(hv->hv_arg, op,
- key, value, valuelen)) != 0)
+ key, keylen, value, valuelen, NULL)) != 0)
break;
sz = strlen(value) + 1;
Index: sys/dev/pv/pvvar.h
===================================================================
RCS file: /cvs/src/sys/dev/pv/pvvar.h,v
retrieving revision 1.10
diff -u -p -r1.10 pvvar.h
--- sys/dev/pv/pvvar.h 22 Jun 2017 06:21:12 -0000 1.10
+++ sys/dev/pv/pvvar.h 5 Oct 2022 03:23:01 -0000
@@ -24,11 +24,14 @@ struct pvbus_req {
char *pvr_key;
size_t pvr_valuelen;
char *pvr_value;
+ size_t *pvr_len;
};
#define PVBUSIOC_KVREAD _IOWR('V', 1, struct pvbus_req)
#define PVBUSIOC_KVWRITE _IOWR('V', 2, struct pvbus_req)
#define PVBUSIOC_TYPE _IOWR('V', 3, struct pvbus_req)
+#define PVBUSIOC_GETVALUELEN _IOWR('V', 4, struct pvbus_req)
+#define PVBUSIOC_GETTYPELEN _IOWR('V', 5, struct pvbus_req)
#ifdef _KERNEL
enum {
@@ -45,7 +48,9 @@ enum {
enum {
PVBUS_KVREAD,
PVBUS_KVWRITE,
- PVBUS_KVLS
+ PVBUS_KVLS,
+ PVBUS_KVGETVALLEN,
+ PVBUS_KVLSGETVALLEN
};
struct pvbus_hv {
@@ -55,7 +60,8 @@ struct pvbus_hv {
uint16_t hv_minor;
void *hv_arg;
- int (*hv_kvop)(void *, int, char *, char *, size_t);
+ int (*hv_kvop)(void *, int, char *, size_t, char *,
+ size_t, size_t *);
void (*hv_init_cpu)(struct pvbus_hv *);
};
Index: sys/dev/pv/vmt.c
===================================================================
RCS file: /cvs/src/sys/dev/pv/vmt.c,v
retrieving revision 1.26
diff -u -p -r1.26 vmt.c
--- sys/dev/pv/vmt.c 8 Sep 2022 10:22:06 -0000 1.26
+++ sys/dev/pv/vmt.c 5 Oct 2022 03:23:01 -0000
@@ -241,6 +241,8 @@ struct vmt_softc {
struct vm_rpc sc_tclo_rpc;
char *sc_rpc_buf;
+ size_t sc_rpc_buflen;
+ size_t sc_rpc_rxlen;
int sc_rpc_error;
int sc_tclo_ping;
int sc_set_guest_os;
@@ -277,12 +279,13 @@ int vm_rpc_send(const struct vm_rpc *,
int vm_rpc_send_str(const struct vm_rpc *, const uint8_t *);
int vm_rpc_get_length(const struct vm_rpc *, uint32_t *, uint16_t *);
int vm_rpc_get_data(const struct vm_rpc *, char *, uint32_t, uint16_t);
-int vm_rpc_send_rpci_tx_buf(struct vmt_softc *, const uint8_t *, uint32_t);
+int vm_rpc_send_rpci_tx_buf(struct vmt_softc *, char *, uint32_t);
int vm_rpc_send_rpci_tx(struct vmt_softc *, const char *, ...)
__attribute__((__format__(__kprintf__,2,3)));
-int vm_rpci_response_successful(struct vmt_softc *);
+int vm_rpci_response_successful(const char *);
+int vm_rpc_buf_realloc(struct vmt_softc *, size_t);
-int vmt_kvop(void *, int, char *, char *, size_t);
+int vmt_kvop(void *, int, char *, size_t, char *, size_t, size_t *);
void vmt_probe_cmd(struct vm_backdoor *, uint16_t);
void vmt_tclo_state_change_success(struct vmt_softc *, int, char);
@@ -440,7 +443,8 @@ vmt_attach(struct device *parent, struct
struct pvbus_hv *hv = &pva->pva_hv[PVBUS_VMWARE];
printf("\n");
- sc->sc_rpc_buf = malloc(VMT_RPC_BUFLEN, M_DEVBUF, M_NOWAIT);
+ sc->sc_rpc_buflen = VMT_RPC_BUFLEN;
+ sc->sc_rpc_buf = malloc(sc->sc_rpc_buflen, M_DEVBUF, M_NOWAIT);
if (sc->sc_rpc_buf == NULL) {
printf("%s: unable to allocate buffer for RPC\n",
DEVNAME(sc));
@@ -484,32 +488,40 @@ vmt_attach(struct device *parent, struct
return;
free:
- free(sc->sc_rpc_buf, M_DEVBUF, VMT_RPC_BUFLEN);
+ free(sc->sc_rpc_buf, M_DEVBUF, sc->sc_rpc_buflen);
}
int
-vmt_kvop(void *arg, int op, char *key, char *value, size_t valuelen)
+vmt_kvop(void *arg, int op, char *key, size_t keylen, char *value,
+ size_t valuelen, size_t *vlen)
{
struct vmt_softc *sc = arg;
- char *buf = NULL, *ptr;
- size_t bufsz;
+ char *ptr;
+ size_t bufsz, buflen;
int error = 0;
+ const char *set_cmd = "info-set %s %s";
+ const char *get_cmd = "info-get %s";
- bufsz = VMT_RPC_BUFLEN;
- buf = malloc(bufsz, M_TEMP, M_WAITOK | M_ZERO);
+ bufsz = MAX(strlen(set_cmd), strlen(get_cmd)) + keylen + valuelen;
+ if (bufsz > sc->sc_rpc_buflen &&
+ (error = vm_rpc_buf_realloc(sc, bufsz)) != 0)
+ return error;
switch (op) {
case PVBUS_KVWRITE:
- if ((size_t)snprintf(buf, bufsz, "info-set %s %s",
- key, value) >= bufsz) {
+ buflen = (size_t)snprintf(sc->sc_rpc_buf, bufsz, set_cmd, key,
+ value);
+ if (buflen >= bufsz) {
DPRINTF("%s: write command too long", DEVNAME(sc));
error = EINVAL;
goto done;
}
break;
+ case PVBUS_KVGETVALLEN:
+ /* FALLTHROUGH */
case PVBUS_KVREAD:
- if ((size_t)snprintf(buf, bufsz, "info-get %s",
- key) >= bufsz) {
+ buflen = (size_t)snprintf(sc->sc_rpc_buf, bufsz, get_cmd, key);
+ if (buflen >= bufsz) {
DPRINTF("%s: read command too long", DEVNAME(sc));
error = EINVAL;
goto done;
@@ -520,15 +532,15 @@ vmt_kvop(void *arg, int op, char *key, c
goto done;
}
- if (vm_rpc_send_rpci_tx(sc, "%s", buf) != 0) {
- DPRINTF("%s: error sending command: %s\n", DEVNAME(sc), buf);
+ if (vm_rpc_send_rpci_tx_buf(sc, sc->sc_rpc_buf, buflen) != 0) {
+ DPRINTF("%s: error sending command: %s\n", DEVNAME(sc),
sc->sc_rpc_buf);
sc->sc_rpc_error = 1;
error = EIO;
goto done;
}
- if (vm_rpci_response_successful(sc) == 0) {
- DPRINTF("%s: host rejected command: %s\n", DEVNAME(sc), buf);
+ if (vm_rpci_response_successful(sc->sc_rpc_buf) == 0) {
+ DPRINTF("%s: host rejected command: %s\n", DEVNAME(sc),
sc->sc_rpc_buf);
error = EINVAL;
goto done;
}
@@ -536,12 +548,16 @@ vmt_kvop(void *arg, int op, char *key, c
/* skip response that was tested in vm_rpci_response_successful() */
ptr = sc->sc_rpc_buf + 2;
- /* might truncate, copy anyway but return error */
- if (strlcpy(value, ptr, valuelen) >= valuelen)
+ if (op == PVBUS_KVGETVALLEN)
+ /* decrement response that was tested in
+ * vm_rpci_response_successful().
+ */
+ *vlen = strlen(ptr);
+ /* might truncat, copy anyway but return error */
+ else if (strlcpy(value, ptr, valuelen) >= valuelen)
error = ENOMEM;
done:
- free(buf, M_TEMP, bufsz);
return (error);
}
@@ -826,7 +842,7 @@ vmt_tclo_capreg(struct vmt_softc *sc)
sc->sc_rpc_error = 1;
}
- if (vm_rpci_response_successful(sc) == 0) {
+ if (vm_rpci_response_successful(sc->sc_rpc_buf) == 0) {
DPRINTF("%s: host rejected unified loop setting\n",
DEVNAME(sc));
}
@@ -839,7 +855,7 @@ vmt_tclo_capreg(struct vmt_softc *sc)
sc->sc_rpc_error = 1;
}
- if (vm_rpci_response_successful(sc) == 0) {
+ if (vm_rpci_response_successful(sc->sc_rpc_buf) == 0) {
DPRINTF("%s: host rejected statechange capability\n",
DEVNAME(sc));
}
@@ -1644,14 +1660,28 @@ vm_rpc_get_length(const struct vm_rpc *r
}
int
-vm_rpci_response_successful(struct vmt_softc *sc)
+vm_rpci_response_successful(const char *buf)
{
- return (sc->sc_rpc_buf[0] == '1' && sc->sc_rpc_buf[1] == ' ');
+ return (buf[0] == '1' && buf[1] == ' ');
}
int
-vm_rpc_send_rpci_tx_buf(struct vmt_softc *sc, const uint8_t *buf,
- uint32_t length)
+vm_rpc_buf_realloc(struct vmt_softc *sc, size_t len)
+{
+ free(sc->sc_rpc_buf, M_DEVBUF, sc->sc_rpc_buflen);
+
+ sc->sc_rpc_buflen = len / VMT_RPC_BUFLEN * VMT_RPC_BUFLEN;
+ sc->sc_rpc_buflen += ((len % VMT_RPC_BUFLEN) <= 0) ? 0 : VMT_RPC_BUFLEN;
+ sc->sc_rpc_buf = malloc(sc->sc_rpc_buflen, M_DEVBUF, M_NOWAIT);
+ if (sc->sc_rpc_buf == NULL) {
+ printf("%s: unable to allocate buffer for RPC\n", DEVNAME(sc));
+ return ENOMEM;
+ }
+ return 0;
+}
+
+int
+vm_rpc_send_rpci_tx_buf(struct vmt_softc *sc, char *buf, uint32_t length)
{
struct vm_rpc rpci;
u_int32_t rlen;
@@ -1677,9 +1707,11 @@ vm_rpc_send_rpci_tx_buf(struct vmt_softc
}
if (rlen > 0) {
- if (rlen >= VMT_RPC_BUFLEN) {
- rlen = VMT_RPC_BUFLEN - 1;
- }
+ sc->sc_rpc_rxlen = rlen;
+ /* Add the amount of the NUL terminater */
+ if (rlen >= sc->sc_rpc_buflen &&
+ (result = vm_rpc_buf_realloc(sc, rlen + 1)) != 0)
+ goto out;
if (vm_rpc_get_data(&rpci, sc->sc_rpc_buf, rlen, ack) != 0) {
DPRINTF("%s: failed to get rpci response data\n",
@@ -1707,7 +1739,7 @@ vm_rpc_send_rpci_tx(struct vmt_softc *sc
len = vsnprintf(sc->sc_rpc_buf, VMT_RPC_BUFLEN, fmt, args);
va_end(args);
- if (len >= VMT_RPC_BUFLEN) {
+ if (len >= sc->sc_rpc_buflen) {
DPRINTF("%s: rpci command didn't fit in buffer\n", DEVNAME(sc));
return EIO;
}
Index: sys/dev/pv/xenstore.c
===================================================================
RCS file: /cvs/src/sys/dev/pv/xenstore.c,v
retrieving revision 1.46
diff -u -p -r1.46 xenstore.c
--- sys/dev/pv/xenstore.c 9 Jan 2022 05:42:58 -0000 1.46
+++ sys/dev/pv/xenstore.c 5 Oct 2022 03:23:01 -0000
@@ -1065,7 +1065,8 @@ xs_await_transition(void *xsc, const cha
}
int
-xs_kvop(void *xsc, int op, char *key, char *value, size_t valuelen)
+xs_kvop(void *xsc, int op, char *key, size_t keylen, char *value,
+ size_t valuelen, size_t *vlen)
{
struct xen_softc *sc = xsc;
struct xs_transaction xst;
@@ -1079,9 +1080,13 @@ xs_kvop(void *xsc, int op, char *key, ch
iov.iov_len = strlen(value);
iov_cnt = 1;
break;
+ case PVBUS_KVGETVALLEN:
+ /* FALLTHROUGH */
case PVBUS_KVREAD:
cmd = XS_READ;
break;
+ case PVBUS_KVLSGETVALLEN:
+ /* FALLTHROUGH */
case PVBUS_KVLS:
cmd = XS_LIST;
break;
@@ -1110,16 +1115,25 @@ xs_kvop(void *xsc, int op, char *key, ch
* returns an empty string (single nul byte),
* so try to get the directory list in this case.
*/
- return (xs_kvop(xsc, PVBUS_KVLS, key, value, valuelen));
+ return (xs_kvop(xsc, op == PVBUS_KVREAD ? PVBUS_KVLS :
+ PVBUS_KVLSGETVALLEN, key, keylen, value,
+ valuelen, vlen));
}
/* FALLTHROUGH */
case XS_LIST:
- for (i = 0; i < iov_cnt; i++) {
- if (i && strlcat(value, "\n", valuelen) >= valuelen)
- break;
- if (strlcat(value, iovp[i].iov_base,
- valuelen) >= valuelen)
- break;
+ if (op == PVBUS_KVGETVALLEN || op == PVBUS_KVLSGETVALLEN) {
+ *vlen = 0;
+ for (i = 0; i < iov_cnt; i++)
+ *vlen += iovp[i].iov_len;
+ } else {
+ for (i = 0; i < iov_cnt; i++) {
+ if (i && strlcat(value, "\n", valuelen) >=
+ valuelen)
+ break;
+ if (strlcat(value, iovp[i].iov_base,
+ valuelen) >= valuelen)
+ break;
+ }
}
xs_resfree(&xst, iovp, iov_cnt);
break;
Index: sys/dev/pv/xenvar.h
===================================================================
RCS file: /cvs/src/sys/dev/pv/xenvar.h,v
retrieving revision 1.51
diff -u -p -r1.51 xenvar.h
--- sys/dev/pv/xenvar.h 21 Jul 2017 20:00:47 -0000 1.51
+++ sys/dev/pv/xenvar.h 5 Oct 2022 03:23:01 -0000
@@ -193,7 +193,7 @@ int xs_getnum(void *, const char *, cons
int xs_setnum(void *, const char *, const char *, unsigned long long);
int xs_getprop(void *, const char *, const char *, char *, int);
int xs_setprop(void *, const char *, const char *, char *, int);
-int xs_kvop(void *, int, char *, char *, size_t);
+int xs_kvop(void *, int, char *, size_t, char *, size_t, size_t *);
#define XEN_STATE_UNKNOWN "0"
#define XEN_STATE_INITIALIZING "1"
Index: usr.sbin/hostctl/hostctl.c
===================================================================
RCS file: /cvs/src/usr.sbin/hostctl/hostctl.c,v
retrieving revision 1.5
diff -u -p -r1.5 hostctl.c
--- usr.sbin/hostctl/hostctl.c 28 Jun 2019 13:32:47 -0000 1.5
+++ usr.sbin/hostctl/hostctl.c 5 Oct 2022 03:23:01 -0000
@@ -37,8 +37,7 @@ int qflag = 0; /* quiet */
int tflag = 0; /* show type */
__dead void usage(void);
-int kvsetstr(char *, const char *, size_t);
-int kvsetfile(char *, const char *, size_t);
+int kvsetfile(char **, const char *, size_t *);
__dead void
usage(void)
@@ -50,44 +49,40 @@ usage(void)
}
int
-kvsetstr(char *dst, const char *src, size_t dstlen)
+kvsetfile(char **dst, const char *input, size_t *dstlen)
{
- size_t sz;
-
- /* Sanitize the string before sending it to the kernel and host */
- if ((sz = strnvis(dst, src, dstlen, VIS_SAFE | VIS_CSTYLE)) >= dstlen)
- return (-1);
-
- /* Remove trailing newline */
- dst[strcspn(dst, "\n")] = '\0';
-
- return (0);
-}
-
-int
-kvsetfile(char *dst, const char *input, size_t dstlen)
-{
- char *buf = NULL;
+ char buf[KVBUFSZ];
int ret = -1;
- FILE *fp;
+ FILE *fp, *mp;
+ size_t flen;
if (strcmp("-", input) == 0)
fp = stdin;
else if ((fp = fopen(input, "r")) == NULL)
return (-1);
+ if ((mp = open_memstream(dst, dstlen)) == NULL) {
+ fclose(fp);
+ return (-1);
+ }
- if ((buf = calloc(1, dstlen)) == NULL)
- goto done;
- if (fread(buf, 1, dstlen - 1, fp) == 0)
- goto done;
- if (kvsetstr(dst, buf, dstlen) == -1)
- goto done;
+ do {
+ if ((flen = fread(buf, 1, sizeof (buf), fp)) == 0)
+ goto done;
+ if (fwrite(buf, 1, flen, mp) == 0)
+ goto done;
+ } while (flen >= sizeof (buf));
ret = 0;
done:
- free(buf);
if (fp != stdin)
fclose(fp);
+ fclose(mp);
+
+ /* Remove '\n' at the end of line */
+ if ((*dst)[*dstlen - 1] == '\n') {
+ --(*dstlen);
+ (*dst)[*dstlen] = '\0';
+ }
return (ret);
}
@@ -101,6 +96,7 @@ main(int argc, char *argv[])
int ch;
unsigned long cmd = 0;
char *str;
+ size_t len;
while ((ch = getopt(argc, argv, "f:i:o:qt")) != -1) {
switch (ch) {
@@ -137,12 +133,17 @@ main(int argc, char *argv[])
}
memset(&pvr, 0, sizeof(pvr));
- pvr.pvr_keylen = pvr.pvr_valuelen = KVBUFSZ;
- if ((pvr.pvr_key = calloc(1, pvr.pvr_keylen)) == NULL ||
- (pvr.pvr_value = calloc(1, pvr.pvr_valuelen)) == NULL)
- err(1, "calloc");
if (tflag) {
+ pvr.pvr_len = &len;
+ if ((ret = ioctl(fd, PVBUSIOC_GETTYPELEN, &pvr, sizeof(pvr)))
+ == -1)
+ err(1, "ioctl");
+ /* Add the NUL amount of the terminator */
+ pvr.pvr_keylen = len + 1;
+ if ((pvr.pvr_key = calloc(1, pvr.pvr_keylen)) == NULL)
+ err(1, "calloc");
+
if (ioctl(fd, PVBUSIOC_TYPE, &pvr, sizeof(pvr)) == -1)
err(1, "ioctl");
@@ -159,18 +160,20 @@ main(int argc, char *argv[])
usage();
key = argv[0];
- if (kvsetstr(pvr.pvr_key, key, pvr.pvr_keylen) == -1)
- errx(1, "key too long");
+ if (stravis(&pvr.pvr_key, key, VIS_SAFE | VIS_CSTYLE) == -1)
+ err(1, "stravis");
+ pvr.pvr_keylen = strlen(pvr.pvr_key) + 1;
/* Validate command line options for reading or writing */
if (argc == 2 && in == NULL) {
cmd = PVBUSIOC_KVWRITE;
value = argv[1];
- if (kvsetstr(pvr.pvr_value, value, pvr.pvr_valuelen) == -1)
- errx(1, "value too long");
+ if (stravis(&pvr.pvr_value, value, VIS_SAFE | VIS_CSTYLE) == -1)
+ err(1, "stravis");
+ pvr.pvr_valuelen = strlen(value) + 1;
} else if (argc == 1 && in != NULL) {
cmd = PVBUSIOC_KVWRITE;
- if (kvsetfile(pvr.pvr_value, in, pvr.pvr_valuelen) == -1)
+ if (kvsetfile(&pvr.pvr_value, in, &pvr.pvr_valuelen) == -1)
errx(1, "input file");
} else if (argc == 1) {
cmd = cmd == 0 ? PVBUSIOC_KVREAD : cmd;
@@ -184,6 +187,18 @@ main(int argc, char *argv[])
err(1, "open: %s", path_pvbus);
}
+ /* Get the length of value of key */
+ if (cmd == PVBUSIOC_KVREAD) {
+ pvr.pvr_len = &len;
+ if ((ret = ioctl(fd, PVBUSIOC_GETVALUELEN, &pvr, sizeof(pvr)))
+ == -1)
+ err(1, "ioctl");
+ /* Add the NUL amount of the terminator */
+ pvr.pvr_valuelen = len + 1;
+ if ((pvr.pvr_value = calloc(1, pvr.pvr_valuelen)) == NULL)
+ err(1, "calloc");
+ }
+
if ((ret = ioctl(fd, cmd, &pvr, sizeof(pvr))) == -1)
err(1, "ioctl");
@@ -202,7 +217,8 @@ main(int argc, char *argv[])
done:
if (outfp != stdout)
fclose(outfp);
- free(pvr.pvr_value);
+ if (pvr.pvr_value != NULL)
+ free(pvr.pvr_value);
free(pvr.pvr_key);
close(fd);
--
ASOU Masato