From: Julio Faracco Date: Mon, 2 Mar 2020 00:54:12 +0000 (-0300) Subject: lxc: Add Real Time Clock device into allowed devices X-Git-Tag: v6.2.0-rc1~143 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9132badf2787b85817bc64a5309298721cb20abf;p=thirdparty%2Flibvirt.git lxc: Add Real Time Clock device into allowed devices This commit share host Real Time Clock device (rtc) into LXC containers to support hardware clock. This should be available setting up a `rtc` timer under clock section. Since this option is not emulated, it should be available only for `localtime` clock. This option should be readonly due to security reasons. Before: root# hwclock --verbose hwclock from util-linux 2.32.1 System Time: 1581877557.598365 Trying to open: /dev/rtc0 Trying to open: /dev/rtc Trying to open: /dev/misc/rtc No usable clock interface found. hwclock: Cannot access the Hardware Clock via any known method. Now: root# hwclock 2020-02-16 18:23:55.374134+00:00 root# hwclock -w hwclock: ioctl(RTC_SET_TIME) to /dev/rtc to set the time failed: Permission denied Signed-off-by: Julio Faracco Signed-off-by: Michal Privoznik Reviewed-by: Michal Privoznik --- diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 594146009d..180afe4333 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2465,7 +2465,7 @@ being modified, and can be one of "platform" (currently unsupported), "hpet" (libxl, xen, qemu), "kvmclock" (qemu), - "pit" (qemu), "rtc" (qemu), "tsc" (libxl, qemu - + "pit" (qemu), "rtc" (qemu, lxc), "tsc" (libxl, qemu - since 3.2.0), "hypervclock" (qemu - since 1.2.2) or "armvtimer" (qemu - since 6.1.0). diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index 952d021418..06605cb9ba 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -333,6 +333,46 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def, VIR_CGROUP_DEVICE_RWM) < 0) return -1; + VIR_DEBUG("Allowing timers char devices"); + + /* Sync'ed with Host clock */ + for (i = 0; i < def->clock.ntimers; i++) { + virDomainTimerDefPtr timer = def->clock.timers[i]; + const char *dev = NULL; + + /* Check if "present" is set to "no" otherwise enable it. */ + if (!timer->present) + continue; + + switch ((virDomainTimerNameType)timer->name) { + case VIR_DOMAIN_TIMER_NAME_PLATFORM: + case VIR_DOMAIN_TIMER_NAME_TSC: + case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: + case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK: + case VIR_DOMAIN_TIMER_NAME_PIT: + case VIR_DOMAIN_TIMER_NAME_HPET: + case VIR_DOMAIN_TIMER_NAME_ARMVTIMER: + case VIR_DOMAIN_TIMER_NAME_LAST: + break; + case VIR_DOMAIN_TIMER_NAME_RTC: + dev = "/dev/rtc0"; + break; + } + + if (!dev) + continue; + + if (!virFileExists(dev)) { + VIR_DEBUG("Ignoring non-existent device %s", dev); + continue; + } + + if (virCgroupAllowDevicePath(cgroup, dev, + VIR_CGROUP_DEVICE_READ, + false) < 0) + return -1; + } + VIR_DEBUG("Device whitelist complete"); return 0; diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index fa7b9dd0e7..85986babb8 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -1530,6 +1530,73 @@ static int virLXCControllerPopulateDevices(virLXCControllerPtr ctrl) } +static int +virLXCControllerSetupTimers(virLXCControllerPtr ctrl) +{ + virDomainDefPtr def = ctrl->def; + size_t i; + + /* Not sync'ed with Host clock */ + if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) + return 0; + + for (i = 0; i < def->clock.ntimers; i++) { + virDomainTimerDefPtr timer = def->clock.timers[i]; + g_autofree char *path = NULL; + const char *timer_dev = NULL; + struct stat sb; + dev_t dev; + + /* Check if "present" is set to "no" otherwise enable it. */ + if (!timer->present) + continue; + + switch ((virDomainTimerNameType)timer->name) { + case VIR_DOMAIN_TIMER_NAME_PLATFORM: + case VIR_DOMAIN_TIMER_NAME_TSC: + case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: + case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK: + case VIR_DOMAIN_TIMER_NAME_PIT: + case VIR_DOMAIN_TIMER_NAME_HPET: + case VIR_DOMAIN_TIMER_NAME_ARMVTIMER: + case VIR_DOMAIN_TIMER_NAME_LAST: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(timer->name)); + return -1; + case VIR_DOMAIN_TIMER_NAME_RTC: + timer_dev = "/dev/rtc0"; + path = g_strdup_printf("/%s/%s.dev/%s", LXC_STATE_DIR, + def->name, "/rtc"); + break; + } + + if (!timer_dev) + continue; + + if (stat(timer_dev, &sb) < 0) { + virReportSystemError(errno, _("Unable to access %s"), + timer_dev); + return -1; + } + + dev = makedev(major(sb.st_rdev), minor(sb.st_rdev)); + if (mknod(path, S_IFCHR, dev) < 0 || + chmod(path, sb.st_mode)) { + virReportSystemError(errno, + _("Failed to make device %s"), + path); + return -1; + } + + if (lxcContainerChown(def, path) < 0) + return -1; + } + + return 0; +} + + static int virLXCControllerSetupHostdevSubsysUSB(virDomainDefPtr vmDef, virDomainHostdevDefPtr def, @@ -2321,6 +2388,9 @@ virLXCControllerRun(virLXCControllerPtr ctrl) if (virLXCControllerPopulateDevices(ctrl) < 0) goto cleanup; + if (virLXCControllerSetupTimers(ctrl) < 0) + goto cleanup; + if (virLXCControllerSetupAllDisks(ctrl) < 0) goto cleanup;