]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-cgroup.c
Merge pull request #12510 from keszybz/test-directives
[thirdparty/systemd.git] / src / core / dbus-cgroup.c
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 sd_bus_error *error) {
28
29 CGroupMask *mask = userdata;
30 CGroupController ctrl;
31 int r;
32
33 assert(bus);
34 assert(reply);
35
36 r = sd_bus_message_open_container(reply, 'a', "s");
37 if (r < 0)
38 return r;
39
40 for (ctrl = 0; ctrl < _CGROUP_CONTROLLER_MAX; ctrl++) {
41 if ((*mask & CGROUP_CONTROLLER_TO_MASK(ctrl)) == 0)
42 continue;
43
44 r = sd_bus_message_append(reply, "s", cgroup_controller_to_string(ctrl));
45 if (r < 0)
46 return r;
47 }
48
49 return sd_bus_message_close_container(reply);
50 }
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 sd_bus_error *error) {
60
61 CGroupContext *c = userdata;
62
63 assert(bus);
64 assert(reply);
65 assert(c);
66
67 if (!c->delegate)
68 return sd_bus_message_append(reply, "as", 0);
69
70 return property_get_cgroup_mask(bus, path, interface, property, reply, &c->delegate_controllers, error);
71 }
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 sd_bus_error *error) {
81
82 CGroupContext *c = userdata;
83 CGroupIODeviceWeight *w;
84 int r;
85
86 assert(bus);
87 assert(reply);
88 assert(c);
89
90 r = sd_bus_message_open_container(reply, 'a', "(st)");
91 if (r < 0)
92 return r;
93
94 LIST_FOREACH(device_weights, w, c->io_device_weights) {
95 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
96 if (r < 0)
97 return r;
98 }
99
100 return sd_bus_message_close_container(reply);
101 }
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 sd_bus_error *error) {
111
112 CGroupContext *c = userdata;
113 CGroupIODeviceLimit *l;
114 int r;
115
116 assert(bus);
117 assert(reply);
118 assert(c);
119
120 r = sd_bus_message_open_container(reply, 'a', "(st)");
121 if (r < 0)
122 return r;
123
124 LIST_FOREACH(device_limits, l, c->io_device_limits) {
125 CGroupIOLimitType type;
126
127 type = cgroup_io_limit_type_from_string(property);
128 if (type < 0 || l->limits[type] == cgroup_io_limit_defaults[type])
129 continue;
130
131 r = sd_bus_message_append(reply, "(st)", l->path, l->limits[type]);
132 if (r < 0)
133 return r;
134 }
135
136 return sd_bus_message_close_container(reply);
137 }
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 sd_bus_error *error) {
147
148 CGroupContext *c = userdata;
149 CGroupIODeviceLatency *l;
150 int r;
151
152 assert(bus);
153 assert(reply);
154 assert(c);
155
156 r = sd_bus_message_open_container(reply, 'a', "(st)");
157 if (r < 0)
158 return r;
159
160 LIST_FOREACH(device_latencies, l, c->io_device_latencies) {
161 r = sd_bus_message_append(reply, "(st)", l->path, l->target_usec);
162 if (r < 0)
163 return r;
164 }
165
166 return sd_bus_message_close_container(reply);
167 }
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 sd_bus_error *error) {
177
178 CGroupContext *c = userdata;
179 CGroupBlockIODeviceWeight *w;
180 int r;
181
182 assert(bus);
183 assert(reply);
184 assert(c);
185
186 r = sd_bus_message_open_container(reply, 'a', "(st)");
187 if (r < 0)
188 return r;
189
190 LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
191 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
192 if (r < 0)
193 return r;
194 }
195
196 return sd_bus_message_close_container(reply);
197 }
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 sd_bus_error *error) {
207
208 CGroupContext *c = userdata;
209 CGroupBlockIODeviceBandwidth *b;
210 int r;
211
212 assert(bus);
213 assert(reply);
214 assert(c);
215
216 r = sd_bus_message_open_container(reply, 'a', "(st)");
217 if (r < 0)
218 return r;
219
220 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
221 uint64_t v;
222
223 if (streq(property, "BlockIOReadBandwidth"))
224 v = b->rbps;
225 else
226 v = b->wbps;
227
228 if (v == CGROUP_LIMIT_MAX)
229 continue;
230
231 r = sd_bus_message_append(reply, "(st)", b->path, v);
232 if (r < 0)
233 return r;
234 }
235
236 return sd_bus_message_close_container(reply);
237 }
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 sd_bus_error *error) {
247
248 CGroupContext *c = userdata;
249 CGroupDeviceAllow *a;
250 int r;
251
252 assert(bus);
253 assert(reply);
254 assert(c);
255
256 r = sd_bus_message_open_container(reply, 'a', "(ss)");
257 if (r < 0)
258 return r;
259
260 LIST_FOREACH(device_allow, a, c->device_allow) {
261 unsigned k = 0;
262 char rwm[4];
263
264 if (a->r)
265 rwm[k++] = 'r';
266 if (a->w)
267 rwm[k++] = 'w';
268 if (a->m)
269 rwm[k++] = 'm';
270
271 rwm[k] = 0;
272
273 r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
274 if (r < 0)
275 return r;
276 }
277
278 return sd_bus_message_close_container(reply);
279 }
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 sd_bus_error *error) {
289
290 IPAddressAccessItem** items = userdata, *i;
291 int r;
292
293 r = sd_bus_message_open_container(reply, 'a', "(iayu)");
294 if (r < 0)
295 return r;
296
297 LIST_FOREACH(items, i, *items) {
298
299 r = sd_bus_message_open_container(reply, 'r', "iayu");
300 if (r < 0)
301 return r;
302
303 r = sd_bus_message_append(reply, "i", i->family);
304 if (r < 0)
305 return r;
306
307 r = sd_bus_message_append_array(reply, 'y', &i->address, FAMILY_ADDRESS_SIZE(i->family));
308 if (r < 0)
309 return r;
310
311 r = sd_bus_message_append(reply, "u", (uint32_t) i->prefixlen);
312 if (r < 0)
313 return r;
314
315 r = sd_bus_message_close_container(reply);
316 if (r < 0)
317 return r;
318 }
319
320 return sd_bus_message_close_container(reply);
321 }
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 sd_bus_error *error) {
376
377 int r;
378
379 assert(u);
380 assert(c);
381 assert(name);
382 assert(message);
383
384 flags |= UNIT_PRIVATE;
385
386 if (streq(name, "Delegate")) {
387 int b;
388
389 if (!UNIT_VTABLE(u)->can_delegate)
390 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
391
392 r = sd_bus_message_read(message, "b", &b);
393 if (r < 0)
394 return r;
395
396 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
397 c->delegate = b;
398 c->delegate_controllers = b ? _CGROUP_MASK_ALL : 0;
399
400 unit_write_settingf(u, flags, name, "Delegate=%s", yes_no(b));
401 }
402
403 return 1;
404
405 } else if (STR_IN_SET(name, "DelegateControllers", "DisableControllers")) {
406 CGroupMask mask = 0;
407
408 if (streq(name, "DelegateControllers") && !UNIT_VTABLE(u)->can_delegate)
409 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
410
411 r = sd_bus_message_enter_container(message, 'a', "s");
412 if (r < 0)
413 return r;
414
415 for (;;) {
416 CGroupController cc;
417 const char *t;
418
419 r = sd_bus_message_read(message, "s", &t);
420 if (r < 0)
421 return r;
422 if (r == 0)
423 break;
424
425 cc = cgroup_controller_from_string(t);
426 if (cc < 0)
427 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown cgroup controller '%s'", t);
428
429 mask |= CGROUP_CONTROLLER_TO_MASK(cc);
430 }
431
432 r = sd_bus_message_exit_container(message);
433 if (r < 0)
434 return r;
435
436 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
437 _cleanup_free_ char *t = NULL;
438
439 r = cg_mask_to_string(mask, &t);
440 if (r < 0)
441 return r;
442
443 if (streq(name, "DelegateControllers")) {
444
445 c->delegate = true;
446 if (mask == 0)
447 c->delegate_controllers = 0;
448 else
449 c->delegate_controllers |= mask;
450
451 unit_write_settingf(u, flags, name, "Delegate=%s", strempty(t));
452
453 } else if (streq(name, "DisableControllers")) {
454
455 if (mask == 0)
456 c->disable_controllers = 0;
457 else
458 c->disable_controllers |= mask;
459
460 unit_write_settingf(u, flags, name, "%s=%s", name, strempty(t));
461 }
462 }
463
464 return 1;
465 }
466
467 return 0;
468 }
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 sd_bus_error *error) {
478
479 int b, r;
480
481 assert(p);
482
483 r = sd_bus_message_read(message, "b", &b);
484 if (r < 0)
485 return r;
486
487 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
488 *p = b;
489 unit_invalidate_cgroup(u, mask);
490 unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b));
491 }
492
493 return 1;
494 }
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 sd_bus_error *error) { \
504 \
505 uint64_t v; \
506 int r; \
507 \
508 assert(p); \
509 \
510 r = sd_bus_message_read(message, "t", &v); \
511 if (r < 0) \
512 return r; \
513 \
514 if (!check(v)) \
515 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
516 "Value specified in %s is out of range", name); \
517 \
518 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
519 *p = v; \
520 unit_invalidate_cgroup(u, (mask)); \
521 \
522 if (v == (val)) \
523 unit_write_settingf(u, flags, name, \
524 "%s=", name); \
525 else \
526 unit_write_settingf(u, flags, name, \
527 "%s=%" PRIu64, name, v); \
528 } \
529 \
530 return 1; \
531 }
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 sd_bus_error *error) { \
541 \
542 uint64_t v; \
543 int r; \
544 \
545 assert(p); \
546 \
547 r = sd_bus_message_read(message, "t", &v); \
548 if (r < 0) \
549 return r; \
550 \
551 if (v < minimum) \
552 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
553 "Value specified in %s is out of range", name); \
554 \
555 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
556 *p = v; \
557 unit_invalidate_cgroup(u, (mask)); \
558 \
559 if (v == CGROUP_LIMIT_MAX) \
560 unit_write_settingf(u, flags, name, \
561 "%s=infinity", name); \
562 else \
563 unit_write_settingf(u, flags, name, \
564 "%s=%" PRIu64, name, v); \
565 } \
566 \
567 return 1; \
568 } \
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 sd_bus_error *error) { \
576 \
577 uint64_t v; \
578 uint32_t raw; \
579 int r; \
580 \
581 assert(p); \
582 \
583 r = sd_bus_message_read(message, "u", &raw); \
584 if (r < 0) \
585 return r; \
586 \
587 v = scale(raw, UINT32_MAX); \
588 if (v < minimum || v >= UINT64_MAX) \
589 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
590 "Value specified in %s is out of range", name); \
591 \
592 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
593 const char *e; \
594 \
595 *p = v; \
596 unit_invalidate_cgroup(u, (mask)); \
597 \
598 /* Chop off suffix */ \
599 assert_se(e = endswith(name, "Scale")); \
600 name = strndupa(name, e - name); \
601 \
602 unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name, \
603 (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); \
604 } \
605 \
606 return 1; \
607 }
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 if (*list) {
1431 r = bpf_firewall_supported();
1432 if (r < 0)
1433 return r;
1434 if (r == BPF_FIREWALL_UNSUPPORTED) {
1435 static bool warned = false;
1436
1437 log_full(warned ? LOG_DEBUG : LOG_WARNING,
1438 "Transient unit %s configures an IP firewall, but the local system does not support BPF/cgroup firewalling.\n"
1439 "Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first started transient unit using IP firewalling.)", u->id);
1440
1441 warned = true;
1442 }
1443 }
1444 }
1445
1446 return 1;
1447 }
1448
1449 if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB))
1450 return bus_cgroup_set_transient_property(u, c, name, message, flags, error);
1451
1452 return 0;
1453 }