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