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