On Mon, Nov 14, 2016 at 05:43:30PM +0100, Michal Privoznik wrote: > Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> > --- > src/qemu/qemu_domain.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++++ > src/qemu/qemu_domain.h | 8 ++ > src/qemu/qemu_process.c | 13 +++ > 3 files changed, 254 insertions(+) > > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > index 8cba755..3a0170c 100644 > --- a/src/qemu/qemu_domain.c > +++ b/src/qemu/qemu_domain.c > @@ -55,6 +55,7 @@ > > #include <sys/time.h> > #include <fcntl.h> > +#include <sys/mount.h> > > #include <libxml/xpathInternals.h> > > @@ -86,6 +87,21 @@ VIR_ENUM_IMPL(qemuDomainAsyncJob, QEMU_ASYNC_JOB_LAST, > "start", > ); > > +#define QEMU_DEV_MAJ_MEMORY 1 > +#define QEMU_DEV_MAJ_TTY 5 > +#define QEMU_DEV_MAJ_KVM 10 > +#define QEMU_DEV_MAJ_PTY 136 > + > +#define QEMU_DEV_MIN_CONSOLE 1 > +#define QEMU_DEV_MIN_FULL 7 > +#define QEMU_DEV_MIN_FUSE 229 > +#define QEMU_DEV_MIN_KVM 232 > +#define QEMU_DEV_MIN_NULL 3 > +#define QEMU_DEV_MIN_PTMX 2 > +#define QEMU_DEV_MIN_RANDOM 8 > +#define QEMU_DEV_MIN_TTY 0 > +#define QEMU_DEV_MIN_URANDOM 9 > +#define QEMU_DEV_MIN_ZERO 5 > > struct _qemuDomainLogContext { > int refs; > @@ -6658,3 +6674,220 @@ qemuDomainSupportsVideoVga(virDomainVideoDefPtr video, > > return true; > } > + > + > +static int > +qemuDomainPopulateDevices(virQEMUDriverPtr driver ATTRIBUTE_UNUSED, > + virDomainObjPtr vm ATTRIBUTE_UNUSED, > + const char *path) > +{ > + int ret = -1; > + virFileDevices devs[] = { > + { QEMU_DEV_MAJ_MEMORY, QEMU_DEV_MIN_NULL, 0666, "/null" }, > + { QEMU_DEV_MAJ_MEMORY, QEMU_DEV_MIN_ZERO, 0666, "/zero" }, > + { QEMU_DEV_MAJ_MEMORY, QEMU_DEV_MIN_FULL, 0666, "/full" }, > + { QEMU_DEV_MAJ_KVM, QEMU_DEV_MIN_KVM, 0660, "/kvm"}, > + { QEMU_DEV_MAJ_MEMORY, QEMU_DEV_MIN_RANDOM, 0666, "/random" }, > + { QEMU_DEV_MAJ_MEMORY, QEMU_DEV_MIN_URANDOM, 0666, "/urandom" }, > + { QEMU_DEV_MAJ_TTY, QEMU_DEV_MIN_TTY, 0666, "/tty" }, > + { 0, 0, 0, NULL}, > + }; > + > + if (virFilePopulateDevices(path, devs) < 0) > + goto cleanup; > + > + ret = 0; > + cleanup: > + return ret; > +} > + > + > +static int > +qemuDomainSetupDev(virQEMUDriverPtr driver, > + virDomainObjPtr vm, > + const char *path) > +{ > + char *mount_options = NULL; > + char *opts = NULL; > + int ret = -1; > + > + VIR_DEBUG("Setting up /dev/ for domain %s", vm->def->name); > + > + mount_options = virSecurityManagerGetMountOptions(driver->securityManager, > + vm->def); > + > + if (!mount_options && > + VIR_STRDUP(mount_options, "") < 0) > + goto cleanup; > + > + /* > + * tmpfs is limited to 64kb, since we only have device nodes in there > + * and don't want to DOS the entire OS RAM usage > + */ > + if (virAsprintf(&opts, > + "mode=755,size=65536%s", mount_options) < 0) > + goto cleanup; > + > + if (virFileSetupDev(path, opts) < 0) > + goto cleanup; > + > + if (qemuDomainPopulateDevices(driver, vm, path) < 0) > + goto cleanup; > + > + ret = 0; > + cleanup: > + VIR_FREE(opts); > + VIR_FREE(mount_options); > + return ret; > +} > + > + > +static int > +qemuDomainSetupDevPTS(virQEMUDriverPtr driver, > + virDomainObjPtr vm, > + const char *path) > +{ > + char *mount_options = NULL; > + char *opts = NULL; > + int ret = -1; > + const gid_t ptsgid = 5; > + > + mount_options = virSecurityManagerGetMountOptions(driver->securityManager, > + vm->def); > + > + if (!mount_options && > + VIR_STRDUP(mount_options, "") < 0) > + goto cleanup; > + > + if (virAsprintf(&opts, "newinstance,ptmxmode=0666,mode=0620,gid=%u%s", > + ptsgid, (mount_options ? mount_options : "")) < 0) > + goto cleanup; > + > + if (virFileSetupDevPTS(path, opts, NULL) < 0) > + goto cleanup; > + > + ret = 0; > + cleanup: > + VIR_FREE(opts); > + VIR_FREE(mount_options); > + return ret; > +} This is going to cause problems - the /dev/pts/NNN nodes that QEMU has open (for its chardev backend) are exposed in the guest XML and are intended to be accessed by other processes on the host. By setting up a new /dev/pts mount with newinstance, the /dev/pts/NNN nodes for chardevs will be invisible to the host OS. So while you want to replace /dev completely, you need to keep the original /dev/pts mount unchanged. Practically speaking this means that after doing the unshare() you need to use mount() with MS_MOVE to move /dev/pts somewhere safe, then unmount the old /dev, mount our new /dev instance and then finally MS_MOVE the saved /dev/pts back in place. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://entangle-photo.org -o- http://search.cpan.org/~danberr/ :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list