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