]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shared/cpu-set-util: make transfer of cpu_set_t over bus endian safe
authorMichal Sekletar <msekleta@redhat.com>
Wed, 22 May 2019 11:55:49 +0000 (13:55 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 29 May 2019 14:12:23 +0000 (16:12 +0200)
src/core/dbus-execute.c
src/shared/bus-unit-util.c
src/shared/cpu-set-util.c
src/shared/cpu-set-util.h

index 326e451b9a4f03b76441886019c0a68ffbc6079f..d7d339b9d792538b762236912f91cf2154c3c685 100644 (file)
@@ -1559,18 +1559,22 @@ int bus_exec_context_set_transient_property(
         if (streq(name, "CPUAffinity")) {
                 const void *a;
                 size_t n;
+                _cleanup_(cpu_set_reset) CPUSet set = {};
 
                 r = sd_bus_message_read_array(message, 'y', &a, &n);
                 if (r < 0)
                         return r;
 
+                r = cpu_set_from_dbus(a, n, &set);
+                if (r < 0)
+                        return r;
+
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (n == 0) {
                                 cpu_set_reset(&c->cpu_set);
                                 unit_write_settingf(u, flags, name, "%s=", name);
                         } else {
                                 _cleanup_free_ char *str = NULL;
-                                const CPUSet set = {(cpu_set_t*) a, n};
 
                                 str = cpu_set_to_string(&set);
                                 if (!str)
index e4889dc55d2d8c093ec60a931346d47143a61732..fb86391975373949f986e2ff7091dc4a4fea284c 100644 (file)
@@ -993,12 +993,18 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
 
         if (streq(field, "CPUAffinity")) {
                 _cleanup_(cpu_set_reset) CPUSet cpuset = {};
+                _cleanup_free_ uint8_t *array = NULL;
+                size_t allocated;
 
                 r = parse_cpu_set(eq, &cpuset);
                 if (r < 0)
                         return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
 
-                return bus_append_byte_array(m, field, cpuset.set, cpuset.allocated);
+                r = cpu_set_to_dbus(&cpuset, &array, &allocated);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to serialize CPUAffinity: %m");
+
+                return bus_append_byte_array(m, field, array, allocated);
         }
 
         if (STR_IN_SET(field, "RestrictAddressFamilies", "SystemCallFilter")) {
index e9218a542bc007d596a4da914e273a47308d76d8..4980e1964cedea24292ce4edbfafe06d68fdd77c 100644 (file)
@@ -206,3 +206,41 @@ int cpus_in_affinity_mask(void) {
                 n *= 2;
         }
 }
+
+int cpu_set_to_dbus(const CPUSet *set, uint8_t **ret, size_t *allocated) {
+        uint8_t *out;
+
+        assert(set);
+        assert(ret);
+
+        out = new0(uint8_t, set->allocated);
+        if (!out)
+                return -ENOMEM;
+
+        for (unsigned cpu = 0; cpu < set->allocated * 8; cpu++)
+                if (CPU_ISSET_S(cpu, set->allocated, set->set))
+                        out[cpu / 8] |= 1u << (cpu % 8);
+
+        *ret = out;
+        *allocated = set->allocated;
+        return 0;
+}
+
+int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set) {
+        _cleanup_(cpu_set_reset) CPUSet s = {};
+        int r;
+
+        assert(bits);
+        assert(set);
+
+        for (unsigned cpu = size * 8; cpu > 0; cpu--)
+                if (bits[(cpu - 1) / 8] & (1u << ((cpu - 1) % 8))) {
+                        r = cpu_set_add(&s, cpu - 1);
+                        if (r < 0)
+                                return r;
+                }
+
+        *set = s;
+        s = (CPUSet) {};
+        return 0;
+}
index d1b6814bbacde84e8088cd4ee1e4c8cc47616770..f99a818c6019daa5028ad06ab820aab6f51ef75f 100644 (file)
@@ -42,4 +42,7 @@ static inline int parse_cpu_set(const char *rvalue, CPUSet *cpu_set){
         return parse_cpu_set_full(rvalue, cpu_set, false, NULL, NULL, 0, NULL);
 }
 
+int cpu_set_to_dbus(const CPUSet *set, uint8_t **ret, size_t *allocated);
+int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set);
+
 int cpus_in_affinity_mask(void);