8c03ec
From c82c32f60579d148f37064e5156e857fa3c84c2f Mon Sep 17 00:00:00 2001
8c03ec
Message-Id: <c82c32f60579d148f37064e5156e857fa3c84c2f@dist-git>
8c03ec
From: Pavel Hrdina <phrdina@redhat.com>
8c03ec
Date: Thu, 4 Mar 2021 12:57:57 +0100
8c03ec
Subject: [PATCH] vircgroup: enforce range limit for cpu.shares
8c03ec
MIME-Version: 1.0
8c03ec
Content-Type: text/plain; charset=UTF-8
8c03ec
Content-Transfer-Encoding: 8bit
8c03ec
8c03ec
Before the conversion to using systemd DBus API to set the cpu.shares
8c03ec
there was some magic conversion done by kernel which was documented in
8c03ec
virsh manpage as well. Now systemd errors out if the value is out of
8c03ec
range.
8c03ec
8c03ec
Since we enforce the range for other cpu cgroup attributes 'quota' and
8c03ec
'period' it makes sense to do the same for 'shares' as well.
8c03ec
8c03ec
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
8c03ec
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
8c03ec
(cherry picked from commit 1d9d9961ada6c2d0b9facae0ef8be4f459cf7fc9)
8c03ec
8c03ec
Conflicts:
8c03ec
    docs/formatdomain.rst
8c03ec
    src/conf/domain_validate.c
8c03ec
        - both are not present in downstream
8c03ec
8c03ec
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1798463
8c03ec
8c03ec
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
8c03ec
Message-Id: <79b9ef9f98b3ab35061f8c4e4acf7b6861d28055.1614858616.git.phrdina@redhat.com>
8c03ec
Reviewed-by: Ján Tomko <jtomko@redhat.com>
8c03ec
---
8c03ec
 docs/formatdomain.html.in |  1 +
8c03ec
 docs/manpages/virsh.rst   |  5 +----
8c03ec
 src/conf/domain_conf.c    | 10 ++++++++++
8c03ec
 src/util/vircgroup.h      |  2 ++
8c03ec
 src/util/vircgroupv1.c    | 10 ++++++++++
8c03ec
 src/util/vircgroupv2.c    | 10 ++++++++++
8c03ec
 6 files changed, 34 insertions(+), 4 deletions(-)
8c03ec
8c03ec
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
8c03ec
index 4341e256a8..7ac9523684 100644
8c03ec
--- a/docs/formatdomain.html.in
8c03ec
+++ b/docs/formatdomain.html.in
8c03ec
@@ -854,6 +854,7 @@
8c03ec
         it's a relative measure based on the setting of other VM,
8c03ec
         e.g. A VM configured with value
8c03ec
         2048 will get twice as much CPU time as a VM configured with value 1024.
8c03ec
+        The value should be in range [2, 262144].
8c03ec
         Since 0.9.0
8c03ec
       
8c03ec
       
period
8c03ec
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
8c03ec
index a5b95c1123..01e1c01912 100644
8c03ec
--- a/docs/manpages/virsh.rst
8c03ec
+++ b/docs/manpages/virsh.rst
8c03ec
@@ -3704,10 +3704,7 @@ If *--live* is specified, set scheduler information of a running guest.
8c03ec
 If *--config* is specified, affect the next boot of a persistent guest.
8c03ec
 If *--current* is specified, affect the current guest state.
8c03ec
 
8c03ec
-``Note``: The cpu_shares parameter has a valid value range of 0-262144; Negative
8c03ec
-values are wrapped to positive, and larger values are capped at the maximum.
8c03ec
-Therefore, -1 is a useful shorthand for 262144. On the Linux kernel, the
8c03ec
-values 0 and 1 are automatically converted to a minimal value of 2.
8c03ec
+``Note``: The cpu_shares parameter has a valid value range of 2-262144.
8c03ec
 
8c03ec
 ``Note``: The weight and cap parameters are defined only for the
8c03ec
 XEN_CREDIT scheduler.
8c03ec
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
8c03ec
index 9f6cdb0de8..444657c9a1 100644
8c03ec
--- a/src/conf/domain_conf.c
8c03ec
+++ b/src/conf/domain_conf.c
8c03ec
@@ -7026,6 +7026,16 @@ virDomainDefLifecycleActionValidate(const virDomainDef *def)
8c03ec
 static int
8c03ec
 virDomainDefCputuneValidate(const virDomainDef *def)
8c03ec
 {
8c03ec
+    if (def->cputune.shares > 0 &&
8c03ec
+        (def->cputune.shares < VIR_CGROUP_CPU_SHARES_MIN ||
8c03ec
+         def->cputune.shares > VIR_CGROUP_CPU_SHARES_MAX)) {
8c03ec
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
8c03ec
+                       _("Value of cputune 'shares' must be in range [%llu, %llu]"),
8c03ec
+                         VIR_CGROUP_CPU_SHARES_MIN,
8c03ec
+                         VIR_CGROUP_CPU_SHARES_MAX);
8c03ec
+        return -1;
8c03ec
+    }
8c03ec
+
8c03ec
     CPUTUNE_VALIDATE_PERIOD(period);
8c03ec
     CPUTUNE_VALIDATE_PERIOD(global_period);
8c03ec
     CPUTUNE_VALIDATE_PERIOD(emulator_period);
8c03ec
diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
8c03ec
index 1c6edea0be..938cfdfbe3 100644
8c03ec
--- a/src/util/vircgroup.h
8c03ec
+++ b/src/util/vircgroup.h
8c03ec
@@ -243,6 +243,8 @@ virCgroupGetDomainTotalCpuStats(virCgroupPtr group,
8c03ec
 int virCgroupSetCpuShares(virCgroupPtr group, unsigned long long shares);
8c03ec
 int virCgroupGetCpuShares(virCgroupPtr group, unsigned long long *shares);
8c03ec
 
8c03ec
+#define VIR_CGROUP_CPU_SHARES_MIN 2LL
8c03ec
+#define VIR_CGROUP_CPU_SHARES_MAX 262144LL
8c03ec
 #define VIR_CGROUP_CPU_PERIOD_MIN 1000LL
8c03ec
 #define VIR_CGROUP_CPU_PERIOD_MAX 1000000LL
8c03ec
 #define VIR_CGROUP_CPU_QUOTA_MIN 1000LL
8c03ec
diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
8c03ec
index 49a2cb023e..d417446447 100644
8c03ec
--- a/src/util/vircgroupv1.c
8c03ec
+++ b/src/util/vircgroupv1.c
8c03ec
@@ -1901,6 +1901,16 @@ static int
8c03ec
 virCgroupV1SetCpuShares(virCgroupPtr group,
8c03ec
                         unsigned long long shares)
8c03ec
 {
8c03ec
+    if (shares < VIR_CGROUP_CPU_SHARES_MIN ||
8c03ec
+        shares > VIR_CGROUP_CPU_SHARES_MAX) {
8c03ec
+        virReportError(VIR_ERR_INVALID_ARG,
8c03ec
+                       _("shares '%llu' must be in range [%llu, %llu]"),
8c03ec
+                       shares,
8c03ec
+                       VIR_CGROUP_CPU_SHARES_MIN,
8c03ec
+                       VIR_CGROUP_CPU_SHARES_MAX);
8c03ec
+        return -1;
8c03ec
+    }
8c03ec
+
8c03ec
     if (group->unitName) {
8c03ec
         return virCgroupSetValueDBus(group->unitName, "CPUShares",
8c03ec
                                      "t", shares);
8c03ec
diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
8c03ec
index a14fc669fb..079fe6a8ec 100644
8c03ec
--- a/src/util/vircgroupv2.c
8c03ec
+++ b/src/util/vircgroupv2.c
8c03ec
@@ -1499,6 +1499,16 @@ static int
8c03ec
 virCgroupV2SetCpuShares(virCgroupPtr group,
8c03ec
                         unsigned long long shares)
8c03ec
 {
8c03ec
+    if (shares < VIR_CGROUP_CPU_SHARES_MIN ||
8c03ec
+        shares > VIR_CGROUP_CPU_SHARES_MAX) {
8c03ec
+        virReportError(VIR_ERR_INVALID_ARG,
8c03ec
+                       _("shares '%llu' must be in range [%llu, %llu]"),
8c03ec
+                       shares,
8c03ec
+                       VIR_CGROUP_CPU_SHARES_MIN,
8c03ec
+                       VIR_CGROUP_CPU_SHARES_MAX);
8c03ec
+        return -1;
8c03ec
+    }
8c03ec
+
8c03ec
     if (group->unitName) {
8c03ec
         return virCgroupSetValueDBus(group->unitName, "CPUWeight",
8c03ec
                                      "t", shares);
8c03ec
-- 
8c03ec
2.30.0
8c03ec