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
This commit is contained in:
parent
dbb1521165
commit
422a8a4d3a
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -245,7 +245,7 @@ vmmdev_rw(struct cdev *cdev, struct uio *uio, int flags)
|
||||
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 *mseg)
|
||||
}
|
||||
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 *mseg)
|
||||
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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user