Hi,
this is the last diff of the series. It allows users to start or stop
VMs and to access the console accordingly. In order to make it work,
VMs have to be pre-configured with the new "owner" option in vm.conf
or an included file.
1. Add a "owner user[:group]" in your vm block of vm.conf, eg.
vm "foo" {
owner :wheel
}
$ vmctl status
ID PID VCPUS MAXMEM CURMEM TTY OWNER NAME
- - 1 1.0G - - :wheel foo
2. You can now start, stop and attach to it as a matching user:
$ vmctl start foo
$ vmctl status
ID PID VCPUS MAXMEM CURMEM TTY OWNER NAME
1 82712 1 1.0G 169M ttyp6 reyk:wheel foo
$ vmctl console foo
$ vmctl stop foo
It doesn't let you do any template/user-config yet, but this would be
another step. The tty handling is inspired by sshd, maybe a bit
tricky, and needs extra pledges in the parent process.
OK?
Reyk
Add "owner" option to set a user/group ownership for pre-configured VMs
This allows matching users to start or stop VMs that they "own" and to
access the console accordingly.
diff --git usr.sbin/vmctl/main.c usr.sbin/vmctl/main.c
index f0007c9..20227ac 100644
--- usr.sbin/vmctl/main.c
+++ usr.sbin/vmctl/main.c
@@ -151,7 +151,7 @@ parse(int argc, char *argv[])
if (!ctl->has_pledge) {
/* pledge(2) default if command doesn't have its own pledge */
- if (pledge("stdio rpath exec unix", NULL) == -1)
+ if (pledge("stdio rpath exec unix getpw", NULL) == -1)
err(1, "pledge");
}
if (ctl->main(&res, argc, argv) != 0)
diff --git usr.sbin/vmctl/vmctl.c usr.sbin/vmctl/vmctl.c
index ca2da8a..01f2617 100644
--- usr.sbin/vmctl/vmctl.c
+++ usr.sbin/vmctl/vmctl.c
@@ -16,7 +16,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/types.h>
+#include <sys/param.h>
#include <sys/queue.h>
#include <sys/uio.h>
#include <sys/stat.h>
@@ -35,6 +35,8 @@
#include <string.h>
#include <unistd.h>
#include <util.h>
+#include <pwd.h>
+#include <grp.h>
#include "vmd.h"
#include "vmctl.h"
@@ -369,14 +371,36 @@ print_vm_info(struct vmop_info_result *list, size_t ct)
char *vcpu_state, *tty;
char curmem[FMT_SCALED_STRSIZE];
char maxmem[FMT_SCALED_STRSIZE];
+ char user[16];
+ struct passwd *pw;
+ struct group *gr;
- printf("%5s %5s %5s %7s %7s %7s %s\n", "ID", "PID", "VCPUS",
- "MAXMEM", "CURMEM", "TTY", "NAME");
+ printf("%5s %5s %5s %7s %7s %7s %12s %s\n", "ID", "PID", "VCPUS",
+ "MAXMEM", "CURMEM", "TTY", "OWNER", "NAME");
for (i = 0; i < ct; i++) {
vmi = &list[i];
vir = &vmi->vir_info;
if (check_info_id(vir->vir_name, vir->vir_id)) {
+ /* get user name */
+ if ((pw = getpwuid(vmi->vir_uid)) == NULL)
+ (void)snprintf(user, sizeof(user),
+ "%d", vmi->vir_uid);
+ else
+ (void)strlcpy(user, pw->pw_name,
+ sizeof(user));
+ /* get group name */
+ if (vmi->vir_gid != -1) {
+ if (vmi->vir_uid == 0)
+ *user = '\0';
+ if ((gr = getgrgid(vmi->vir_gid)) == NULL)
+ (void)snprintf(user, sizeof(user),
+ "%s:%lld", user, vmi->vir_gid);
+ else
+ (void)snprintf(user, sizeof(user),
+ "%s:%s", user, gr->gr_name);
+ }
+
(void)strlcpy(curmem, "-", sizeof(curmem));
(void)strlcpy(maxmem, "-", sizeof(maxmem));
@@ -392,16 +416,16 @@ print_vm_info(struct vmop_info_result *list, size_t ct)
(void)fmt_scaled(vir->vir_used_size, curmem);
/* running vm */
- printf("%5u %5u %5zd %7s %7s %7s %s\n",
+ printf("%5u %5u %5zd %7s %7s %7s %12s %s\n",
vir->vir_id, vir->vir_creator_pid,
vir->vir_ncpus, maxmem, curmem,
- tty, vir->vir_name);
+ tty, user, vir->vir_name);
} else {
/* disabled vm */
- printf("%5s %5s %5zd %7s %7s %7s %s\n",
+ printf("%5s %5s %5zd %7s %7s %7s %12s %s\n",
"-", "-",
vir->vir_ncpus, maxmem, curmem,
- "-", vir->vir_name);
+ "-", user, vir->vir_name);
}
}
if (check_info_id(vir->vir_name, vir->vir_id) > 0) {
diff --git usr.sbin/vmd/config.c usr.sbin/vmd/config.c
index a16c143..72c151a 100644
--- usr.sbin/vmd/config.c
+++ usr.sbin/vmd/config.c
@@ -120,7 +120,7 @@ config_getreset(struct vmd *env, struct imsg *imsg)
}
int
-config_setvm(struct privsep *ps, struct vmd_vm *vm, uint32_t peerid)
+config_setvm(struct privsep *ps, struct vmd_vm *vm, uint32_t peerid, uid_t uid)
{
struct vmd_if *vif;
struct vmop_create_params *vmc = &vm->vm_params;
@@ -158,6 +158,7 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm,
uint32_t peerid)
tapfds[i] = -1;
vm->vm_peerid = peerid;
+ vm->vm_uid = uid;
/* Open external kernel for child */
if (strlen(vcp->vcp_kernel) &&
@@ -309,7 +310,7 @@ config_getvm(struct privsep *ps, struct imsg *imsg)
memcpy(&vmc, imsg->data, sizeof(vmc));
errno = 0;
- if (vm_register(ps, &vmc, &vm, imsg->hdr.peerid) == -1)
+ if (vm_register(ps, &vmc, &vm, imsg->hdr.peerid, 0) == -1)
goto fail;
/* If the fd is -1, the kernel will be searched on the disk */
diff --git usr.sbin/vmd/control.c usr.sbin/vmd/control.c
index cda7df9..0bdf90e 100644
--- usr.sbin/vmd/control.c
+++ usr.sbin/vmd/control.c
@@ -324,6 +324,8 @@ control_dispatch_imsg(int fd, short event, void *arg)
switch (imsg.hdr.type) {
case IMSG_VMDOP_GET_INFO_VM_REQUEST:
+ case IMSG_VMDOP_TERMINATE_VM_REQUEST:
+ case IMSG_VMDOP_START_VM_REQUEST:
break;
default:
if (c->peercred.uid != 0) {
@@ -351,7 +353,6 @@ control_dispatch_imsg(int fd, short event, void *arg)
case IMSG_CTL_VERBOSE:
if (IMSG_DATA_SIZE(&imsg) < sizeof(v))
goto fail;
-
memcpy(&v, imsg.data, sizeof(v));
log_setverbose(v);
@@ -360,9 +361,12 @@ control_dispatch_imsg(int fd, short event, void *arg)
case IMSG_VMDOP_START_VM_REQUEST:
if (IMSG_DATA_SIZE(&imsg) < sizeof(vmc))
goto fail;
+ memcpy(&vmc, imsg.data, sizeof(vmc));
+ vmc.vmc_uid = c->peercred.uid;
+ vmc.vmc_gid = -1;
+
if (proc_compose_imsg(ps, PROC_PARENT, -1,
- imsg.hdr.type, fd, -1,
- imsg.data, IMSG_DATA_SIZE(&imsg)) == -1) {
+ imsg.hdr.type, fd, -1, &vmc, sizeof(vmc)) == -1) {
control_close(fd, cs);
return;
}
@@ -370,9 +374,11 @@ control_dispatch_imsg(int fd, short event, void *arg)
case IMSG_VMDOP_TERMINATE_VM_REQUEST:
if (IMSG_DATA_SIZE(&imsg) < sizeof(vid))
goto fail;
+ memcpy(&vid, imsg.data, sizeof(vid));
+ vid.vid_uid = c->peercred.uid;
+
if (proc_compose_imsg(ps, PROC_PARENT, -1,
- imsg.hdr.type, fd, -1,
- imsg.data, IMSG_DATA_SIZE(&imsg)) == -1) {
+ imsg.hdr.type, fd, -1, &vid, sizeof(vid)) == -1) {
control_close(fd, cs);
return;
}
diff --git usr.sbin/vmd/parse.y usr.sbin/vmd/parse.y
index 30f002f..062146b 100644
--- usr.sbin/vmd/parse.y
+++ usr.sbin/vmd/parse.y
@@ -44,6 +44,8 @@
#include <util.h>
#include <errno.h>
#include <err.h>
+#include <pwd.h>
+#include <grp.h>
#include "proc.h"
#include "vmd.h"
@@ -101,6 +103,10 @@ typedef struct {
uint8_t lladdr[ETHER_ADDR_LEN];
int64_t number;
char *string;
+ struct {
+ uid_t uid;
+ int64_t gid;
+ } owner;
} v;
int lineno;
} YYSTYPE;
@@ -110,7 +116,7 @@ typedef struct {
%token INCLUDE ERROR
%token ADD DISK DOWN GROUP INTERFACE NIFS PATH SIZE SWITCH UP VMID
-%token ENABLE DISABLE VM KERNEL LLADDR MEMORY
+%token ENABLE DISABLE VM KERNEL LLADDR MEMORY OWNER
%token <v.string> STRING
%token <v.number> NUMBER
%type <v.number> disable
@@ -118,6 +124,7 @@ typedef struct {
%type <v.lladdr> lladdr
%type <v.string> string
%type <v.string> optstring
+%type <v.owner> owner_id
%%
@@ -260,6 +267,10 @@ vm : VM string {
yyerror("vm name too long");
YYERROR;
}
+
+ /* set default user/group permissions */
+ vmc.vmc_uid = 0;
+ vmc.vmc_gid = -1;
} '{' optnl vm_opts_l '}' {
int ret;
@@ -268,7 +279,8 @@ vm : VM string {
vcp->vcp_nnics = vcp_nnics;
if (!env->vmd_noaction) {
- ret = vm_register(&env->vmd_ps, &vmc, &vm, 0);
+ ret = vm_register(&env->vmd_ps, &vmc,
+ &vm, 0, 0);
if (ret == -1 && errno == EALREADY) {
log_debug("%s:%d: vm \"%s\""
" skipped (%s)",
@@ -398,6 +410,57 @@ vm_opts : disable {
vcp->vcp_memranges[0].vmr_size = (size_t)res;
vmc.vmc_flags |= VMOP_CREATE_MEMORY;
}
+ | OWNER owner_id {
+ vmc.vmc_uid = $2.uid;
+ vmc.vmc_gid = $2.gid;
+ }
+ ;
+
+owner_id : /* none */ {
+ $$.uid = 0;
+ $$.gid = -1;
+ }
+ | NUMBER {
+ $$.uid = $1;
+ $$.gid = -1;
+ }
+ | STRING {
+ char *user, *group;
+ struct passwd *pw;
+ struct group *gr;
+
+ $$.uid = 0;
+ $$.gid = -1;
+
+ user = $1;
+ if ((group = strchr(user, ':')) != NULL) {
+ if (group == user)
+ user = NULL;
+ *group++ = '\0';
+ }
+
+ if (user != NULL && *user) {
+ if ((pw = getpwnam(user)) == NULL) {
+ yyerror("failed to get user: %s",
+ user);
+ free($1);
+ YYERROR;
+ }
+ $$.uid = pw->pw_uid;
+ }
+
+ if (group != NULL && *group) {
+ if ((gr = getgrnam(group)) == NULL) {
+ yyerror("failed to get group: %s",
+ group);
+ free($1);
+ YYERROR;
+ }
+ $$.gid = gr->gr_gid;
+ }
+
+ free($1);
+ }
;
iface_opts_o : '{' optnl iface_opts_l '}'
@@ -544,6 +607,7 @@ lookup(char *s)
{ "kernel", KERNEL },
{ "lladdr", LLADDR },
{ "memory", MEMORY },
+ { "owner", OWNER },
{ "size", SIZE },
{ "switch", SWITCH },
{ "up", UP },
diff --git usr.sbin/vmd/vm.conf.5 usr.sbin/vmd/vm.conf.5
index 9a48a51..c1401ec 100644
--- usr.sbin/vmd/vm.conf.5
+++ usr.sbin/vmd/vm.conf.5
@@ -161,6 +161,12 @@ Kernel to load when booting the VM.
.It Cm memory Ar bytes
Memory size of the VM, in bytes, rounded to megabytes.
The default is 512M.
+.It Cm owner Ar user Ns Op : Ns Ar group
+Set the owner of the VM to the specified user or group.
+The owner will be allowed to start or stop the VM and get the
+permissions to open the VM's console.
+.It Cm owner Pf : Ar group
+Set the owner to the specified group.
.El
.Sh SWITCH CONFIGURATION
A virtual switch allows VMs to communicate with other network interfaces on the
diff --git usr.sbin/vmd/vmd.c usr.sbin/vmd/vmd.c
index ed678ee..6152c4f 100644
--- usr.sbin/vmd/vmd.c
+++ usr.sbin/vmd/vmd.c
@@ -20,6 +20,7 @@
#include <sys/queue.h>
#include <sys/wait.h>
#include <sys/cdefs.h>
+#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/ioctl.h>
@@ -35,6 +36,8 @@
#include <syslog.h>
#include <unistd.h>
#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
#include "proc.h"
#include "vmd.h"
@@ -80,7 +83,7 @@ vmd_dispatch_control(int fd, struct privsep_proc *p, struct
imsg *imsg)
case IMSG_VMDOP_START_VM_REQUEST:
IMSG_SIZE_CHECK(imsg, &vmc);
memcpy(&vmc, imsg->data, sizeof(vmc));
- ret = vm_register(ps, &vmc, &vm, 0);
+ ret = vm_register(ps, &vmc, &vm, 0, vmc.vmc_uid);
if (vmc.vmc_flags == 0) {
/* start an existing VM with pre-configured options */
if (!(ret == -1 && errno == EALREADY)) {
@@ -92,7 +95,7 @@ vmd_dispatch_control(int fd, struct privsep_proc *p, struct
imsg *imsg)
cmd = IMSG_VMDOP_START_VM_RESPONSE;
}
if (res == 0 &&
- config_setvm(ps, vm, imsg->hdr.peerid) == -1) {
+ config_setvm(ps, vm, imsg->hdr.peerid, vmc.vmc_uid) == -1) {
res = errno;
cmd = IMSG_VMDOP_START_VM_RESPONSE;
}
@@ -108,6 +111,12 @@ vmd_dispatch_control(int fd, struct privsep_proc *p,
struct imsg *imsg)
break;
}
id = vm->vm_params.vmc_params.vcp_id;
+ } else
+ vm = vm_getbyid(id);
+ if (vm_checkperm(vm, vid.vid_uid) != 0) {
+ res = EPERM;
+ cmd = IMSG_VMDOP_TERMINATE_VM_RESPONSE;
+ break;
}
memset(&vtp, 0, sizeof(vtp));
vtp.vtp_vm_id = id;
@@ -247,7 +256,7 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struct
imsg *imsg)
} else if (vmr.vmr_result == EAGAIN) {
/* Stop VM instance but keep the tty open */
vm_stop(vm, 1);
- config_setvm(ps, vm, (uint32_t)-1);
+ config_setvm(ps, vm, (uint32_t)-1, 0);
}
break;
case IMSG_VMDOP_GET_INFO_VM_DATA:
@@ -256,6 +265,9 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struct
imsg *imsg)
if ((vm = vm_getbyid(vir.vir_info.vir_id)) != NULL) {
(void)strlcpy(vir.vir_ttyname, vm->vm_ttyname,
sizeof(vir.vir_ttyname));
+ /* get the user id who started the vm */
+ vir.vir_uid = vm->vm_uid;
+ vir.vir_gid = vm->vm_params.vmc_gid;
}
if (proc_compose_imsg(ps, PROC_CONTROL, -1, imsg->hdr.type,
imsg->hdr.peerid, -1, &vir, sizeof(vir)) == -1) {
@@ -280,6 +292,9 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struct
imsg *imsg)
vm->vm_params.vmc_params.vcp_memranges[0].vmr_size;
vir.vir_info.vir_ncpus =
vm->vm_params.vmc_params.vcp_ncpus;
+ /* get the configured user id for this vm */
+ vir.vir_uid = vm->vm_params.vmc_uid;
+ vir.vir_gid = vm->vm_params.vmc_gid;
if (proc_compose_imsg(ps, PROC_CONTROL, -1,
IMSG_VMDOP_GET_INFO_VM_DATA,
imsg->hdr.peerid, -1, &vir,
@@ -496,8 +511,11 @@ vmd_configure(void)
* tty - for openpty.
* proc - run kill to terminate its children safely.
* sendfd - for disks, interfaces and other fds.
+ * getpw - lookup user or group id by name.
+ * chown, fattr - change tty ownership
*/
- if (pledge("stdio rpath wpath proc tty sendfd", NULL) == -1)
+ if (pledge("stdio rpath wpath proc tty sendfd getpw"
+ " chown fattr", NULL) == -1)
fatal("pledge");
if (parse_config(env->vmd_conffile) == -1) {
@@ -529,7 +547,7 @@ vmd_configure(void)
vm->vm_params.vmc_params.vcp_name);
continue;
}
- if (config_setvm(&env->vmd_ps, vm, -1) == -1)
+ if (config_setvm(&env->vmd_ps, vm, -1, 0) == -1)
return (-1);
}
@@ -595,7 +613,7 @@ vmd_reload(unsigned int reset, const char *filename)
vm->vm_params.vmc_params.vcp_name);
continue;
}
- if (config_setvm(&env->vmd_ps, vm, -1) == -1)
+ if (config_setvm(&env->vmd_ps, vm, -1, 0) == -1)
return;
} else {
log_debug("%s: not creating vm \"%s\": "
@@ -712,6 +730,7 @@ vm_stop(struct vmd_vm *vm, int keeptty)
close(vm->vm_kernel);
vm->vm_kernel = -1;
}
+ vm->vm_uid = 0;
if (!keeptty)
vm_closetty(vm);
}
@@ -729,7 +748,7 @@ vm_remove(struct vmd_vm *vm)
int
vm_register(struct privsep *ps, struct vmop_create_params *vmc,
- struct vmd_vm **ret_vm, uint32_t id)
+ struct vmd_vm **ret_vm, uint32_t id, uid_t uid)
{
struct vmd_vm *vm = NULL;
struct vm_create_params *vcp = &vmc->vmc_params;
@@ -739,11 +758,23 @@ vm_register(struct privsep *ps, struct vmop_create_params
*vmc,
*ret_vm = NULL;
if ((vm = vm_getbyname(vcp->vcp_name)) != NULL) {
+ if (vm_checkperm(vm, uid) != 0 || vmc->vmc_flags != 0) {
+ errno = EPERM;
+ goto fail;
+ }
*ret_vm = vm;
errno = EALREADY;
goto fail;
}
+ /*
+ * non-root users can only start existing VMs
+ * XXX there could be a mechanism to allow overwriting some options
+ */
+ if (vm_checkperm(NULL, uid) != 0) {
+ errno = EPERM;
+ goto fail;
+ }
if (vmc->vmc_flags == 0) {
errno = ENOENT;
goto fail;
@@ -797,9 +828,45 @@ vm_register(struct privsep *ps, struct vmop_create_params
*vmc,
}
int
+vm_checkperm(struct vmd_vm *vm, uid_t uid)
+{
+ struct group *gr;
+ struct passwd *pw;
+ char **grmem;
+
+ /* root has no restrictions */
+ if (uid == 0)
+ return (0);
+
+ if (vm == NULL)
+ return (-1);
+
+ /* check supplementary groups */
+ if (vm->vm_params.vmc_gid != -1 &&
+ (pw = getpwuid(uid)) != NULL &&
+ (gr = getgrgid(vm->vm_params.vmc_gid)) != NULL) {
+ for (grmem = gr->gr_mem; *grmem; grmem++)
+ if (strcmp(*grmem, pw->pw_name) == 0)
+ return (0);
+ }
+
+ /* check user */
+ if ((vm->vm_running && vm->vm_uid == uid) ||
+ (!vm->vm_running && vm->vm_params.vmc_uid == uid))
+ return (0);
+
+ return (-1);
+}
+
+int
vm_opentty(struct vmd_vm *vm)
{
struct ptmget ptm;
+ struct stat st;
+ struct group *gr;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
/*
* Open tty with pre-opened PTM fd
@@ -812,6 +879,54 @@ vm_opentty(struct vmd_vm *vm)
if ((vm->vm_ttyname = strdup(ptm.sn)) == NULL)
goto fail;
+ uid = vm->vm_uid;
+ gid = vm->vm_params.vmc_gid;
+
+ if (vm->vm_params.vmc_gid != -1) {
+ mode = 0660;
+ } else if ((gr = getgrnam("tty")) != NULL) {
+ gid = gr->gr_gid;
+ mode = 0620;
+ } else {
+ mode = 0600;
+ gid = 0;
+ }
+
+ log_debug("%s: vm %s tty %s uid %d gid %d mode %o",
+ __func__, vm->vm_params.vmc_params.vcp_name,
+ vm->vm_ttyname, uid, gid, mode);
+
+ /*
+ * Change ownership and mode of the tty as required.
+ * Loosely based on the implementation of sshpty.c
+ */
+ if (stat(vm->vm_ttyname, &st) == -1)
+ goto fail;
+
+ if (st.st_uid != uid || st.st_gid != gid) {
+ if (chown(vm->vm_ttyname, uid, gid) == -1) {
+ log_warn("chown %s %d %d failed, uid %d",
+ vm->vm_ttyname, uid, gid, getuid());
+
+ /* Ignore failure on read-only filesystems */
+ if (!((errno == EROFS) &&
+ (st.st_uid == uid || st.st_uid == 0)))
+ goto fail;
+ }
+ }
+
+ if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) {
+ if (chmod(vm->vm_ttyname, mode) == -1) {
+ log_warn("chmod %s %o failed, uid %d",
+ vm->vm_ttyname, mode, getuid());
+
+ /* Ignore failure on read-only filesystems */
+ if (!((errno == EROFS) &&
+ (st.st_uid == uid || st.st_uid == 0)))
+ goto fail;
+ }
+ }
+
return (0);
fail:
vm_closetty(vm);
@@ -822,6 +937,11 @@ void
vm_closetty(struct vmd_vm *vm)
{
if (vm->vm_tty != -1) {
+ /* Release and close the tty */
+ if (fchown(vm->vm_tty, 0, 0) == -1)
+ log_warn("chown %s 0 0 failed", vm->vm_ttyname);
+ if (fchmod(vm->vm_tty, 0666) == -1)
+ log_warn("chmod %s 0666 failed", vm->vm_ttyname);
close(vm->vm_tty);
vm->vm_tty = -1;
}
diff --git usr.sbin/vmd/vmd.h usr.sbin/vmd/vmd.h
index 26d345c..af31349 100644
--- usr.sbin/vmd/vmd.h
+++ usr.sbin/vmd/vmd.h
@@ -87,11 +87,14 @@ struct vmop_result {
struct vmop_info_result {
struct vm_info_result vir_info;
char vir_ttyname[VM_TTYNAME_MAX];
+ uid_t vir_uid;
+ int64_t vir_gid;
};
struct vmop_id {
uint32_t vid_id;
char vid_name[VMM_MAX_NAME_LEN];
+ uid_t vid_uid;
};
struct vmop_ifreq {
@@ -113,6 +116,8 @@ struct vmop_create_params {
char vmc_ifnames[VMM_MAX_NICS_PER_VM][IF_NAMESIZE];
char vmc_ifswitch[VMM_MAX_NICS_PER_VM][VM_NAME_MAX];
char vmc_ifgroup[VMM_MAX_NICS_PER_VM][IF_NAMESIZE];
+ uid_t vmc_uid;
+ int64_t vmc_gid;
};
struct vmboot_params {
@@ -166,6 +171,8 @@ struct vmd_vm {
int vm_from_config;
struct imsgev vm_iev;
int vm_shutdown;
+ uid_t vm_uid;
+
TAILQ_ENTRY(vmd_vm) vm_entry;
};
TAILQ_HEAD(vmlist, vmd_vm);
@@ -197,7 +204,8 @@ struct vmd_vm *vm_getbypid(pid_t);
void vm_stop(struct vmd_vm *, int);
void vm_remove(struct vmd_vm *);
int vm_register(struct privsep *, struct vmop_create_params *,
- struct vmd_vm **, uint32_t);
+ struct vmd_vm **, uint32_t, uid_t);
+int vm_checkperm(struct vmd_vm *, uid_t);
int vm_opentty(struct vmd_vm *);
void vm_closetty(struct vmd_vm *);
void switch_remove(struct vmd_switch *);
@@ -227,7 +235,7 @@ int config_init(struct vmd *);
void config_purge(struct vmd *, unsigned int);
int config_setreset(struct vmd *, unsigned int);
int config_getreset(struct vmd *, struct imsg *);
-int config_setvm(struct privsep *, struct vmd_vm *, uint32_t);
+int config_setvm(struct privsep *, struct vmd_vm *, uint32_t, uid_t);
int config_getvm(struct privsep *, struct imsg *);
int config_getdisk(struct privsep *, struct imsg *);
int config_getif(struct privsep *, struct imsg *);