summaryrefslogtreecommitdiffstats
path: root/usr.sbin/vmd/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/vmd/config.c')
-rw-r--r--usr.sbin/vmd/config.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/usr.sbin/vmd/config.c b/usr.sbin/vmd/config.c
index eb1aa3a91df..373e027b425 100644
--- a/usr.sbin/vmd/config.c
+++ b/usr.sbin/vmd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.51 2018/10/08 16:32:01 reyk Exp $ */
+/* $OpenBSD: config.c,v 1.52 2018/10/15 10:35:41 reyk Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -193,6 +193,7 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm, uint32_t peerid, uid_t uid)
char base[PATH_MAX];
char expanded[PATH_MAX];
unsigned int unit;
+ struct timeval tv, rate, since_last;
errno = 0;
@@ -211,6 +212,39 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm, uint32_t peerid, uid_t uid)
}
}
+ /*
+ * Rate-limit the VM so that it cannot restart in a loop:
+ * if the VM restarts after less than VM_START_RATE_SEC seconds,
+ * we increment the limit counter. After VM_START_RATE_LIMIT
+ * of suchs fast reboots the VM is stopped.
+ */
+ getmonotime(&tv);
+ if (vm->vm_start_tv.tv_sec) {
+ timersub(&tv, &vm->vm_start_tv, &since_last);
+
+ rate.tv_sec = VM_START_RATE_SEC;
+ rate.tv_usec = 0;
+ if (timercmp(&since_last, &rate, <))
+ vm->vm_start_limit++;
+ else {
+ /* Reset counter */
+ vm->vm_start_limit = 0;
+ }
+
+ log_debug("%s: vm %u restarted after %lld.%ld seconds,"
+ " limit %d/%d", __func__, vcp->vcp_id, since_last.tv_sec,
+ since_last.tv_usec, vm->vm_start_limit,
+ VM_START_RATE_LIMIT);
+
+ if (vm->vm_start_limit >= VM_START_RATE_LIMIT) {
+ log_warnx("%s: vm %u restarted too quickly",
+ __func__, vcp->vcp_id);
+ errno = EPERM;
+ goto fail;
+ }
+ }
+ vm->vm_start_tv = tv;
+
for (i = 0; i < VMM_MAX_DISKS_PER_VM; i++)
for (j = 0; j < VM_MAX_BASE_PER_DISK; j++)
diskfds[i][j] = -1;