svn commit: r349948 - in head/sys/amd64: include vmm
Scott Long
scottl at FreeBSD.org
Fri Jul 12 18:37:58 UTC 2019
Author: scottl
Date: Fri Jul 12 18:37:56 2019
New Revision: 349948
URL: https://svnweb.freebsd.org/changeset/base/349948
Log:
Tie the name limit of a VM to SPECNAMELEN from devfs instead of a
hard-coded value. Don't allocate space for it from the kernel stack.
Account for prefix, suffix, and separator space in the name. This
takes the effective length up to 229 bytes on 13-current, and 37 bytes
on 12-stable. 37 bytes is enough to hold a full GUID string.
PR: 234134
MFC after: 1 week
Differential Revision: http://reviews.freebsd.org/D20924
Modified:
head/sys/amd64/include/vmm.h
head/sys/amd64/include/vmm_dev.h
head/sys/amd64/vmm/vmm_dev.c
Modified: head/sys/amd64/include/vmm.h
==============================================================================
--- head/sys/amd64/include/vmm.h Fri Jul 12 18:33:58 2019 (r349947)
+++ head/sys/amd64/include/vmm.h Fri Jul 12 18:37:56 2019 (r349948)
@@ -114,9 +114,30 @@ enum x2apic_state {
#define VM_INTINFO_HWEXCEPTION (3 << 8)
#define VM_INTINFO_SWINTR (4 << 8)
-#ifdef _KERNEL
+/*
+ * The VM name has to fit into the pathname length constraints of devfs,
+ * governed primarily by SPECNAMELEN. The length is the total number of
+ * characters in the full path, relative to the mount point and not
+ * including any leading '/' characters.
+ * A prefix and a suffix are added to the name specified by the user.
+ * The prefix is usually "vmm/" or "vmm.io/", but can be a few characters
+ * longer for future use.
+ * The suffix is a string that identifies a bootrom image or some similar
+ * image that is attached to the VM. A separator character gets added to
+ * the suffix automatically when generating the full path, so it must be
+ * accounted for, reducing the effective length by 1.
+ * The effective length of a VM name is 229 bytes for FreeBSD 13 and 37
+ * bytes for FreeBSD 12. A minimum length is set for safety and supports
+ * a SPECNAMELEN as small as 32 on old systems.
+ */
+#define VM_MAX_PREFIXLEN 10
+#define VM_MAX_SUFFIXLEN 15
+#define VM_MIN_NAMELEN 6
+#define VM_MAX_NAMELEN \
+ (SPECNAMELEN - VM_MAX_PREFIXLEN - VM_MAX_SUFFIXLEN - 1)
-#define VM_MAX_NAMELEN 32
+#ifdef _KERNEL
+CTASSERT(VM_MAX_NAMELEN >= VM_MIN_NAMELEN);
struct vm;
struct vm_exception;
Modified: head/sys/amd64/include/vmm_dev.h
==============================================================================
--- head/sys/amd64/include/vmm_dev.h Fri Jul 12 18:33:58 2019 (r349947)
+++ head/sys/amd64/include/vmm_dev.h Fri Jul 12 18:37:56 2019 (r349948)
@@ -51,7 +51,7 @@ struct vm_memmap {
struct vm_memseg {
int segid;
size_t len;
- char name[SPECNAMELEN + 1];
+ char name[VM_MAX_SUFFIXLEN + 1];
};
struct vm_register {
Modified: head/sys/amd64/vmm/vmm_dev.c
==============================================================================
--- head/sys/amd64/vmm/vmm_dev.c Fri Jul 12 18:33:58 2019 (r349947)
+++ head/sys/amd64/vmm/vmm_dev.c Fri Jul 12 18:37:56 2019 (r349948)
@@ -245,7 +245,7 @@ vmmdev_rw(struct cdev *cdev, struct uio *uio, int flag
return (error);
}
-CTASSERT(sizeof(((struct vm_memseg *)0)->name) >= SPECNAMELEN + 1);
+CTASSERT(sizeof(((struct vm_memseg *)0)->name) >= VM_MAX_SUFFIXLEN + 1);
static int
get_memseg(struct vmmdev_softc *sc, struct vm_memseg *mseg)
@@ -265,7 +265,8 @@ get_memseg(struct vmmdev_softc *sc, struct vm_memseg *
}
KASSERT(dsc != NULL, ("%s: devmem segment %d not found",
__func__, mseg->segid));
- error = copystr(dsc->name, mseg->name, SPECNAMELEN + 1, NULL);
+ error = copystr(dsc->name, mseg->name, sizeof(mseg->name),
+ NULL);
} else {
bzero(mseg->name, sizeof(mseg->name));
}
@@ -284,10 +285,14 @@ alloc_memseg(struct vmmdev_softc *sc, struct vm_memseg
name = NULL;
sysmem = true;
+ /*
+ * The allocation is lengthened by 1 to hold a terminating NUL. It'll
+ * by stripped off when devfs processes the full string.
+ */
if (VM_MEMSEG_NAME(mseg)) {
sysmem = false;
- name = malloc(SPECNAMELEN + 1, M_VMMDEV, M_WAITOK);
- error = copystr(mseg->name, name, SPECNAMELEN + 1, 0);
+ name = malloc(sizeof(mseg->name) M_VMMDEV, M_WAITOK);
+ error = copystr(mseg->name, name, sizeof(mseg->name), NULL);
if (error)
goto done;
}
@@ -894,26 +899,29 @@ vmmdev_destroy(void *arg)
static int
sysctl_vmm_destroy(SYSCTL_HANDLER_ARGS)
{
- int error;
- char buf[VM_MAX_NAMELEN];
struct devmem_softc *dsc;
struct vmmdev_softc *sc;
struct cdev *cdev;
+ char *buf;
+ int error, buflen;
error = vmm_priv_check(req->td->td_ucred);
if (error)
return (error);
- strlcpy(buf, "beavis", sizeof(buf));
- error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
+ buflen = VM_MAX_NAMELEN + 1;
+ buf = malloc(buflen, M_VMMDEV, M_WAITOK | M_ZERO);
+ strlcpy(buf, "beavis", buflen);
+ error = sysctl_handle_string(oidp, buf, buflen, req);
if (error != 0 || req->newptr == NULL)
- return (error);
+ goto out;
mtx_lock(&vmmdev_mtx);
sc = vmmdev_lookup(buf);
if (sc == NULL || sc->cdev == NULL) {
mtx_unlock(&vmmdev_mtx);
- return (EINVAL);
+ error = EINVAL;
+ goto out;
}
/*
@@ -943,7 +951,11 @@ sysctl_vmm_destroy(SYSCTL_HANDLER_ARGS)
destroy_dev_sched_cb(dsc->cdev, devmem_destroy, dsc);
}
destroy_dev_sched_cb(cdev, vmmdev_destroy, sc);
- return (0);
+ error = 0;
+
+out:
+ free(buf, M_VMMDEV);
+ return (error);
}
SYSCTL_PROC(_hw_vmm, OID_AUTO, destroy,
CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON,
@@ -961,30 +973,34 @@ static struct cdevsw vmmdevsw = {
static int
sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
{
- int error;
struct vm *vm;
struct cdev *cdev;
struct vmmdev_softc *sc, *sc2;
- char buf[VM_MAX_NAMELEN];
+ char *buf;
+ int error, buflen;
error = vmm_priv_check(req->td->td_ucred);
if (error)
return (error);
- strlcpy(buf, "beavis", sizeof(buf));
- error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
+ buflen = VM_MAX_NAMELEN + 1;
+ buf = malloc(buflen, M_VMMDEV, M_WAITOK | M_ZERO);
+ strlcpy(buf, "beavis", buflen);
+ error = sysctl_handle_string(oidp, buf, buflen, req);
if (error != 0 || req->newptr == NULL)
- return (error);
+ goto out;
mtx_lock(&vmmdev_mtx);
sc = vmmdev_lookup(buf);
mtx_unlock(&vmmdev_mtx);
- if (sc != NULL)
- return (EEXIST);
+ if (sc != NULL) {
+ error = EEXIST;
+ goto out;
+ }
error = vm_create(buf, &vm);
if (error != 0)
- return (error);
+ goto out;
sc = malloc(sizeof(struct vmmdev_softc), M_VMMDEV, M_WAITOK | M_ZERO);
sc->vm = vm;
@@ -1004,14 +1020,15 @@ sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
if (sc2 != NULL) {
vmmdev_destroy(sc);
- return (EEXIST);
+ error = EEXIST;
+ goto out;
}
error = make_dev_p(MAKEDEV_CHECKNAME, &cdev, &vmmdevsw, NULL,
UID_ROOT, GID_WHEEL, 0600, "vmm/%s", buf);
if (error != 0) {
vmmdev_destroy(sc);
- return (error);
+ goto out;
}
mtx_lock(&vmmdev_mtx);
@@ -1019,7 +1036,9 @@ sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
sc->cdev->si_drv1 = sc;
mtx_unlock(&vmmdev_mtx);
- return (0);
+out:
+ free(buf, M_VMMDEV);
+ return (error);
}
SYSCTL_PROC(_hw_vmm, OID_AUTO, create,
CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON,
More information about the svn-src-all
mailing list