Coverage Report

Created: 2019-06-19 13:33

/src/systemd/src/core/dbus-cgroup.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: LGPL-2.1+ */
2
3
#include <arpa/inet.h>
4
5
#include "af-list.h"
6
#include "alloc-util.h"
7
#include "bpf-firewall.h"
8
#include "bus-util.h"
9
#include "cgroup-util.h"
10
#include "cgroup.h"
11
#include "dbus-cgroup.h"
12
#include "dbus-util.h"
13
#include "fd-util.h"
14
#include "fileio.h"
15
#include "limits-util.h"
16
#include "path-util.h"
17
18
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
19
20
static int property_get_cgroup_mask(
21
                sd_bus *bus,
22
                const char *path,
23
                const char *interface,
24
                const char *property,
25
                sd_bus_message *reply,
26
                void *userdata,
27
0
                sd_bus_error *error) {
28
0
29
0
        CGroupMask *mask = userdata;
30
0
        CGroupController ctrl;
31
0
        int r;
32
0
33
0
        assert(bus);
34
0
        assert(reply);
35
0
36
0
        r = sd_bus_message_open_container(reply, 'a', "s");
37
0
        if (r < 0)
38
0
                return r;
39
0
40
0
        for (ctrl = 0; ctrl < _CGROUP_CONTROLLER_MAX; ctrl++) {
41
0
                if ((*mask & CGROUP_CONTROLLER_TO_MASK(ctrl)) == 0)
42
0
                        continue;
43
0
44
0
                r = sd_bus_message_append(reply, "s", cgroup_controller_to_string(ctrl));
45
0
                if (r < 0)
46
0
                        return r;
47
0
        }
48
0
49
0
        return sd_bus_message_close_container(reply);
50
0
}
51
52
static int property_get_delegate_controllers(
53
                sd_bus *bus,
54
                const char *path,
55
                const char *interface,
56
                const char *property,
57
                sd_bus_message *reply,
58
                void *userdata,
59
0
                sd_bus_error *error) {
60
0
61
0
        CGroupContext *c = userdata;
62
0
63
0
        assert(bus);
64
0
        assert(reply);
65
0
        assert(c);
66
0
67
0
        if (!c->delegate)
68
0
                return sd_bus_message_append(reply, "as", 0);
69
0
70
0
        return property_get_cgroup_mask(bus, path, interface, property, reply, &c->delegate_controllers, error);
71
0
}
72
73
static int property_get_io_device_weight(
74
                sd_bus *bus,
75
                const char *path,
76
                const char *interface,
77
                const char *property,
78
                sd_bus_message *reply,
79
                void *userdata,
80
0
                sd_bus_error *error) {
81
0
82
0
        CGroupContext *c = userdata;
83
0
        CGroupIODeviceWeight *w;
84
0
        int r;
85
0
86
0
        assert(bus);
87
0
        assert(reply);
88
0
        assert(c);
89
0
90
0
        r = sd_bus_message_open_container(reply, 'a', "(st)");
91
0
        if (r < 0)
92
0
                return r;
93
0
94
0
        LIST_FOREACH(device_weights, w, c->io_device_weights) {
95
0
                r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
96
0
                if (r < 0)
97
0
                        return r;
98
0
        }
99
0
100
0
        return sd_bus_message_close_container(reply);
101
0
}
102
103
static int property_get_io_device_limits(
104
                sd_bus *bus,
105
                const char *path,
106
                const char *interface,
107
                const char *property,
108
                sd_bus_message *reply,
109
                void *userdata,
110
0
                sd_bus_error *error) {
111
0
112
0
        CGroupContext *c = userdata;
113
0
        CGroupIODeviceLimit *l;
114
0
        int r;
115
0
116
0
        assert(bus);
117
0
        assert(reply);
118
0
        assert(c);
119
0
120
0
        r = sd_bus_message_open_container(reply, 'a', "(st)");
121
0
        if (r < 0)
122
0
                return r;
123
0
124
0
        LIST_FOREACH(device_limits, l, c->io_device_limits) {
125
0
                CGroupIOLimitType type;
126
0
127
0
                type = cgroup_io_limit_type_from_string(property);
128
0
                if (type < 0 || l->limits[type] == cgroup_io_limit_defaults[type])
129
0
                        continue;
130
0
131
0
                r = sd_bus_message_append(reply, "(st)", l->path, l->limits[type]);
132
0
                if (r < 0)
133
0
                        return r;
134
0
        }
135
0
136
0
        return sd_bus_message_close_container(reply);
137
0
}
138
139
static int property_get_io_device_latency(
140
                sd_bus *bus,
141
                const char *path,
142
                const char *interface,
143
                const char *property,
144
                sd_bus_message *reply,
145
                void *userdata,
146
0
                sd_bus_error *error) {
147
0
148
0
        CGroupContext *c = userdata;
149
0
        CGroupIODeviceLatency *l;
150
0
        int r;
151
0
152
0
        assert(bus);
153
0
        assert(reply);
154
0
        assert(c);
155
0
156
0
        r = sd_bus_message_open_container(reply, 'a', "(st)");
157
0
        if (r < 0)
158
0
                return r;
159
0
160
0
        LIST_FOREACH(device_latencies, l, c->io_device_latencies) {
161
0
                r = sd_bus_message_append(reply, "(st)", l->path, l->target_usec);
162
0
                if (r < 0)
163
0
                        return r;
164
0
        }
165
0
166
0
        return sd_bus_message_close_container(reply);
167
0
}
168
169
static int property_get_blockio_device_weight(
170
                sd_bus *bus,
171
                const char *path,
172
                const char *interface,
173
                const char *property,
174
                sd_bus_message *reply,
175
                void *userdata,
176
0
                sd_bus_error *error) {
177
0
178
0
        CGroupContext *c = userdata;
179
0
        CGroupBlockIODeviceWeight *w;
180
0
        int r;
181
0
182
0
        assert(bus);
183
0
        assert(reply);
184
0
        assert(c);
185
0
186
0
        r = sd_bus_message_open_container(reply, 'a', "(st)");
187
0
        if (r < 0)
188
0
                return r;
189
0
190
0
        LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
191
0
                r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
192
0
                if (r < 0)
193
0
                        return r;
194
0
        }
195
0
196
0
        return sd_bus_message_close_container(reply);
197
0
}
198
199
static int property_get_blockio_device_bandwidths(
200
                sd_bus *bus,
201
                const char *path,
202
                const char *interface,
203
                const char *property,
204
                sd_bus_message *reply,
205
                void *userdata,
206
0
                sd_bus_error *error) {
207
0
208
0
        CGroupContext *c = userdata;
209
0
        CGroupBlockIODeviceBandwidth *b;
210
0
        int r;
211
0
212
0
        assert(bus);
213
0
        assert(reply);
214
0
        assert(c);
215
0
216
0
        r = sd_bus_message_open_container(reply, 'a', "(st)");
217
0
        if (r < 0)
218
0
                return r;
219
0
220
0
        LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
221
0
                uint64_t v;
222
0
223
0
                if (streq(property, "BlockIOReadBandwidth"))
224
0
                        v = b->rbps;
225
0
                else
226
0
                        v = b->wbps;
227
0
228
0
                if (v == CGROUP_LIMIT_MAX)
229
0
                        continue;
230
0
231
0
                r = sd_bus_message_append(reply, "(st)", b->path, v);
232
0
                if (r < 0)
233
0
                        return r;
234
0
        }
235
0
236
0
        return sd_bus_message_close_container(reply);
237
0
}
238
239
static int property_get_device_allow(
240
                sd_bus *bus,
241
                const char *path,
242
                const char *interface,
243
                const char *property,
244
                sd_bus_message *reply,
245
                void *userdata,
246
0
                sd_bus_error *error) {
247
0
248
0
        CGroupContext *c = userdata;
249
0
        CGroupDeviceAllow *a;
250
0
        int r;
251
0
252
0
        assert(bus);
253
0
        assert(reply);
254
0
        assert(c);
255
0
256
0
        r = sd_bus_message_open_container(reply, 'a', "(ss)");
257
0
        if (r < 0)
258
0
                return r;
259
0
260
0
        LIST_FOREACH(device_allow, a, c->device_allow) {
261
0
                unsigned k = 0;
262
0
                char rwm[4];
263
0
264
0
                if (a->r)
265
0
                        rwm[k++] = 'r';
266
0
                if (a->w)
267
0
                        rwm[k++] = 'w';
268
0
                if (a->m)
269
0
                        rwm[k++] = 'm';
270
0
271
0
                rwm[k] = 0;
272
0
273
0
                r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
274
0
                if (r < 0)
275
0
                        return r;
276
0
        }
277
0
278
0
        return sd_bus_message_close_container(reply);
279
0
}
280
281
static int property_get_ip_address_access(
282
                sd_bus *bus,
283
                const char *path,
284
                const char *interface,
285
                const char *property,
286
                sd_bus_message *reply,
287
                void *userdata,
288
0
                sd_bus_error *error) {
289
0
290
0
        IPAddressAccessItem** items = userdata, *i;
291
0
        int r;
292
0
293
0
        r = sd_bus_message_open_container(reply, 'a', "(iayu)");
294
0
        if (r < 0)
295
0
                return r;
296
0
297
0
        LIST_FOREACH(items, i, *items) {
298
0
299
0
                r = sd_bus_message_open_container(reply, 'r', "iayu");
300
0
                if (r < 0)
301
0
                        return r;
302
0
303
0
                r = sd_bus_message_append(reply, "i", i->family);
304
0
                if (r < 0)
305
0
                        return r;
306
0
307
0
                r = sd_bus_message_append_array(reply, 'y', &i->address, FAMILY_ADDRESS_SIZE(i->family));
308
0
                if (r < 0)
309
0
                        return r;
310
0
311
0
                r = sd_bus_message_append(reply, "u", (uint32_t) i->prefixlen);
312
0
                if (r < 0)
313
0
                        return r;
314
0
315
0
                r = sd_bus_message_close_container(reply);
316
0
                if (r < 0)
317
0
                        return r;
318
0
        }
319
0
320
0
        return sd_bus_message_close_container(reply);
321
0
}
322
323
const sd_bus_vtable bus_cgroup_vtable[] = {
324
        SD_BUS_VTABLE_START(0),
325
        SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
326
        SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers, 0, 0),
327
        SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
328
        SD_BUS_PROPERTY("CPUWeight", "t", NULL, offsetof(CGroupContext, cpu_weight), 0),
329
        SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL, offsetof(CGroupContext, startup_cpu_weight), 0),
330
        SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0),
331
        SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0),
332
        SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
333
        SD_BUS_PROPERTY("CPUQuotaPeriodUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_period_usec), 0),
334
        SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, io_accounting), 0),
335
        SD_BUS_PROPERTY("IOWeight", "t", NULL, offsetof(CGroupContext, io_weight), 0),
336
        SD_BUS_PROPERTY("StartupIOWeight", "t", NULL, offsetof(CGroupContext, startup_io_weight), 0),
337
        SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight, 0, 0),
338
        SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
339
        SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
340
        SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
341
        SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
342
        SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency, 0, 0),
343
        SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
344
        SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0),
345
        SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0),
346
        SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
347
        SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
348
        SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
349
        SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
350
        SD_BUS_PROPERTY("DefaultMemoryLow", "t", NULL, offsetof(CGroupContext, default_memory_low), 0),
351
        SD_BUS_PROPERTY("DefaultMemoryMin", "t", NULL, offsetof(CGroupContext, default_memory_min), 0),
352
        SD_BUS_PROPERTY("MemoryMin", "t", NULL, offsetof(CGroupContext, memory_min), 0),
353
        SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0),
354
        SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0),
355
        SD_BUS_PROPERTY("MemoryMax", "t", NULL, offsetof(CGroupContext, memory_max), 0),
356
        SD_BUS_PROPERTY("MemorySwapMax", "t", NULL, offsetof(CGroupContext, memory_swap_max), 0),
357
        SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
358
        SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
359
        SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
360
        SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0),
361
        SD_BUS_PROPERTY("TasksMax", "t", NULL, offsetof(CGroupContext, tasks_max), 0),
362
        SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, ip_accounting), 0),
363
        SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_allow), 0),
364
        SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_deny), 0),
365
        SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask, offsetof(CGroupContext, disable_controllers), 0),
366
        SD_BUS_VTABLE_END
367
};
368
369
static int bus_cgroup_set_transient_property(
370
                Unit *u,
371
                CGroupContext *c,
372
                const char *name,
373
                sd_bus_message *message,
374
                UnitWriteFlags flags,
375
0
                sd_bus_error *error) {
376
0
377
0
        int r;
378
0
379
0
        assert(u);
380
0
        assert(c);
381
0
        assert(name);
382
0
        assert(message);
383
0
384
0
        flags |= UNIT_PRIVATE;
385
0
386
0
        if (streq(name, "Delegate")) {
387
0
                int b;
388
0
389
0
                if (!UNIT_VTABLE(u)->can_delegate)
390
0
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
391
0
392
0
                r = sd_bus_message_read(message, "b", &b);
393
0
                if (r < 0)
394
0
                        return r;
395
0
396
0
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
397
0
                        c->delegate = b;
398
0
                        c->delegate_controllers = b ? _CGROUP_MASK_ALL : 0;
399
0
400
0
                        unit_write_settingf(u, flags, name, "Delegate=%s", yes_no(b));
401
0
                }
402
0
403
0
                return 1;
404
0
405
0
        } else if (STR_IN_SET(name, "DelegateControllers", "DisableControllers")) {
406
0
                CGroupMask mask = 0;
407
0
408
0
                if (streq(name, "DelegateControllers") && !UNIT_VTABLE(u)->can_delegate)
409
0
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
410
0
411
0
                r = sd_bus_message_enter_container(message, 'a', "s");
412
0
                if (r < 0)
413
0
                        return r;
414
0
415
0
                for (;;) {
416
0
                        CGroupController cc;
417
0
                        const char *t;
418
0
419
0
                        r = sd_bus_message_read(message, "s", &t);
420
0
                        if (r < 0)
421
0
                                return r;
422
0
                        if (r == 0)
423
0
                                break;
424
0
425
0
                        cc = cgroup_controller_from_string(t);
426
0
                        if (cc < 0)
427
0
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown cgroup controller '%s'", t);
428
0
429
0
                        mask |= CGROUP_CONTROLLER_TO_MASK(cc);
430
0
                }
431
0
432
0
                r = sd_bus_message_exit_container(message);
433
0
                if (r < 0)
434
0
                        return r;
435
0
436
0
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
437
0
                        _cleanup_free_ char *t = NULL;
438
0
439
0
                        r = cg_mask_to_string(mask, &t);
440
0
                        if (r < 0)
441
0
                                return r;
442
0
443
0
                        if (streq(name, "DelegateControllers")) {
444
0
445
0
                                c->delegate = true;
446
0
                                if (mask == 0)
447
0
                                        c->delegate_controllers = 0;
448
0
                                else
449
0
                                        c->delegate_controllers |= mask;
450
0
451
0
                                unit_write_settingf(u, flags, name, "Delegate=%s", strempty(t));
452
0
453
0
                        } else if (streq(name, "DisableControllers")) {
454
0
455
0
                                if (mask == 0)
456
0
                                        c->disable_controllers = 0;
457
0
                                else
458
0
                                        c->disable_controllers |= mask;
459
0
460
0
                                unit_write_settingf(u, flags, name, "%s=%s", name, strempty(t));
461
0
                        }
462
0
                }
463
0
464
0
                return 1;
465
0
        }
466
0
467
0
        return 0;
468
0
}
469
470
static int bus_cgroup_set_boolean(
471
                Unit *u,
472
                const char *name,
473
                bool *p,
474
                CGroupMask mask,
475
                sd_bus_message *message,
476
                UnitWriteFlags flags,
477
0
                sd_bus_error *error) {
478
0
479
0
        int b, r;
480
0
481
0
        assert(p);
482
0
483
0
        r = sd_bus_message_read(message, "b", &b);
484
0
        if (r < 0)
485
0
                return r;
486
0
487
0
        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
488
0
                *p = b;
489
0
                unit_invalidate_cgroup(u, mask);
490
0
                unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b));
491
0
        }
492
0
493
0
        return 1;
494
0
}
495
496
#define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val)        \
497
        static int bus_cgroup_set_##function(                           \
498
                        Unit *u,                                        \
499
                        const char *name,                               \
500
                        uint64_t *p,                                    \
501
                        sd_bus_message *message,                        \
502
                        UnitWriteFlags flags,                           \
503
0
                        sd_bus_error *error) {                          \
504
0
                                                                        \
505
0
                uint64_t v;                                             \
506
0
                int r;                                                  \
507
0
                                                                        \
508
0
                assert(p);                                              \
509
0
                                                                        \
510
0
                r = sd_bus_message_read(message, "t", &v);              \
511
0
                if (r < 0)                                              \
512
0
                        return r;                                       \
513
0
                                                                        \
514
0
                if (!check(v))                                          \
515
0
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
516
0
                                                 "Value specified in %s is out of range", name); \
517
0
                                                                        \
518
0
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {                    \
519
0
                        *p = v;                                         \
520
0
                        unit_invalidate_cgroup(u, (mask));              \
521
0
                                                                        \
522
0
                        if (v == (val))                                 \
523
0
                                unit_write_settingf(u, flags, name,     \
524
0
                                                    "%s=", name);       \
525
0
                        else                                            \
526
0
                                unit_write_settingf(u, flags, name,     \
527
0
                                                    "%s=%" PRIu64, name, v); \
528
0
                }                                                       \
529
0
                                                                        \
530
0
                return 1;                                               \
531
0
        }
Unexecuted instantiation: dbus-cgroup.c:bus_cgroup_set_cpu_weight
Unexecuted instantiation: dbus-cgroup.c:bus_cgroup_set_cpu_shares
Unexecuted instantiation: dbus-cgroup.c:bus_cgroup_set_io_weight
Unexecuted instantiation: dbus-cgroup.c:bus_cgroup_set_blockio_weight
532
533
#define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum)     \
534
        static int bus_cgroup_set_##function(                           \
535
                        Unit *u,                                        \
536
                        const char *name,                               \
537
                        uint64_t *p,                                    \
538
                        sd_bus_message *message,                        \
539
                        UnitWriteFlags flags,                           \
540
0
                        sd_bus_error *error) {                          \
541
0
                                                                        \
542
0
                uint64_t v;                                             \
543
0
                int r;                                                  \
544
0
                                                                        \
545
0
                assert(p);                                              \
546
0
                                                                        \
547
0
                r = sd_bus_message_read(message, "t", &v);              \
548
0
                if (r < 0)                                              \
549
0
                        return r;                                       \
550
0
                                                                        \
551
0
                if (v < minimum)                                        \
552
0
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
553
0
                                                 "Value specified in %s is out of range", name); \
554
0
                                                                        \
555
0
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {                    \
556
0
                        *p = v;                                         \
557
0
                        unit_invalidate_cgroup(u, (mask));              \
558
0
                                                                        \
559
0
                        if (v == CGROUP_LIMIT_MAX)                      \
560
0
                                unit_write_settingf(u, flags, name,     \
561
0
                                                    "%s=infinity", name); \
562
0
                        else                                            \
563
0
                                unit_write_settingf(u, flags, name,     \
564
0
                                                    "%s=%" PRIu64, name, v); \
565
0
                }                                                       \
566
0
                                                                        \
567
0
                return 1;                                               \
568
0
        }                                                               \
Unexecuted instantiation: dbus-cgroup.c:bus_cgroup_set_memory_protection
Unexecuted instantiation: dbus-cgroup.c:bus_cgroup_set_memory
Unexecuted instantiation: dbus-cgroup.c:bus_cgroup_set_swap
Unexecuted instantiation: dbus-cgroup.c:bus_cgroup_set_tasks_max
569
        static int bus_cgroup_set_##function##_scale(                   \
570
                        Unit *u,                                        \
571
                        const char *name,                               \
572
                        uint64_t *p,                                    \
573
                        sd_bus_message *message,                        \
574
                        UnitWriteFlags flags,                           \
575
0
                        sd_bus_error *error) {                          \
576
0
                                                                        \
577
0
                uint64_t v;                                             \
578
0
                uint32_t raw;                                           \
579
0
                int r;                                                  \
580
0
                                                                        \
581
0
                assert(p);                                              \
582
0
                                                                        \
583
0
                r = sd_bus_message_read(message, "u", &raw);            \
584
0
                if (r < 0)                                              \
585
0
                        return r;                                       \
586
0
                                                                        \
587
0
                v = scale(raw, UINT32_MAX);                             \
588
0
                if (v < minimum || v >= UINT64_MAX)                     \
589
0
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
590
0
                                                 "Value specified in %s is out of range", name); \
591
0
                                                                        \
592
0
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {                    \
593
0
                        const char *e;                                  \
594
0
                                                                        \
595
0
                        *p = v;                                         \
596
0
                        unit_invalidate_cgroup(u, (mask));              \
597
0
                                                                        \
598
0
                        /* Chop off suffix */                           \
599
0
                        assert_se(e = endswith(name, "Scale"));         \
600
0
                        name = strndupa(name, e - name);                \
601
0
                                                                        \
602
0
                        unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name, \
603
0
                                            (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); \
604
0
                }                                                       \
605
0
                                                                        \
606
0
                return 1;                                               \
607
0
        }
Unexecuted instantiation: dbus-cgroup.c:bus_cgroup_set_memory_protection_scale
Unexecuted instantiation: dbus-cgroup.c:bus_cgroup_set_memory_scale
Unexecuted instantiation: dbus-cgroup.c:bus_cgroup_set_swap_scale
Unexecuted instantiation: dbus-cgroup.c:bus_cgroup_set_tasks_max_scale
608
609
#pragma GCC diagnostic push
610
#pragma GCC diagnostic ignored "-Wtype-limits"
611
BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight, CGROUP_MASK_CPU, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
612
BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_OK, CGROUP_CPU_SHARES_INVALID);
613
BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight, CGROUP_MASK_IO, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
614
BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEIGHT_IS_OK, CGROUP_BLKIO_WEIGHT_INVALID);
615
BUS_DEFINE_SET_CGROUP_LIMIT(memory, CGROUP_MASK_MEMORY, physical_memory_scale, 1);
616
BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
617
BUS_DEFINE_SET_CGROUP_LIMIT(swap, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
618
BUS_DEFINE_SET_CGROUP_LIMIT(tasks_max, CGROUP_MASK_PIDS, system_tasks_max_scale, 1);
619
#pragma GCC diagnostic pop
620
621
int bus_cgroup_set_property(
622
                Unit *u,
623
                CGroupContext *c,
624
                const char *name,
625
                sd_bus_message *message,
626
                UnitWriteFlags flags,
627
                sd_bus_error *error) {
628
629
        CGroupIOLimitType iol_type;
630
        int r;
631
632
        assert(u);
633
        assert(c);
634
        assert(name);
635
        assert(message);
636
637
        flags |= UNIT_PRIVATE;
638
639
        if (streq(name, "CPUAccounting"))
640
                return bus_cgroup_set_boolean(u, name, &c->cpu_accounting, get_cpu_accounting_mask(), message, flags, error);
641
642
        if (streq(name, "CPUWeight"))
643
                return bus_cgroup_set_cpu_weight(u, name, &c->cpu_weight, message, flags, error);
644
645
        if (streq(name, "StartupCPUWeight"))
646
                return bus_cgroup_set_cpu_weight(u, name, &c->startup_cpu_weight, message, flags, error);
647
648
        if (streq(name, "CPUShares"))
649
                return bus_cgroup_set_cpu_shares(u, name, &c->cpu_shares, message, flags, error);
650
651
        if (streq(name, "StartupCPUShares"))
652
                return bus_cgroup_set_cpu_shares(u, name, &c->startup_cpu_shares, message, flags, error);
653
654
        if (streq(name, "IOAccounting"))
655
                return bus_cgroup_set_boolean(u, name, &c->io_accounting, CGROUP_MASK_IO, message, flags, error);
656
657
        if (streq(name, "IOWeight"))
658
                return bus_cgroup_set_io_weight(u, name, &c->io_weight, message, flags, error);
659
660
        if (streq(name, "StartupIOWeight"))
661
                return bus_cgroup_set_io_weight(u, name, &c->startup_io_weight, message, flags, error);
662
663
        if (streq(name, "BlockIOAccounting"))
664
                return bus_cgroup_set_boolean(u, name, &c->blockio_accounting, CGROUP_MASK_BLKIO, message, flags, error);
665
666
        if (streq(name, "BlockIOWeight"))
667
                return bus_cgroup_set_blockio_weight(u, name, &c->blockio_weight, message, flags, error);
668
669
        if (streq(name, "StartupBlockIOWeight"))
670
                return bus_cgroup_set_blockio_weight(u, name, &c->startup_blockio_weight, message, flags, error);
671
672
        if (streq(name, "MemoryAccounting"))
673
                return bus_cgroup_set_boolean(u, name, &c->memory_accounting, CGROUP_MASK_MEMORY, message, flags, error);
674
675
        if (streq(name, "MemoryMin"))
676
                return bus_cgroup_set_memory_protection(u, name, &c->memory_min, message, flags, error);
677
678
        if (streq(name, "MemoryLow"))
679
                return bus_cgroup_set_memory_protection(u, name, &c->memory_low, message, flags, error);
680
681
        if (streq(name, "DefaultMemoryMin"))
682
                return bus_cgroup_set_memory_protection(u, name, &c->default_memory_min, message, flags, error);
683
684
        if (streq(name, "DefaultMemoryLow"))
685
                return bus_cgroup_set_memory_protection(u, name, &c->default_memory_low, message, flags, error);
686
687
        if (streq(name, "MemoryHigh"))
688
                return bus_cgroup_set_memory(u, name, &c->memory_high, message, flags, error);
689
690
        if (streq(name, "MemorySwapMax"))
691
                return bus_cgroup_set_swap(u, name, &c->memory_swap_max, message, flags, error);
692
693
        if (streq(name, "MemoryMax"))
694
                return bus_cgroup_set_memory(u, name, &c->memory_max, message, flags, error);
695
696
        if (streq(name, "MemoryLimit"))
697
                return bus_cgroup_set_memory(u, name, &c->memory_limit, message, flags, error);
698
699
        if (streq(name, "MemoryMinScale"))
700
                return bus_cgroup_set_memory_protection_scale(u, name, &c->memory_min, message, flags, error);
701
702
        if (streq(name, "MemoryLowScale"))
703
                return bus_cgroup_set_memory_protection_scale(u, name, &c->memory_low, message, flags, error);
704
705
        if (streq(name, "DefaultMemoryMinScale"))
706
                return bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_min, message, flags, error);
707
708
        if (streq(name, "DefaultMemoryLowScale"))
709
                return bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_low, message, flags, error);
710
711
        if (streq(name, "MemoryHighScale"))
712
                return bus_cgroup_set_memory_scale(u, name, &c->memory_high, message, flags, error);
713
714
        if (streq(name, "MemorySwapMaxScale"))
715
                return bus_cgroup_set_swap_scale(u, name, &c->memory_swap_max, message, flags, error);
716
717
        if (streq(name, "MemoryMaxScale"))
718
                return bus_cgroup_set_memory_scale(u, name, &c->memory_max, message, flags, error);
719
720
        if (streq(name, "MemoryLimitScale"))
721
                return bus_cgroup_set_memory_scale(u, name, &c->memory_limit, message, flags, error);
722
723
        if (streq(name, "TasksAccounting"))
724
                return bus_cgroup_set_boolean(u, name, &c->tasks_accounting, CGROUP_MASK_PIDS, message, flags, error);
725
726
        if (streq(name, "TasksMax"))
727
                return bus_cgroup_set_tasks_max(u, name, &c->tasks_max, message, flags, error);
728
729
        if (streq(name, "TasksMaxScale"))
730
                return bus_cgroup_set_tasks_max_scale(u, name, &c->tasks_max, message, flags, error);
731
732
        if (streq(name, "CPUQuotaPerSecUSec")) {
733
                uint64_t u64;
734
735
                r = sd_bus_message_read(message, "t", &u64);
736
                if (r < 0)
737
                        return r;
738
739
                if (u64 <= 0)
740
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "CPUQuotaPerSecUSec= value out of range");
741
742
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
743
                        c->cpu_quota_per_sec_usec = u64;
744
                        u->warned_clamping_cpu_quota_period = false;
745
                        unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
746
747
                        if (c->cpu_quota_per_sec_usec == USEC_INFINITY)
748
                                unit_write_setting(u, flags, "CPUQuota", "CPUQuota=");
749
                        else
750
                                /* config_parse_cpu_quota() requires an integer, so truncating division is used on
751
                                 * purpose here. */
752
                                unit_write_settingf(u, flags, "CPUQuota",
753
                                                    "CPUQuota=%0.f%%",
754
                                                    (double) (c->cpu_quota_per_sec_usec / 10000));
755
                }
756
757
                return 1;
758
759
        } else if (streq(name, "CPUQuotaPeriodUSec")) {
760
                uint64_t u64;
761
762
                r = sd_bus_message_read(message, "t", &u64);
763
                if (r < 0)
764
                        return r;
765
766
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
767
                        c->cpu_quota_period_usec = u64;
768
                        u->warned_clamping_cpu_quota_period = false;
769
                        unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
770
                        if (c->cpu_quota_period_usec == USEC_INFINITY)
771
                                unit_write_setting(u, flags, "CPUQuotaPeriodSec", "CPUQuotaPeriodSec=");
772
                        else {
773
                                char v[FORMAT_TIMESPAN_MAX];
774
                                unit_write_settingf(u, flags, "CPUQuotaPeriodSec",
775
                                                    "CPUQuotaPeriodSec=%s",
776
                                                    format_timespan(v, sizeof(v), c->cpu_quota_period_usec, 1));
777
                        }
778
                }
779
780
                return 1;
781
782
        } else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) {
783
                const char *path;
784
                unsigned n = 0;
785
                uint64_t u64;
786
787
                r = sd_bus_message_enter_container(message, 'a', "(st)");
788
                if (r < 0)
789
                        return r;
790
791
                while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
792
793
                        if (!path_is_normalized(path))
794
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
795
796
                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
797
                                CGroupIODeviceLimit *a = NULL, *b;
798
799
                                LIST_FOREACH(device_limits, b, c->io_device_limits) {
800
                                        if (path_equal(path, b->path)) {
801
                                                a = b;
802
                                                break;
803
                                        }
804
                                }
805
806
                                if (!a) {
807
                                        CGroupIOLimitType type;
808
809
                                        a = new0(CGroupIODeviceLimit, 1);
810
                                        if (!a)
811
                                                return -ENOMEM;
812
813
                                        a->path = strdup(path);
814
                                        if (!a->path) {
815
                                                free(a);
816
                                                return -ENOMEM;
817
                                        }
818
819
                                        for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
820
                                                a->limits[type] = cgroup_io_limit_defaults[type];
821
822
                                        LIST_PREPEND(device_limits, c->io_device_limits, a);
823
                                }
824
825
                                a->limits[iol_type] = u64;
826
                        }
827
828
                        n++;
829
                }
830
                if (r < 0)
831
                        return r;
832
833
                r = sd_bus_message_exit_container(message);
834
                if (r < 0)
835
                        return r;
836
837
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
838
                        CGroupIODeviceLimit *a;
839
                        _cleanup_free_ char *buf = NULL;
840
                        _cleanup_fclose_ FILE *f = NULL;
841
                        size_t size = 0;
842
843
                        if (n == 0) {
844
                                LIST_FOREACH(device_limits, a, c->io_device_limits)
845
                                        a->limits[iol_type] = cgroup_io_limit_defaults[iol_type];
846
                        }
847
848
                        unit_invalidate_cgroup(u, CGROUP_MASK_IO);
849
850
                        f = open_memstream_unlocked(&buf, &size);
851
                        if (!f)
852
                                return -ENOMEM;
853
854
                        fprintf(f, "%s=\n", name);
855
                        LIST_FOREACH(device_limits, a, c->io_device_limits)
856
                                        if (a->limits[iol_type] != cgroup_io_limit_defaults[iol_type])
857
                                                fprintf(f, "%s=%s %" PRIu64 "\n", name, a->path, a->limits[iol_type]);
858
859
                        r = fflush_and_check(f);
860
                        if (r < 0)
861
                                return r;
862
                        unit_write_setting(u, flags, name, buf);
863
                }
864
865
                return 1;
866
867
        } else if (streq(name, "IODeviceWeight")) {
868
                const char *path;
869
                uint64_t weight;
870
                unsigned n = 0;
871
872
                r = sd_bus_message_enter_container(message, 'a', "(st)");
873
                if (r < 0)
874
                        return r;
875
876
                while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
877
878
                        if (!path_is_normalized(path))
879
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
880
881
                        if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID)
882
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IODeviceWeight= value out of range");
883
884
                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
885
                                CGroupIODeviceWeight *a = NULL, *b;
886
887
                                LIST_FOREACH(device_weights, b, c->io_device_weights) {
888
                                        if (path_equal(b->path, path)) {
889
                                                a = b;
890
                                                break;
891
                                        }
892
                                }
893
894
                                if (!a) {
895
                                        a = new0(CGroupIODeviceWeight, 1);
896
                                        if (!a)
897
                                                return -ENOMEM;
898
899
                                        a->path = strdup(path);
900
                                        if (!a->path) {
901
                                                free(a);
902
                                                return -ENOMEM;
903
                                        }
904
                                        LIST_PREPEND(device_weights, c->io_device_weights, a);
905
                                }
906
907
                                a->weight = weight;
908
                        }
909
910
                        n++;
911
                }
912
913
                r = sd_bus_message_exit_container(message);
914
                if (r < 0)
915
                        return r;
916
917
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
918
                        _cleanup_free_ char *buf = NULL;
919
                        _cleanup_fclose_ FILE *f = NULL;
920
                        CGroupIODeviceWeight *a;
921
                        size_t size = 0;
922
923
                        if (n == 0) {
924
                                while (c->io_device_weights)
925
                                        cgroup_context_free_io_device_weight(c, c->io_device_weights);
926
                        }
927
928
                        unit_invalidate_cgroup(u, CGROUP_MASK_IO);
929
930
                        f = open_memstream_unlocked(&buf, &size);
931
                        if (!f)
932
                                return -ENOMEM;
933
934
                        fputs("IODeviceWeight=\n", f);
935
                        LIST_FOREACH(device_weights, a, c->io_device_weights)
936
                                fprintf(f, "IODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
937
938
                        r = fflush_and_check(f);
939
                        if (r < 0)
940
                                return r;
941
                        unit_write_setting(u, flags, name, buf);
942
                }
943
944
                return 1;
945
946
        } else if (streq(name, "IODeviceLatencyTargetUSec")) {
947
                const char *path;
948
                uint64_t target;
949
                unsigned n = 0;
950
951
                r = sd_bus_message_enter_container(message, 'a', "(st)");
952
                if (r < 0)
953
                        return r;
954
955
                while ((r = sd_bus_message_read(message, "(st)", &path, &target)) > 0) {
956
957
                        if (!path_is_normalized(path))
958
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
959
960
                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
961
                                CGroupIODeviceLatency *a = NULL, *b;
962
963
                                LIST_FOREACH(device_latencies, b, c->io_device_latencies) {
964
                                        if (path_equal(b->path, path)) {
965
                                                a = b;
966
                                                break;
967
                                        }
968
                                }
969
970
                                if (!a) {
971
                                        a = new0(CGroupIODeviceLatency, 1);
972
                                        if (!a)
973
                                                return -ENOMEM;
974
975
                                        a->path = strdup(path);
976
                                        if (!a->path) {
977
                                                free(a);
978
                                                return -ENOMEM;
979
                                        }
980
                                        LIST_PREPEND(device_latencies, c->io_device_latencies, a);
981
                                }
982
983
                                a->target_usec = target;
984
                        }
985
986
                        n++;
987
                }
988
989
                r = sd_bus_message_exit_container(message);
990
                if (r < 0)
991
                        return r;
992
993
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
994
                        _cleanup_free_ char *buf = NULL;
995
                        _cleanup_fclose_ FILE *f = NULL;
996
                        char ts[FORMAT_TIMESPAN_MAX];
997
                        CGroupIODeviceLatency *a;
998
                        size_t size = 0;
999
1000
                        if (n == 0) {
1001
                                while (c->io_device_latencies)
1002
                                        cgroup_context_free_io_device_latency(c, c->io_device_latencies);
1003
                        }
1004
1005
                        unit_invalidate_cgroup(u, CGROUP_MASK_IO);
1006
1007
                        f = open_memstream_unlocked(&buf, &size);
1008
                        if (!f)
1009
                                return -ENOMEM;
1010
1011
                        fputs("IODeviceLatencyTargetSec=\n", f);
1012
                        LIST_FOREACH(device_latencies, a, c->io_device_latencies)
1013
                                fprintf(f, "IODeviceLatencyTargetSec=%s %s\n",
1014
                                        a->path, format_timespan(ts, sizeof(ts), a->target_usec, 1));
1015
1016
                        r = fflush_and_check(f);
1017
                        if (r < 0)
1018
                                return r;
1019
                        unit_write_setting(u, flags, name, buf);
1020
                }
1021
1022
                return 1;
1023
1024
        } else if (STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1025
                const char *path;
1026
                bool read = true;
1027
                unsigned n = 0;
1028
                uint64_t u64;
1029
1030
                if (streq(name, "BlockIOWriteBandwidth"))
1031
                        read = false;
1032
1033
                r = sd_bus_message_enter_container(message, 'a', "(st)");
1034
                if (r < 0)
1035
                        return r;
1036
1037
                while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
1038
1039
                        if (!path_is_normalized(path))
1040
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
1041
1042
                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1043
                                CGroupBlockIODeviceBandwidth *a = NULL, *b;
1044
1045
                                LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
1046
                                        if (path_equal(path, b->path)) {
1047
                                                a = b;
1048
                                                break;
1049
                                        }
1050
                                }
1051
1052
                                if (!a) {
1053
                                        a = new0(CGroupBlockIODeviceBandwidth, 1);
1054
                                        if (!a)
1055
                                                return -ENOMEM;
1056
1057
                                        a->rbps = CGROUP_LIMIT_MAX;
1058
                                        a->wbps = CGROUP_LIMIT_MAX;
1059
                                        a->path = strdup(path);
1060
                                        if (!a->path) {
1061
                                                free(a);
1062
                                                return -ENOMEM;
1063
                                        }
1064
1065
                                        LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
1066
                                }
1067
1068
                                if (read)
1069
                                        a->rbps = u64;
1070
                                else
1071
                                        a->wbps = u64;
1072
                        }
1073
1074
                        n++;
1075
                }
1076
                if (r < 0)
1077
                        return r;
1078
1079
                r = sd_bus_message_exit_container(message);
1080
                if (r < 0)
1081
                        return r;
1082
1083
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1084
                        CGroupBlockIODeviceBandwidth *a;
1085
                        _cleanup_free_ char *buf = NULL;
1086
                        _cleanup_fclose_ FILE *f = NULL;
1087
                        size_t size = 0;
1088
1089
                        if (n == 0) {
1090
                                LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) {
1091
                                        if (read)
1092
                                                a->rbps = CGROUP_LIMIT_MAX;
1093
                                        else
1094
                                                a->wbps = CGROUP_LIMIT_MAX;
1095
                                }
1096
                        }
1097
1098
                        unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
1099
1100
                        f = open_memstream_unlocked(&buf, &size);
1101
                        if (!f)
1102
                                return -ENOMEM;
1103
1104
                        if (read) {
1105
                                fputs("BlockIOReadBandwidth=\n", f);
1106
                                LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
1107
                                        if (a->rbps != CGROUP_LIMIT_MAX)
1108
                                                fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->rbps);
1109
                        } else {
1110
                                fputs("BlockIOWriteBandwidth=\n", f);
1111
                                LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
1112
                                        if (a->wbps != CGROUP_LIMIT_MAX)
1113
                                                fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->wbps);
1114
                        }
1115
1116
                        r = fflush_and_check(f);
1117
                        if (r < 0)
1118
                                return r;
1119
1120
                        unit_write_setting(u, flags, name, buf);
1121
                }
1122
1123
                return 1;
1124
1125
        } else if (streq(name, "BlockIODeviceWeight")) {
1126
                const char *path;
1127
                uint64_t weight;
1128
                unsigned n = 0;
1129
1130
                r = sd_bus_message_enter_container(message, 'a', "(st)");
1131
                if (r < 0)
1132
                        return r;
1133
1134
                while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
1135
1136
                        if (!path_is_normalized(path))
1137
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
1138
1139
                        if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
1140
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIODeviceWeight= out of range");
1141
1142
                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1143
                                CGroupBlockIODeviceWeight *a = NULL, *b;
1144
1145
                                LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
1146
                                        if (path_equal(b->path, path)) {
1147
                                                a = b;
1148
                                                break;
1149
                                        }
1150
                                }
1151
1152
                                if (!a) {
1153
                                        a = new0(CGroupBlockIODeviceWeight, 1);
1154
                                        if (!a)
1155
                                                return -ENOMEM;
1156
1157
                                        a->path = strdup(path);
1158
                                        if (!a->path) {
1159
                                                free(a);
1160
                                                return -ENOMEM;
1161
                                        }
1162
                                        LIST_PREPEND(device_weights, c->blockio_device_weights, a);
1163
                                }
1164
1165
                                a->weight = weight;
1166
                        }
1167
1168
                        n++;
1169
                }
1170
1171
                r = sd_bus_message_exit_container(message);
1172
                if (r < 0)
1173
                        return r;
1174
1175
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1176
                        _cleanup_free_ char *buf = NULL;
1177
                        _cleanup_fclose_ FILE *f = NULL;
1178
                        CGroupBlockIODeviceWeight *a;
1179
                        size_t size = 0;
1180
1181
                        if (n == 0) {
1182
                                while (c->blockio_device_weights)
1183
                                        cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
1184
                        }
1185
1186
                        unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
1187
1188
                        f = open_memstream_unlocked(&buf, &size);
1189
                        if (!f)
1190
                                return -ENOMEM;
1191
1192
                        fputs("BlockIODeviceWeight=\n", f);
1193
                        LIST_FOREACH(device_weights, a, c->blockio_device_weights)
1194
                                fprintf(f, "BlockIODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
1195
1196
                        r = fflush_and_check(f);
1197
                        if (r < 0)
1198
                                return r;
1199
1200
                        unit_write_setting(u, flags, name, buf);
1201
                }
1202
1203
                return 1;
1204
1205
        } else if (streq(name, "DevicePolicy")) {
1206
                const char *policy;
1207
                CGroupDevicePolicy p;
1208
1209
                r = sd_bus_message_read(message, "s", &policy);
1210
                if (r < 0)
1211
                        return r;
1212
1213
                p = cgroup_device_policy_from_string(policy);
1214
                if (p < 0)
1215
                        return -EINVAL;
1216
1217
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1218
                        c->device_policy = p;
1219
                        unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
1220
                        unit_write_settingf(u, flags, name, "DevicePolicy=%s", policy);
1221
                }
1222
1223
                return 1;
1224
1225
        } else if (streq(name, "DeviceAllow")) {
1226
                const char *path, *rwm;
1227
                unsigned n = 0;
1228
1229
                r = sd_bus_message_enter_container(message, 'a', "(ss)");
1230
                if (r < 0)
1231
                        return r;
1232
1233
                while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
1234
1235
                        if (!valid_device_allow_pattern(path) || strpbrk(path, WHITESPACE))
1236
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node or pattern");
1237
1238
                        if (isempty(rwm))
1239
                                rwm = "rwm";
1240
                        else if (!in_charset(rwm, "rwm"))
1241
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
1242
1243
                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1244
                                CGroupDeviceAllow *a = NULL, *b;
1245
1246
                                LIST_FOREACH(device_allow, b, c->device_allow) {
1247
                                        if (path_equal(b->path, path)) {
1248
                                                a = b;
1249
                                                break;
1250
                                        }
1251
                                }
1252
1253
                                if (!a) {
1254
                                        a = new0(CGroupDeviceAllow, 1);
1255
                                        if (!a)
1256
                                                return -ENOMEM;
1257
1258
                                        a->path = strdup(path);
1259
                                        if (!a->path) {
1260
                                                free(a);
1261
                                                return -ENOMEM;
1262
                                        }
1263
1264
                                        LIST_PREPEND(device_allow, c->device_allow, a);
1265
                                }
1266
1267
                                a->r = !!strchr(rwm, 'r');
1268
                                a->w = !!strchr(rwm, 'w');
1269
                                a->m = !!strchr(rwm, 'm');
1270
                        }
1271
1272
                        n++;
1273
                }
1274
                if (r < 0)
1275
                        return r;
1276
1277
                r = sd_bus_message_exit_container(message);
1278
                if (r < 0)
1279
                        return r;
1280
1281
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1282
                        _cleanup_free_ char *buf = NULL;
1283
                        _cleanup_fclose_ FILE *f = NULL;
1284
                        CGroupDeviceAllow *a;
1285
                        size_t size = 0;
1286
1287
                        if (n == 0) {
1288
                                while (c->device_allow)
1289
                                        cgroup_context_free_device_allow(c, c->device_allow);
1290
                        }
1291
1292
                        unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
1293
1294
                        f = open_memstream_unlocked(&buf, &size);
1295
                        if (!f)
1296
                                return -ENOMEM;
1297
1298
                        fputs("DeviceAllow=\n", f);
1299
                        LIST_FOREACH(device_allow, a, c->device_allow)
1300
                                fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
1301
1302
                        r = fflush_and_check(f);
1303
                        if (r < 0)
1304
                                return r;
1305
                        unit_write_setting(u, flags, name, buf);
1306
                }
1307
1308
                return 1;
1309
1310
        } else if (streq(name, "IPAccounting")) {
1311
                int b;
1312
1313
                r = sd_bus_message_read(message, "b", &b);
1314
                if (r < 0)
1315
                        return r;
1316
1317
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1318
                        c->ip_accounting = b;
1319
1320
                        unit_invalidate_cgroup_bpf(u);
1321
                        unit_write_settingf(u, flags, name, "IPAccounting=%s", yes_no(b));
1322
                }
1323
1324
                return 1;
1325
1326
        } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
1327
                IPAddressAccessItem **list;
1328
                size_t n = 0;
1329
1330
                list = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny;
1331
1332
                r = sd_bus_message_enter_container(message, 'a', "(iayu)");
1333
                if (r < 0)
1334
                        return r;
1335
1336
                for (;;) {
1337
                        const void *ap;
1338
                        int32_t family;
1339
                        uint32_t prefixlen;
1340
                        size_t an;
1341
1342
                        r = sd_bus_message_enter_container(message, 'r', "iayu");
1343
                        if (r < 0)
1344
                                return r;
1345
                        if (r == 0)
1346
                                break;
1347
1348
                        r = sd_bus_message_read(message, "i", &family);
1349
                        if (r < 0)
1350
                                return r;
1351
1352
                        if (!IN_SET(family, AF_INET, AF_INET6))
1353
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects IPv4 or IPv6 addresses only.", name);
1354
1355
                        r = sd_bus_message_read_array(message, 'y', &ap, &an);
1356
                        if (r < 0)
1357
                                return r;
1358
1359
                        if (an != FAMILY_ADDRESS_SIZE(family))
1360
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1361
                                                               af_to_name(family), FAMILY_ADDRESS_SIZE(family), an);
1362
1363
                        r = sd_bus_message_read(message, "u", &prefixlen);
1364
                        if (r < 0)
1365
                                return r;
1366
1367
                        if (prefixlen > FAMILY_ADDRESS_SIZE(family)*8)
1368
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Prefix length %" PRIu32 " too large for address family %s.", prefixlen, af_to_name(family));
1369
1370
                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1371
                                IPAddressAccessItem *item;
1372
1373
                                item = new0(IPAddressAccessItem, 1);
1374
                                if (!item)
1375
                                        return -ENOMEM;
1376
1377
                                item->family = family;
1378
                                item->prefixlen = prefixlen;
1379
                                memcpy(&item->address, ap, an);
1380
1381
                                LIST_PREPEND(items, *list, item);
1382
                        }
1383
1384
                        r = sd_bus_message_exit_container(message);
1385
                        if (r < 0)
1386
                                return r;
1387
1388
                        n++;
1389
                }
1390
1391
                r = sd_bus_message_exit_container(message);
1392
                if (r < 0)
1393
                        return r;
1394
1395
                *list = ip_address_access_reduce(*list);
1396
1397
                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1398
                        _cleanup_free_ char *buf = NULL;
1399
                        _cleanup_fclose_ FILE *f = NULL;
1400
                        IPAddressAccessItem *item;
1401
                        size_t size = 0;
1402
1403
                        if (n == 0)
1404
                                *list = ip_address_access_free_all(*list);
1405
1406
                        unit_invalidate_cgroup_bpf(u);
1407
                        f = open_memstream_unlocked(&buf, &size);
1408
                        if (!f)
1409
                                return -ENOMEM;
1410
1411
                        fputs(name, f);
1412
                        fputs("=\n", f);
1413
1414
                        LIST_FOREACH(items, item, *list) {
1415
                                char buffer[CONST_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
1416
1417
                                errno = 0;
1418
                                if (!inet_ntop(item->family, &item->address, buffer, sizeof(buffer)))
1419
                                        return errno > 0 ? -errno : -EINVAL;
1420
1421
                                fprintf(f, "%s=%s/%u\n", name, buffer, item->prefixlen);
1422
                        }
1423
1424
                        r = fflush_and_check(f);
1425
                        if (r < 0)
1426
                                return r;
1427
1428
                        unit_write_setting(u, flags, name, buf);
1429
                }
1430
1431
                return 1;
1432
        }
1433
1434
        if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB))
1435
                return bus_cgroup_set_transient_property(u, c, name, message, flags, error);
1436
1437
        return 0;
1438
}