[PATCH 1/4] lxc: Add Real Time Clock device into allowed devices
Daniel Henrique Barboza
danielhb413 at gmail.com
Wed Feb 19 12:01:36 UTC 2020
On 2/16/20 2:11 PM, Julio Faracco wrote:
> 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 <jcfaracco at gmail.com>
> ---
> docs/formatdomain.html.in | 2 +-
> src/lxc/lxc_cgroup.c | 36 +++++++++++++++++++
> src/lxc/lxc_controller.c | 73 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 110 insertions(+), 1 deletion(-)
>
> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
> index 1a31eda154..b045314917 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 -
> <span class="since">since 3.2.0</span>), "hypervclock"
> (qemu - <span class="since">since 1.2.2</span>) or
> "armvtimer" (qemu - <span class="since">since 6.1.0</span>).
> diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c
> index 7f3701593a..752cb4b047 100644
> --- a/src/lxc/lxc_cgroup.c
> +++ b/src/lxc/lxc_cgroup.c
> @@ -410,6 +410,42 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def,
> VIR_CGROUP_DEVICE_RWM) < 0)
> return -1;
>
> + VIR_DEBUG("Allowing timers char devices");
> +
> + /* Sync'ed with Host clock */
> + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) {
> + for (i = 0; i < def->clock.ntimers; i++) {
> + virDomainTimerDefPtr timer = def->clock.timers[i];
> +
> + 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:
> + if (!timer->present)
> + break;
> +
> + if (virFileExists("/dev/rtc")) {
> + if (virCgroupAllowDevicePath(cgroup, "/dev/rtc",
> + VIR_CGROUP_DEVICE_READ,
> + false) < 0)
> + return -1;
> + } else {
> + VIR_DEBUG("Ignoring non-existent device /dev/rtc");
> + }
> + break;
> + }
> + }
> + } else {
> + VIR_DEBUG("Ignoring non-localtime clock");
> + }
> +
> VIR_DEBUG("Device whitelist complete");
>
> return 0;
> diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
> index c3dec0859c..528f2fabf1 100644
> --- a/src/lxc/lxc_controller.c
> +++ b/src/lxc/lxc_controller.c
> @@ -1550,6 +1550,76 @@ static int virLXCControllerPopulateDevices(virLXCControllerPtr ctrl)
> }
>
>
> +static int
> +virLXCControllerSetupTimers(virLXCControllerPtr ctrl)
> +{
> + int ret = -1;
> + char *path = NULL;
You can use g_autofree with this path variable to avoid the need for a VIR_FREE()
call and the 'cleanup' label. The 'ret' variable becomes unneeded after that as
well since you can just return -1 on error.
> + size_t i;
> + struct stat sb;
> + virDomainDefPtr def = ctrl->def;
> +
> + /* 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++) {
> + dev_t dev;
> + virDomainTimerDefPtr timer = def->clock.timers[i];
> +
> + 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:
> + if (!timer->present)
> + break;
> +
> + if (stat("/dev/rtc", &sb) < 0) {
> + if (errno == EACCES)
> + goto cleanup;
> +
> + virReportSystemError(errno,
> + _("Path '%s' is not accessible"),
> + path);
> + goto cleanup;
> + }
> +
> + path = g_strdup_printf("/%s/%s.dev/%s", LXC_STATE_DIR,
> + ctrl->def->name, "/rtc");
> +
> + 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);
> + goto cleanup;
> + }
> +
> + if (lxcContainerChown(ctrl->def, path) < 0)
> + goto cleanup;
> + break;
> + }
> + }
> +
> + ret = 0;
> + cleanup:
> + VIR_FREE(path);
> + return ret;
> +
> +}
> +
> +
> static int
> virLXCControllerSetupHostdevSubsysUSB(virDomainDefPtr vmDef,
> virDomainHostdevDefPtr def,
> @@ -2352,6 +2422,9 @@ virLXCControllerRun(virLXCControllerPtr ctrl)
> if (virLXCControllerPopulateDevices(ctrl) < 0)
> goto cleanup;
>
> + if (virLXCControllerSetupTimers(ctrl) < 0)
> + goto cleanup;
> +
> if (virLXCControllerSetupAllDisks(ctrl) < 0)
> goto cleanup;
>
>
More information about the libvir-list
mailing list