Change the way root_owner works: consider the calling process as root_owner

not if it has root privileges, but if the /dev/nvmm device was opened with
write permissions. Introduce the undocumented nvmm_root_init() function to
achieve that.

The goal is to simplify the logic and have more granularity, eg if we want
a monitoring agent to access VMs but don't want to give this agent real
root access on the system.
This commit is contained in:
maxv 2019-10-27 20:17:36 +00:00
parent 2845a430aa
commit d2ac291e7d
3 changed files with 40 additions and 17 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: libnvmm.c,v 1.17 2019/10/27 07:08:15 maxv Exp $ */
/* $NetBSD: libnvmm.c,v 1.18 2019/10/27 20:17:36 maxv Exp $ */
/*
* Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
@ -179,6 +179,29 @@ nvmm_init(void)
return 0;
}
int
nvmm_root_init(void)
{
if (nvmm_fd != -1)
return 0;
nvmm_fd = open("/dev/nvmm", O_WRONLY | O_CLOEXEC);
if (nvmm_fd == -1)
return -1;
if (nvmm_capability(&__capability) == -1) {
close(nvmm_fd);
nvmm_fd = -1;
return -1;
}
if (__capability.version != NVMM_KERN_VERSION) {
close(nvmm_fd);
nvmm_fd = -1;
errno = EPROGMISMATCH;
return -1;
}
return 0;
}
int
nvmm_capability(struct nvmm_capability *cap)
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: nvmm.h,v 1.15 2019/10/27 07:08:15 maxv Exp $ */
/* $NetBSD: nvmm.h,v 1.16 2019/10/27 20:17:36 maxv Exp $ */
/*
* Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
@ -90,6 +90,7 @@ struct nvmm_mem {
typedef uint64_t nvmm_prot_t;
int nvmm_init(void);
int nvmm_root_init(void);
int nvmm_capability(struct nvmm_capability *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: nvmm.c,v 1.23 2019/10/23 07:01:11 maxv Exp $ */
/* $NetBSD: nvmm.c,v 1.24 2019/10/27 20:17:36 maxv Exp $ */
/*
* Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.23 2019/10/23 07:01:11 maxv Exp $");
__KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.24 2019/10/27 20:17:36 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -889,7 +889,7 @@ out:
/* -------------------------------------------------------------------------- */
static int
nvmm_ctl_mach_info(struct nvmm_ioc_ctl *args)
nvmm_ctl_mach_info(struct nvmm_owner *owner, struct nvmm_ioc_ctl *args)
{
struct nvmm_ctl_mach_info ctl;
struct nvmm_machine *mach;
@ -903,7 +903,7 @@ nvmm_ctl_mach_info(struct nvmm_ioc_ctl *args)
if (error)
return error;
error = nvmm_machine_get(&root_owner, ctl.machid, &mach, true);
error = nvmm_machine_get(owner, ctl.machid, &mach, true);
if (error)
return error;
@ -930,16 +930,9 @@ nvmm_ctl_mach_info(struct nvmm_ioc_ctl *args)
static int
nvmm_ctl(struct nvmm_owner *owner, struct nvmm_ioc_ctl *args)
{
int error;
error = kauth_authorize_device(curlwp->l_cred, KAUTH_DEVICE_NVMM_CTL,
NULL, NULL, NULL, NULL);
if (error)
return error;
switch (args->op) {
case NVMM_CTL_MACH_INFO:
return nvmm_ctl_mach_info(args);
return nvmm_ctl_mach_info(owner, args);
default:
return EINVAL;
}
@ -1047,8 +1040,12 @@ nvmm_open(dev_t dev, int flags, int type, struct lwp *l)
if (error)
return error;
owner = kmem_alloc(sizeof(*owner), KM_SLEEP);
owner->pid = l->l_proc->p_pid;
if (OFLAGS(flags) & O_WRONLY) {
owner = &root_owner;
} else {
owner = kmem_alloc(sizeof(*owner), KM_SLEEP);
owner->pid = l->l_proc->p_pid;
}
return fd_clone(fp, fd, flags, &nvmm_fileops, owner);
}
@ -1060,7 +1057,9 @@ nvmm_close(file_t *fp)
KASSERT(owner != NULL);
nvmm_kill_machines(owner);
kmem_free(owner, sizeof(*owner));
if (owner != &root_owner) {
kmem_free(owner, sizeof(*owner));
}
fp->f_data = NULL;
return 0;