]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-cgroup.c
Merge pull request #23396 from msekletar/fix-idle-action-lock
[thirdparty/systemd.git] / src / core / dbus-cgroup.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <arpa/inet.h>
4
5 #include "af-list.h"
6 #include "alloc-util.h"
7 #include "bpf-firewall.h"
8 #include "bpf-foreign.h"
9 #include "bus-get-properties.h"
10 #include "cgroup-util.h"
11 #include "cgroup.h"
12 #include "core-varlink.h"
13 #include "dbus-cgroup.h"
14 #include "dbus-util.h"
15 #include "errno-util.h"
16 #include "fd-util.h"
17 #include "fileio.h"
18 #include "in-addr-prefix-util.h"
19 #include "ip-protocol-list.h"
20 #include "limits-util.h"
21 #include "parse-util.h"
22 #include "path-util.h"
23 #include "percent-util.h"
24 #include "socket-util.h"
25
26 BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max, "t", TasksMax, tasks_max_resolve);
27
28 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
29 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_mode, managed_oom_mode, ManagedOOMMode);
30 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_preference, managed_oom_preference, ManagedOOMPreference);
31
32 static int property_get_cgroup_mask(
33 sd_bus *bus,
34 const char *path,
35 const char *interface,
36 const char *property,
37 sd_bus_message *reply,
38 void *userdata,
39 sd_bus_error *error) {
40
41 CGroupMask *mask = userdata;
42 int r;
43
44 assert(bus);
45 assert(reply);
46
47 r = sd_bus_message_open_container(reply, 'a', "s");
48 if (r < 0)
49 return r;
50
51 for (CGroupController ctrl = 0; ctrl < _CGROUP_CONTROLLER_MAX; ctrl++) {
52 if ((*mask & CGROUP_CONTROLLER_TO_MASK(ctrl)) == 0)
53 continue;
54
55 r = sd_bus_message_append(reply, "s", cgroup_controller_to_string(ctrl));
56 if (r < 0)
57 return r;
58 }
59
60 return sd_bus_message_close_container(reply);
61 }
62
63 static int property_get_delegate_controllers(
64 sd_bus *bus,
65 const char *path,
66 const char *interface,
67 const char *property,
68 sd_bus_message *reply,
69 void *userdata,
70 sd_bus_error *error) {
71
72 CGroupContext *c = userdata;
73
74 assert(bus);
75 assert(reply);
76 assert(c);
77
78 if (!c->delegate)
79 return sd_bus_message_append(reply, "as", 0);
80
81 return property_get_cgroup_mask(bus, path, interface, property, reply, &c->delegate_controllers, error);
82 }
83
84 static int property_get_cpuset(
85 sd_bus *bus,
86 const char *path,
87 const char *interface,
88 const char *property,
89 sd_bus_message *reply,
90 void *userdata,
91 sd_bus_error *error) {
92
93 CPUSet *cpus = userdata;
94 _cleanup_free_ uint8_t *array = NULL;
95 size_t allocated;
96
97 assert(bus);
98 assert(reply);
99 assert(cpus);
100
101 (void) cpu_set_to_dbus(cpus, &array, &allocated);
102 return sd_bus_message_append_array(reply, 'y', array, allocated);
103 }
104
105 static int property_get_io_device_weight(
106 sd_bus *bus,
107 const char *path,
108 const char *interface,
109 const char *property,
110 sd_bus_message *reply,
111 void *userdata,
112 sd_bus_error *error) {
113
114 CGroupContext *c = userdata;
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_weights, w, c->io_device_weights) {
126 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
127 if (r < 0)
128 return r;
129 }
130
131 return sd_bus_message_close_container(reply);
132 }
133
134 static int property_get_io_device_limits(
135 sd_bus *bus,
136 const char *path,
137 const char *interface,
138 const char *property,
139 sd_bus_message *reply,
140 void *userdata,
141 sd_bus_error *error) {
142
143 CGroupContext *c = userdata;
144 int r;
145
146 assert(bus);
147 assert(reply);
148 assert(c);
149
150 r = sd_bus_message_open_container(reply, 'a', "(st)");
151 if (r < 0)
152 return r;
153
154 LIST_FOREACH(device_limits, l, c->io_device_limits) {
155 CGroupIOLimitType type;
156
157 type = cgroup_io_limit_type_from_string(property);
158 if (type < 0 || l->limits[type] == cgroup_io_limit_defaults[type])
159 continue;
160
161 r = sd_bus_message_append(reply, "(st)", l->path, l->limits[type]);
162 if (r < 0)
163 return r;
164 }
165
166 return sd_bus_message_close_container(reply);
167 }
168
169 static int property_get_io_device_latency(
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 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_latencies, l, c->io_device_latencies) {
190 r = sd_bus_message_append(reply, "(st)", l->path, l->target_usec);
191 if (r < 0)
192 return r;
193 }
194
195 return sd_bus_message_close_container(reply);
196 }
197
198 static int property_get_blockio_device_weight(
199 sd_bus *bus,
200 const char *path,
201 const char *interface,
202 const char *property,
203 sd_bus_message *reply,
204 void *userdata,
205 sd_bus_error *error) {
206
207 CGroupContext *c = userdata;
208 int r;
209
210 assert(bus);
211 assert(reply);
212 assert(c);
213
214 r = sd_bus_message_open_container(reply, 'a', "(st)");
215 if (r < 0)
216 return r;
217
218 LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
219 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
220 if (r < 0)
221 return r;
222 }
223
224 return sd_bus_message_close_container(reply);
225 }
226
227 static int property_get_blockio_device_bandwidths(
228 sd_bus *bus,
229 const char *path,
230 const char *interface,
231 const char *property,
232 sd_bus_message *reply,
233 void *userdata,
234 sd_bus_error *error) {
235
236 CGroupContext *c = userdata;
237 int r;
238
239 assert(bus);
240 assert(reply);
241 assert(c);
242
243 r = sd_bus_message_open_container(reply, 'a', "(st)");
244 if (r < 0)
245 return r;
246
247 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
248 uint64_t v;
249
250 if (streq(property, "BlockIOReadBandwidth"))
251 v = b->rbps;
252 else
253 v = b->wbps;
254
255 if (v == CGROUP_LIMIT_MAX)
256 continue;
257
258 r = sd_bus_message_append(reply, "(st)", b->path, v);
259 if (r < 0)
260 return r;
261 }
262
263 return sd_bus_message_close_container(reply);
264 }
265
266 static int property_get_device_allow(
267 sd_bus *bus,
268 const char *path,
269 const char *interface,
270 const char *property,
271 sd_bus_message *reply,
272 void *userdata,
273 sd_bus_error *error) {
274
275 CGroupContext *c = userdata;
276 int r;
277
278 assert(bus);
279 assert(reply);
280 assert(c);
281
282 r = sd_bus_message_open_container(reply, 'a', "(ss)");
283 if (r < 0)
284 return r;
285
286 LIST_FOREACH(device_allow, a, c->device_allow) {
287 unsigned k = 0;
288 char rwm[4];
289
290 if (a->r)
291 rwm[k++] = 'r';
292 if (a->w)
293 rwm[k++] = 'w';
294 if (a->m)
295 rwm[k++] = 'm';
296
297 rwm[k] = 0;
298
299 r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
300 if (r < 0)
301 return r;
302 }
303
304 return sd_bus_message_close_container(reply);
305 }
306
307 static int property_get_ip_address_access(
308 sd_bus *bus,
309 const char *path,
310 const char *interface,
311 const char *property,
312 sd_bus_message *reply,
313 void *userdata,
314 sd_bus_error *error) {
315
316 Set **prefixes = userdata;
317 struct in_addr_prefix *i;
318 int r;
319
320 assert(prefixes);
321
322 r = sd_bus_message_open_container(reply, 'a', "(iayu)");
323 if (r < 0)
324 return r;
325
326 SET_FOREACH(i, *prefixes) {
327
328 r = sd_bus_message_open_container(reply, 'r', "iayu");
329 if (r < 0)
330 return r;
331
332 r = sd_bus_message_append(reply, "i", i->family);
333 if (r < 0)
334 return r;
335
336 r = sd_bus_message_append_array(reply, 'y', &i->address, FAMILY_ADDRESS_SIZE(i->family));
337 if (r < 0)
338 return r;
339
340 r = sd_bus_message_append(reply, "u", (uint32_t) i->prefixlen);
341 if (r < 0)
342 return r;
343
344 r = sd_bus_message_close_container(reply);
345 if (r < 0)
346 return r;
347 }
348
349 return sd_bus_message_close_container(reply);
350 }
351
352 static int property_get_bpf_foreign_program(
353 sd_bus *bus,
354 const char *path,
355 const char *interface,
356 const char *property,
357 sd_bus_message *reply,
358 void *userdata,
359 sd_bus_error *error) {
360 CGroupContext *c = userdata;
361 int r;
362
363 r = sd_bus_message_open_container(reply, 'a', "(ss)");
364 if (r < 0)
365 return r;
366
367 LIST_FOREACH(programs, p, c->bpf_foreign_programs) {
368 const char *attach_type = bpf_cgroup_attach_type_to_string(p->attach_type);
369
370 r = sd_bus_message_append(reply, "(ss)", attach_type, p->bpffs_path);
371 if (r < 0)
372 return r;
373 }
374
375 return sd_bus_message_close_container(reply);
376 }
377
378 static int property_get_socket_bind(
379 sd_bus *bus,
380 const char *path,
381 const char *interface,
382 const char *property,
383 sd_bus_message *reply,
384 void *userdata,
385 sd_bus_error *error) {
386
387 CGroupSocketBindItem **items = userdata;
388 int r;
389
390 assert(items);
391
392 r = sd_bus_message_open_container(reply, 'a', "(iiqq)");
393 if (r < 0)
394 return r;
395
396 LIST_FOREACH(socket_bind_items, i, *items) {
397 r = sd_bus_message_append(reply, "(iiqq)", i->address_family, i->ip_protocol, i->nr_ports, i->port_min);
398 if (r < 0)
399 return r;
400 }
401
402 return sd_bus_message_close_container(reply);
403 }
404
405 static int property_get_restrict_network_interfaces(
406 sd_bus *bus,
407 const char *path,
408 const char *interface,
409 const char *property,
410 sd_bus_message *reply,
411 void *userdata,
412 sd_bus_error *error) {
413 int r;
414 CGroupContext *c = userdata;
415 char *iface;
416
417 assert(bus);
418 assert(reply);
419 assert(c);
420
421 r = sd_bus_message_open_container(reply, 'r', "bas");
422 if (r < 0)
423 return r;
424
425 r = sd_bus_message_append(reply, "b", c->restrict_network_interfaces_is_allow_list);
426 if (r < 0)
427 return r;
428
429 r = sd_bus_message_open_container(reply, 'a', "s");
430 if (r < 0)
431 return r;
432
433 SET_FOREACH(iface, c->restrict_network_interfaces) {
434 r = sd_bus_message_append(reply, "s", iface);
435 if (r < 0)
436 return r;
437 }
438
439 r = sd_bus_message_close_container(reply);
440 if (r < 0)
441 return r;
442
443 return sd_bus_message_close_container(reply);
444 }
445
446 const sd_bus_vtable bus_cgroup_vtable[] = {
447 SD_BUS_VTABLE_START(0),
448 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
449 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers, 0, 0),
450 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
451 SD_BUS_PROPERTY("CPUWeight", "t", NULL, offsetof(CGroupContext, cpu_weight), 0),
452 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL, offsetof(CGroupContext, startup_cpu_weight), 0),
453 SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0),
454 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0),
455 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
456 SD_BUS_PROPERTY("CPUQuotaPeriodUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_period_usec), 0),
457 SD_BUS_PROPERTY("AllowedCPUs", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_cpus), 0),
458 SD_BUS_PROPERTY("StartupAllowedCPUs", "ay", property_get_cpuset, offsetof(CGroupContext, startup_cpuset_cpus), 0),
459 SD_BUS_PROPERTY("AllowedMemoryNodes", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_mems), 0),
460 SD_BUS_PROPERTY("StartupAllowedMemoryNodes", "ay", property_get_cpuset, offsetof(CGroupContext, startup_cpuset_mems), 0),
461 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, io_accounting), 0),
462 SD_BUS_PROPERTY("IOWeight", "t", NULL, offsetof(CGroupContext, io_weight), 0),
463 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL, offsetof(CGroupContext, startup_io_weight), 0),
464 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight, 0, 0),
465 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
466 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
467 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
468 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
469 SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency, 0, 0),
470 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
471 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0),
472 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0),
473 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
474 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
475 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
476 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
477 SD_BUS_PROPERTY("DefaultMemoryLow", "t", NULL, offsetof(CGroupContext, default_memory_low), 0),
478 SD_BUS_PROPERTY("DefaultMemoryMin", "t", NULL, offsetof(CGroupContext, default_memory_min), 0),
479 SD_BUS_PROPERTY("MemoryMin", "t", NULL, offsetof(CGroupContext, memory_min), 0),
480 SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0),
481 SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0),
482 SD_BUS_PROPERTY("MemoryMax", "t", NULL, offsetof(CGroupContext, memory_max), 0),
483 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL, offsetof(CGroupContext, memory_swap_max), 0),
484 SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
485 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
486 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
487 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0),
488 SD_BUS_PROPERTY("TasksMax", "t", bus_property_get_tasks_max, offsetof(CGroupContext, tasks_max), 0),
489 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, ip_accounting), 0),
490 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_allow), 0),
491 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_deny), 0),
492 SD_BUS_PROPERTY("IPIngressFilterPath", "as", NULL, offsetof(CGroupContext, ip_filters_ingress), 0),
493 SD_BUS_PROPERTY("IPEgressFilterPath", "as", NULL, offsetof(CGroupContext, ip_filters_egress), 0),
494 SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask, offsetof(CGroupContext, disable_controllers), 0),
495 SD_BUS_PROPERTY("ManagedOOMSwap", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_swap), 0),
496 SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_mem_pressure), 0),
497 SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimit", "u", NULL, offsetof(CGroupContext, moom_mem_pressure_limit), 0),
498 SD_BUS_PROPERTY("ManagedOOMPreference", "s", property_get_managed_oom_preference, offsetof(CGroupContext, moom_preference), 0),
499 SD_BUS_PROPERTY("BPFProgram", "a(ss)", property_get_bpf_foreign_program, 0, 0),
500 SD_BUS_PROPERTY("SocketBindAllow", "a(iiqq)", property_get_socket_bind, offsetof(CGroupContext, socket_bind_allow), 0),
501 SD_BUS_PROPERTY("SocketBindDeny", "a(iiqq)", property_get_socket_bind, offsetof(CGroupContext, socket_bind_deny), 0),
502 SD_BUS_PROPERTY("RestrictNetworkInterfaces", "(bas)", property_get_restrict_network_interfaces, 0, 0),
503 SD_BUS_VTABLE_END
504 };
505
506 static int bus_cgroup_set_transient_property(
507 Unit *u,
508 CGroupContext *c,
509 const char *name,
510 sd_bus_message *message,
511 UnitWriteFlags flags,
512 sd_bus_error *error) {
513
514 int r;
515
516 assert(u);
517 assert(c);
518 assert(name);
519 assert(message);
520
521 flags |= UNIT_PRIVATE;
522
523 if (streq(name, "Delegate")) {
524 int b;
525
526 if (!UNIT_VTABLE(u)->can_delegate)
527 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
528
529 r = sd_bus_message_read(message, "b", &b);
530 if (r < 0)
531 return r;
532
533 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
534 c->delegate = b;
535 c->delegate_controllers = b ? _CGROUP_MASK_ALL : 0;
536
537 unit_write_settingf(u, flags, name, "Delegate=%s", yes_no(b));
538 }
539
540 return 1;
541
542 } else if (STR_IN_SET(name, "DelegateControllers", "DisableControllers")) {
543 CGroupMask mask = 0;
544
545 if (streq(name, "DelegateControllers") && !UNIT_VTABLE(u)->can_delegate)
546 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
547
548 r = sd_bus_message_enter_container(message, 'a', "s");
549 if (r < 0)
550 return r;
551
552 for (;;) {
553 CGroupController cc;
554 const char *t;
555
556 r = sd_bus_message_read(message, "s", &t);
557 if (r < 0)
558 return r;
559 if (r == 0)
560 break;
561
562 cc = cgroup_controller_from_string(t);
563 if (cc < 0)
564 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown cgroup controller '%s'", t);
565
566 mask |= CGROUP_CONTROLLER_TO_MASK(cc);
567 }
568
569 r = sd_bus_message_exit_container(message);
570 if (r < 0)
571 return r;
572
573 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
574 _cleanup_free_ char *t = NULL;
575
576 r = cg_mask_to_string(mask, &t);
577 if (r < 0)
578 return r;
579
580 if (streq(name, "DelegateControllers")) {
581
582 c->delegate = true;
583 if (mask == 0)
584 c->delegate_controllers = 0;
585 else
586 c->delegate_controllers |= mask;
587
588 unit_write_settingf(u, flags, name, "Delegate=%s", strempty(t));
589
590 } else if (streq(name, "DisableControllers")) {
591
592 if (mask == 0)
593 c->disable_controllers = 0;
594 else
595 c->disable_controllers |= mask;
596
597 unit_write_settingf(u, flags, name, "%s=%s", name, strempty(t));
598 }
599 }
600
601 return 1;
602 } else if (STR_IN_SET(name, "IPIngressFilterPath", "IPEgressFilterPath")) {
603 char ***filters;
604 size_t n = 0;
605
606 filters = streq(name, "IPIngressFilterPath") ? &c->ip_filters_ingress : &c->ip_filters_egress;
607 r = sd_bus_message_enter_container(message, 'a', "s");
608 if (r < 0)
609 return r;
610
611 for (;;) {
612 const char *path;
613
614 r = sd_bus_message_read(message, "s", &path);
615 if (r < 0)
616 return r;
617 if (r == 0)
618 break;
619
620 if (!path_is_normalized(path) || !path_is_absolute(path))
621 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects a normalized absolute path.", name);
622
623 if (!UNIT_WRITE_FLAGS_NOOP(flags) && !strv_contains(*filters, path)) {
624 r = strv_extend(filters, path);
625 if (r < 0)
626 return log_oom();
627 }
628 n++;
629 }
630 r = sd_bus_message_exit_container(message);
631 if (r < 0)
632 return r;
633
634 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
635 _cleanup_free_ char *buf = NULL;
636 _cleanup_fclose_ FILE *f = NULL;
637 size_t size = 0;
638
639 if (n == 0)
640 *filters = strv_free(*filters);
641
642 unit_invalidate_cgroup_bpf(u);
643 f = open_memstream_unlocked(&buf, &size);
644 if (!f)
645 return -ENOMEM;
646
647 fputs(name, f);
648 fputs("=\n", f);
649
650 STRV_FOREACH(entry, *filters)
651 fprintf(f, "%s=%s\n", name, *entry);
652
653 r = fflush_and_check(f);
654 if (r < 0)
655 return r;
656
657 unit_write_setting(u, flags, name, buf);
658
659 if (*filters) {
660 r = bpf_firewall_supported();
661 if (r < 0)
662 return r;
663 if (r != BPF_FIREWALL_SUPPORTED_WITH_MULTI) {
664 static bool warned = false;
665
666 log_full(warned ? LOG_DEBUG : LOG_WARNING,
667 "Transient unit %s configures an IP firewall with BPF, but the local system does not support BPF/cgroup firewalling with multiple filters.\n"
668 "Starting this unit will fail! (This warning is only shown for the first started transient unit using IP firewalling.)", u->id);
669 warned = true;
670 }
671 }
672 }
673
674 return 1;
675 } else if (streq(name, "BPFProgram")) {
676 const char *a, *p;
677 size_t n = 0;
678
679 r = sd_bus_message_enter_container(message, 'a', "(ss)");
680 if (r < 0)
681 return r;
682
683 while ((r = sd_bus_message_read(message, "(ss)", &a, &p)) > 0) {
684 int attach_type = bpf_cgroup_attach_type_from_string(a);
685 if (attach_type < 0)
686 return sd_bus_error_setf(
687 error,
688 SD_BUS_ERROR_INVALID_ARGS,
689 "%s expects a valid BPF attach type, got '%s'.",
690 name, a);
691
692 if (!path_is_normalized(p) || !path_is_absolute(p))
693 return sd_bus_error_setf(
694 error,
695 SD_BUS_ERROR_INVALID_ARGS,
696 "%s= expects a normalized absolute path.",
697 name);
698
699 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
700 r = cgroup_add_bpf_foreign_program(c, attach_type, p);
701 if (r < 0)
702 return r;
703 }
704 n++;
705 }
706 if (r < 0)
707 return r;
708
709 r = sd_bus_message_exit_container(message);
710 if (r < 0)
711 return r;
712
713 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
714 _cleanup_free_ char *buf = NULL;
715 _cleanup_fclose_ FILE *f = NULL;
716 size_t size = 0;
717
718 if (n == 0)
719 while (c->bpf_foreign_programs)
720 cgroup_context_remove_bpf_foreign_program(c, c->bpf_foreign_programs);
721
722 f = open_memstream_unlocked(&buf, &size);
723 if (!f)
724 return -ENOMEM;
725
726 fputs(name, f);
727 fputs("=\n", f);
728
729 LIST_FOREACH(programs, fp, c->bpf_foreign_programs)
730 fprintf(f, "%s=%s:%s\n", name,
731 bpf_cgroup_attach_type_to_string(fp->attach_type),
732 fp->bpffs_path);
733
734 r = fflush_and_check(f);
735 if (r < 0)
736 return r;
737
738 unit_write_setting(u, flags, name, buf);
739
740 if (c->bpf_foreign_programs) {
741 r = bpf_foreign_supported();
742 if (r < 0)
743 return r;
744 if (r == 0)
745 log_full(LOG_DEBUG,
746 "Transient unit %s configures a BPF program pinned to BPF "
747 "filesystem, but the local system does not support that.\n"
748 "Starting this unit will fail!", u->id);
749 }
750 }
751
752 return 1;
753 }
754
755 return 0;
756 }
757
758 static int bus_cgroup_set_boolean(
759 Unit *u,
760 const char *name,
761 bool *p,
762 CGroupMask mask,
763 sd_bus_message *message,
764 UnitWriteFlags flags,
765 sd_bus_error *error) {
766
767 int b, r;
768
769 assert(p);
770
771 r = sd_bus_message_read(message, "b", &b);
772 if (r < 0)
773 return r;
774
775 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
776 *p = b;
777 unit_invalidate_cgroup(u, mask);
778 unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b));
779 }
780
781 return 1;
782 }
783
784 #define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \
785 static int bus_cgroup_set_##function( \
786 Unit *u, \
787 const char *name, \
788 uint64_t *p, \
789 sd_bus_message *message, \
790 UnitWriteFlags flags, \
791 sd_bus_error *error) { \
792 \
793 uint64_t v; \
794 int r; \
795 \
796 assert(p); \
797 \
798 r = sd_bus_message_read(message, "t", &v); \
799 if (r < 0) \
800 return r; \
801 \
802 if (!check(v)) \
803 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
804 "Value specified in %s is out of range", name); \
805 \
806 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
807 *p = v; \
808 unit_invalidate_cgroup(u, mask); \
809 \
810 if (v == (val)) \
811 unit_write_settingf(u, flags, name, \
812 "%s=", name); \
813 else \
814 unit_write_settingf(u, flags, name, \
815 "%s=%" PRIu64, name, v); \
816 } \
817 \
818 return 1; \
819 }
820
821 #define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \
822 static int bus_cgroup_set_##function( \
823 Unit *u, \
824 const char *name, \
825 uint64_t *p, \
826 sd_bus_message *message, \
827 UnitWriteFlags flags, \
828 sd_bus_error *error) { \
829 \
830 uint64_t v; \
831 int r; \
832 \
833 assert(p); \
834 \
835 r = sd_bus_message_read(message, "t", &v); \
836 if (r < 0) \
837 return r; \
838 \
839 if (v < minimum) \
840 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
841 "Value specified in %s is out of range", name); \
842 \
843 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
844 *p = v; \
845 unit_invalidate_cgroup(u, mask); \
846 \
847 if (v == CGROUP_LIMIT_MAX) \
848 unit_write_settingf(u, flags, name, \
849 "%s=infinity", name); \
850 else \
851 unit_write_settingf(u, flags, name, \
852 "%s=%" PRIu64, name, v); \
853 } \
854 \
855 return 1; \
856 } \
857 static int bus_cgroup_set_##function##_scale( \
858 Unit *u, \
859 const char *name, \
860 uint64_t *p, \
861 sd_bus_message *message, \
862 UnitWriteFlags flags, \
863 sd_bus_error *error) { \
864 \
865 uint64_t v; \
866 uint32_t raw; \
867 int r; \
868 \
869 assert(p); \
870 \
871 r = sd_bus_message_read(message, "u", &raw); \
872 if (r < 0) \
873 return r; \
874 \
875 v = scale(raw, UINT32_MAX); \
876 if (v < minimum || v >= UINT64_MAX) \
877 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
878 "Value specified in %s is out of range", name); \
879 \
880 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
881 *p = v; \
882 unit_invalidate_cgroup(u, mask); \
883 \
884 /* Prepare to chop off suffix */ \
885 assert_se(endswith(name, "Scale")); \
886 \
887 int scaled = UINT32_SCALE_TO_PERMYRIAD(raw); \
888 unit_write_settingf(u, flags, name, "%.*s=" PERMYRIAD_AS_PERCENT_FORMAT_STR, \
889 (int)(strlen(name) - strlen("Scale")), name, \
890 PERMYRIAD_AS_PERCENT_FORMAT_VAL(scaled)); \
891 } \
892 \
893 return 1; \
894 }
895
896 DISABLE_WARNING_TYPE_LIMITS;
897 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight, CGROUP_MASK_CPU, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
898 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_OK, CGROUP_CPU_SHARES_INVALID);
899 BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight, CGROUP_MASK_IO, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
900 BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEIGHT_IS_OK, CGROUP_BLKIO_WEIGHT_INVALID);
901 BUS_DEFINE_SET_CGROUP_LIMIT(memory, CGROUP_MASK_MEMORY, physical_memory_scale, 1);
902 BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
903 BUS_DEFINE_SET_CGROUP_LIMIT(swap, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
904 REENABLE_WARNING;
905
906 static int bus_cgroup_set_tasks_max(
907 Unit *u,
908 const char *name,
909 TasksMax *p,
910 sd_bus_message *message,
911 UnitWriteFlags flags,
912 sd_bus_error *error) {
913
914 uint64_t v;
915 int r;
916
917 assert(p);
918
919 r = sd_bus_message_read(message, "t", &v);
920 if (r < 0)
921 return r;
922
923 if (v < 1)
924 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
925 "Value specified in %s is out of range", name);
926
927 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
928 *p = (TasksMax) { .value = v, .scale = 0 }; /* When .scale==0, .value is the absolute value */
929 unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
930
931 if (v == CGROUP_LIMIT_MAX)
932 unit_write_settingf(u, flags, name,
933 "%s=infinity", name);
934 else
935 unit_write_settingf(u, flags, name,
936 "%s=%" PRIu64, name, v);
937 }
938
939 return 1;
940 }
941
942 static int bus_cgroup_set_tasks_max_scale(
943 Unit *u,
944 const char *name,
945 TasksMax *p,
946 sd_bus_message *message,
947 UnitWriteFlags flags,
948 sd_bus_error *error) {
949
950 uint32_t v;
951 int r;
952
953 assert(p);
954
955 r = sd_bus_message_read(message, "u", &v);
956 if (r < 0)
957 return r;
958
959 if (v < 1 || v >= UINT32_MAX)
960 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
961 "Value specified in %s is out of range", name);
962
963 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
964 *p = (TasksMax) { v, UINT32_MAX }; /* .scale is not 0, so this is interpreted as v/UINT32_MAX. */
965 unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
966
967 uint32_t scaled = DIV_ROUND_UP((uint64_t) v * 100U, (uint64_t) UINT32_MAX);
968 unit_write_settingf(u, flags, name, "%s=%" PRIu32 ".%" PRIu32 "%%", "TasksMax",
969 scaled / 10, scaled % 10);
970 }
971
972 return 1;
973 }
974
975 int bus_cgroup_set_property(
976 Unit *u,
977 CGroupContext *c,
978 const char *name,
979 sd_bus_message *message,
980 UnitWriteFlags flags,
981 sd_bus_error *error) {
982
983 CGroupIOLimitType iol_type;
984 int r;
985
986 assert(u);
987 assert(c);
988 assert(name);
989 assert(message);
990
991 flags |= UNIT_PRIVATE;
992
993 if (streq(name, "CPUAccounting"))
994 return bus_cgroup_set_boolean(u, name, &c->cpu_accounting, get_cpu_accounting_mask(), message, flags, error);
995
996 if (streq(name, "CPUWeight"))
997 return bus_cgroup_set_cpu_weight(u, name, &c->cpu_weight, message, flags, error);
998
999 if (streq(name, "StartupCPUWeight"))
1000 return bus_cgroup_set_cpu_weight(u, name, &c->startup_cpu_weight, message, flags, error);
1001
1002 if (streq(name, "CPUShares"))
1003 return bus_cgroup_set_cpu_shares(u, name, &c->cpu_shares, message, flags, error);
1004
1005 if (streq(name, "StartupCPUShares"))
1006 return bus_cgroup_set_cpu_shares(u, name, &c->startup_cpu_shares, message, flags, error);
1007
1008 if (streq(name, "IOAccounting"))
1009 return bus_cgroup_set_boolean(u, name, &c->io_accounting, CGROUP_MASK_IO, message, flags, error);
1010
1011 if (streq(name, "IOWeight"))
1012 return bus_cgroup_set_io_weight(u, name, &c->io_weight, message, flags, error);
1013
1014 if (streq(name, "StartupIOWeight"))
1015 return bus_cgroup_set_io_weight(u, name, &c->startup_io_weight, message, flags, error);
1016
1017 if (streq(name, "BlockIOAccounting"))
1018 return bus_cgroup_set_boolean(u, name, &c->blockio_accounting, CGROUP_MASK_BLKIO, message, flags, error);
1019
1020 if (streq(name, "BlockIOWeight"))
1021 return bus_cgroup_set_blockio_weight(u, name, &c->blockio_weight, message, flags, error);
1022
1023 if (streq(name, "StartupBlockIOWeight"))
1024 return bus_cgroup_set_blockio_weight(u, name, &c->startup_blockio_weight, message, flags, error);
1025
1026 if (streq(name, "MemoryAccounting"))
1027 return bus_cgroup_set_boolean(u, name, &c->memory_accounting, CGROUP_MASK_MEMORY, message, flags, error);
1028
1029 if (streq(name, "MemoryMin")) {
1030 r = bus_cgroup_set_memory_protection(u, name, &c->memory_min, message, flags, error);
1031 if (r > 0)
1032 c->memory_min_set = true;
1033 return r;
1034 }
1035
1036 if (streq(name, "MemoryLow")) {
1037 r = bus_cgroup_set_memory_protection(u, name, &c->memory_low, message, flags, error);
1038 if (r > 0)
1039 c->memory_low_set = true;
1040 return r;
1041 }
1042
1043 if (streq(name, "DefaultMemoryMin")) {
1044 r = bus_cgroup_set_memory_protection(u, name, &c->default_memory_min, message, flags, error);
1045 if (r > 0)
1046 c->default_memory_min_set = true;
1047 return r;
1048 }
1049
1050 if (streq(name, "DefaultMemoryLow")) {
1051 r = bus_cgroup_set_memory_protection(u, name, &c->default_memory_low, message, flags, error);
1052 if (r > 0)
1053 c->default_memory_low_set = true;
1054 return r;
1055 }
1056
1057 if (streq(name, "MemoryHigh"))
1058 return bus_cgroup_set_memory(u, name, &c->memory_high, message, flags, error);
1059
1060 if (streq(name, "MemorySwapMax"))
1061 return bus_cgroup_set_swap(u, name, &c->memory_swap_max, message, flags, error);
1062
1063 if (streq(name, "MemoryMax"))
1064 return bus_cgroup_set_memory(u, name, &c->memory_max, message, flags, error);
1065
1066 if (streq(name, "MemoryLimit"))
1067 return bus_cgroup_set_memory(u, name, &c->memory_limit, message, flags, error);
1068
1069 if (streq(name, "MemoryMinScale")) {
1070 r = bus_cgroup_set_memory_protection_scale(u, name, &c->memory_min, message, flags, error);
1071 if (r > 0)
1072 c->memory_min_set = true;
1073 return r;
1074 }
1075
1076 if (streq(name, "MemoryLowScale")) {
1077 r = bus_cgroup_set_memory_protection_scale(u, name, &c->memory_low, message, flags, error);
1078 if (r > 0)
1079 c->memory_low_set = true;
1080 return r;
1081 }
1082
1083 if (streq(name, "DefaultMemoryMinScale")) {
1084 r = bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_min, message, flags, error);
1085 if (r > 0)
1086 c->default_memory_min_set = true;
1087 return r;
1088 }
1089
1090 if (streq(name, "DefaultMemoryLowScale")) {
1091 r = bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_low, message, flags, error);
1092 if (r > 0)
1093 c->default_memory_low_set = true;
1094 return r;
1095 }
1096
1097 if (streq(name, "MemoryHighScale"))
1098 return bus_cgroup_set_memory_scale(u, name, &c->memory_high, message, flags, error);
1099
1100 if (streq(name, "MemorySwapMaxScale"))
1101 return bus_cgroup_set_swap_scale(u, name, &c->memory_swap_max, message, flags, error);
1102
1103 if (streq(name, "MemoryMaxScale"))
1104 return bus_cgroup_set_memory_scale(u, name, &c->memory_max, message, flags, error);
1105
1106 if (streq(name, "MemoryLimitScale"))
1107 return bus_cgroup_set_memory_scale(u, name, &c->memory_limit, message, flags, error);
1108
1109 if (streq(name, "TasksAccounting"))
1110 return bus_cgroup_set_boolean(u, name, &c->tasks_accounting, CGROUP_MASK_PIDS, message, flags, error);
1111
1112 if (streq(name, "TasksMax"))
1113 return bus_cgroup_set_tasks_max(u, name, &c->tasks_max, message, flags, error);
1114
1115 if (streq(name, "TasksMaxScale"))
1116 return bus_cgroup_set_tasks_max_scale(u, name, &c->tasks_max, message, flags, error);
1117
1118 if (streq(name, "CPUQuotaPerSecUSec")) {
1119 uint64_t u64;
1120
1121 r = sd_bus_message_read(message, "t", &u64);
1122 if (r < 0)
1123 return r;
1124
1125 if (u64 <= 0)
1126 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "CPUQuotaPerSecUSec= value out of range");
1127
1128 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1129 c->cpu_quota_per_sec_usec = u64;
1130 u->warned_clamping_cpu_quota_period = false;
1131 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
1132
1133 if (c->cpu_quota_per_sec_usec == USEC_INFINITY)
1134 unit_write_setting(u, flags, "CPUQuota", "CPUQuota=");
1135 else
1136 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
1137 * purpose here. */
1138 unit_write_settingf(u, flags, "CPUQuota",
1139 "CPUQuota=%0.f%%",
1140 (double) (c->cpu_quota_per_sec_usec / 10000));
1141 }
1142
1143 return 1;
1144
1145 } else if (streq(name, "CPUQuotaPeriodUSec")) {
1146 uint64_t u64;
1147
1148 r = sd_bus_message_read(message, "t", &u64);
1149 if (r < 0)
1150 return r;
1151
1152 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1153 c->cpu_quota_period_usec = u64;
1154 u->warned_clamping_cpu_quota_period = false;
1155 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
1156 if (c->cpu_quota_period_usec == USEC_INFINITY)
1157 unit_write_setting(u, flags, "CPUQuotaPeriodSec", "CPUQuotaPeriodSec=");
1158 else
1159 unit_write_settingf(u, flags, "CPUQuotaPeriodSec",
1160 "CPUQuotaPeriodSec=%s",
1161 FORMAT_TIMESPAN(c->cpu_quota_period_usec, 1));
1162 }
1163
1164 return 1;
1165
1166 } else if (STR_IN_SET(name, "AllowedCPUs", "StartupAllowedCPUs", "AllowedMemoryNodes", "StartupAllowedMemoryNodes")) {
1167 const void *a;
1168 size_t n;
1169 _cleanup_(cpu_set_reset) CPUSet new_set = {};
1170
1171 r = sd_bus_message_read_array(message, 'y', &a, &n);
1172 if (r < 0)
1173 return r;
1174
1175 r = cpu_set_from_dbus(a, n, &new_set);
1176 if (r < 0)
1177 return r;
1178
1179 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1180 _cleanup_free_ char *setstr = NULL;
1181 CPUSet *set = NULL;
1182
1183 setstr = cpu_set_to_range_string(&new_set);
1184 if (!setstr)
1185 return -ENOMEM;
1186
1187 if (streq(name, "AllowedCPUs"))
1188 set = &c->cpuset_cpus;
1189 else if (streq(name, "StartupAllowedCPUs"))
1190 set = &c->startup_cpuset_cpus;
1191 else if (streq(name, "AllowedMemoryNodes"))
1192 set = &c->cpuset_mems;
1193 else if (streq(name, "StartupAllowedMemoryNodes"))
1194 set = &c->startup_cpuset_mems;
1195
1196 assert(set);
1197
1198 cpu_set_reset(set);
1199 *set = new_set;
1200 new_set = (CPUSet) {};
1201
1202 unit_invalidate_cgroup(u, CGROUP_MASK_CPUSET);
1203 unit_write_settingf(u, flags, name, "%s=%s", name, setstr);
1204 }
1205
1206 return 1;
1207
1208 } else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) {
1209 const char *path;
1210 unsigned n = 0;
1211 uint64_t u64;
1212
1213 r = sd_bus_message_enter_container(message, 'a', "(st)");
1214 if (r < 0)
1215 return r;
1216
1217 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
1218
1219 if (!path_is_normalized(path))
1220 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
1221
1222 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1223 CGroupIODeviceLimit *a = NULL;
1224
1225 LIST_FOREACH(device_limits, b, c->io_device_limits)
1226 if (path_equal(path, b->path)) {
1227 a = b;
1228 break;
1229 }
1230
1231 if (!a) {
1232 CGroupIOLimitType type;
1233
1234 a = new0(CGroupIODeviceLimit, 1);
1235 if (!a)
1236 return -ENOMEM;
1237
1238 a->path = strdup(path);
1239 if (!a->path) {
1240 free(a);
1241 return -ENOMEM;
1242 }
1243
1244 for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
1245 a->limits[type] = cgroup_io_limit_defaults[type];
1246
1247 LIST_PREPEND(device_limits, c->io_device_limits, a);
1248 }
1249
1250 a->limits[iol_type] = u64;
1251 }
1252
1253 n++;
1254 }
1255 if (r < 0)
1256 return r;
1257
1258 r = sd_bus_message_exit_container(message);
1259 if (r < 0)
1260 return r;
1261
1262 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1263 _cleanup_free_ char *buf = NULL;
1264 _cleanup_fclose_ FILE *f = NULL;
1265 size_t size = 0;
1266
1267 if (n == 0)
1268 LIST_FOREACH(device_limits, a, c->io_device_limits)
1269 a->limits[iol_type] = cgroup_io_limit_defaults[iol_type];
1270
1271 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
1272
1273 f = open_memstream_unlocked(&buf, &size);
1274 if (!f)
1275 return -ENOMEM;
1276
1277 fprintf(f, "%s=\n", name);
1278 LIST_FOREACH(device_limits, a, c->io_device_limits)
1279 if (a->limits[iol_type] != cgroup_io_limit_defaults[iol_type])
1280 fprintf(f, "%s=%s %" PRIu64 "\n", name, a->path, a->limits[iol_type]);
1281
1282 r = fflush_and_check(f);
1283 if (r < 0)
1284 return r;
1285 unit_write_setting(u, flags, name, buf);
1286 }
1287
1288 return 1;
1289
1290 } else if (streq(name, "IODeviceWeight")) {
1291 const char *path;
1292 uint64_t weight;
1293 unsigned n = 0;
1294
1295 r = sd_bus_message_enter_container(message, 'a', "(st)");
1296 if (r < 0)
1297 return r;
1298
1299 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
1300
1301 if (!path_is_normalized(path))
1302 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
1303
1304 if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID)
1305 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "IODeviceWeight= value out of range");
1306
1307 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1308 CGroupIODeviceWeight *a = NULL;
1309
1310 LIST_FOREACH(device_weights, b, c->io_device_weights)
1311 if (path_equal(b->path, path)) {
1312 a = b;
1313 break;
1314 }
1315
1316 if (!a) {
1317 a = new0(CGroupIODeviceWeight, 1);
1318 if (!a)
1319 return -ENOMEM;
1320
1321 a->path = strdup(path);
1322 if (!a->path) {
1323 free(a);
1324 return -ENOMEM;
1325 }
1326 LIST_PREPEND(device_weights, c->io_device_weights, a);
1327 }
1328
1329 a->weight = weight;
1330 }
1331
1332 n++;
1333 }
1334
1335 r = sd_bus_message_exit_container(message);
1336 if (r < 0)
1337 return r;
1338
1339 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1340 _cleanup_free_ char *buf = NULL;
1341 _cleanup_fclose_ FILE *f = NULL;
1342 size_t size = 0;
1343
1344 if (n == 0)
1345 while (c->io_device_weights)
1346 cgroup_context_free_io_device_weight(c, c->io_device_weights);
1347
1348 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
1349
1350 f = open_memstream_unlocked(&buf, &size);
1351 if (!f)
1352 return -ENOMEM;
1353
1354 fputs("IODeviceWeight=\n", f);
1355 LIST_FOREACH(device_weights, a, c->io_device_weights)
1356 fprintf(f, "IODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
1357
1358 r = fflush_and_check(f);
1359 if (r < 0)
1360 return r;
1361 unit_write_setting(u, flags, name, buf);
1362 }
1363
1364 return 1;
1365
1366 } else if (streq(name, "IODeviceLatencyTargetUSec")) {
1367 const char *path;
1368 uint64_t target;
1369 unsigned n = 0;
1370
1371 r = sd_bus_message_enter_container(message, 'a', "(st)");
1372 if (r < 0)
1373 return r;
1374
1375 while ((r = sd_bus_message_read(message, "(st)", &path, &target)) > 0) {
1376
1377 if (!path_is_normalized(path))
1378 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
1379
1380 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1381 CGroupIODeviceLatency *a = NULL;
1382
1383 LIST_FOREACH(device_latencies, b, c->io_device_latencies)
1384 if (path_equal(b->path, path)) {
1385 a = b;
1386 break;
1387 }
1388
1389 if (!a) {
1390 a = new0(CGroupIODeviceLatency, 1);
1391 if (!a)
1392 return -ENOMEM;
1393
1394 a->path = strdup(path);
1395 if (!a->path) {
1396 free(a);
1397 return -ENOMEM;
1398 }
1399 LIST_PREPEND(device_latencies, c->io_device_latencies, a);
1400 }
1401
1402 a->target_usec = target;
1403 }
1404
1405 n++;
1406 }
1407
1408 r = sd_bus_message_exit_container(message);
1409 if (r < 0)
1410 return r;
1411
1412 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1413 _cleanup_free_ char *buf = NULL;
1414 _cleanup_fclose_ FILE *f = NULL;
1415 size_t size = 0;
1416
1417 if (n == 0)
1418 while (c->io_device_latencies)
1419 cgroup_context_free_io_device_latency(c, c->io_device_latencies);
1420
1421 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
1422
1423 f = open_memstream_unlocked(&buf, &size);
1424 if (!f)
1425 return -ENOMEM;
1426
1427 fputs("IODeviceLatencyTargetSec=\n", f);
1428 LIST_FOREACH(device_latencies, a, c->io_device_latencies)
1429 fprintf(f, "IODeviceLatencyTargetSec=%s %s\n",
1430 a->path, FORMAT_TIMESPAN(a->target_usec, 1));
1431
1432 r = fflush_and_check(f);
1433 if (r < 0)
1434 return r;
1435 unit_write_setting(u, flags, name, buf);
1436 }
1437
1438 return 1;
1439
1440 } else if (STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1441 const char *path;
1442 bool read = true;
1443 unsigned n = 0;
1444 uint64_t u64;
1445
1446 if (streq(name, "BlockIOWriteBandwidth"))
1447 read = false;
1448
1449 r = sd_bus_message_enter_container(message, 'a', "(st)");
1450 if (r < 0)
1451 return r;
1452
1453 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
1454
1455 if (!path_is_normalized(path))
1456 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
1457
1458 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1459 CGroupBlockIODeviceBandwidth *a = NULL;
1460
1461 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths)
1462 if (path_equal(path, b->path)) {
1463 a = b;
1464 break;
1465 }
1466
1467 if (!a) {
1468 a = new0(CGroupBlockIODeviceBandwidth, 1);
1469 if (!a)
1470 return -ENOMEM;
1471
1472 a->rbps = CGROUP_LIMIT_MAX;
1473 a->wbps = CGROUP_LIMIT_MAX;
1474 a->path = strdup(path);
1475 if (!a->path) {
1476 free(a);
1477 return -ENOMEM;
1478 }
1479
1480 LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
1481 }
1482
1483 if (read)
1484 a->rbps = u64;
1485 else
1486 a->wbps = u64;
1487 }
1488
1489 n++;
1490 }
1491 if (r < 0)
1492 return r;
1493
1494 r = sd_bus_message_exit_container(message);
1495 if (r < 0)
1496 return r;
1497
1498 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1499 _cleanup_free_ char *buf = NULL;
1500 _cleanup_fclose_ FILE *f = NULL;
1501 size_t size = 0;
1502
1503 if (n == 0)
1504 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) {
1505 if (read)
1506 a->rbps = CGROUP_LIMIT_MAX;
1507 else
1508 a->wbps = CGROUP_LIMIT_MAX;
1509 }
1510
1511 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
1512
1513 f = open_memstream_unlocked(&buf, &size);
1514 if (!f)
1515 return -ENOMEM;
1516
1517 if (read) {
1518 fputs("BlockIOReadBandwidth=\n", f);
1519 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
1520 if (a->rbps != CGROUP_LIMIT_MAX)
1521 fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->rbps);
1522 } else {
1523 fputs("BlockIOWriteBandwidth=\n", f);
1524 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
1525 if (a->wbps != CGROUP_LIMIT_MAX)
1526 fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->wbps);
1527 }
1528
1529 r = fflush_and_check(f);
1530 if (r < 0)
1531 return r;
1532
1533 unit_write_setting(u, flags, name, buf);
1534 }
1535
1536 return 1;
1537
1538 } else if (streq(name, "BlockIODeviceWeight")) {
1539 const char *path;
1540 uint64_t weight;
1541 unsigned n = 0;
1542
1543 r = sd_bus_message_enter_container(message, 'a', "(st)");
1544 if (r < 0)
1545 return r;
1546
1547 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
1548
1549 if (!path_is_normalized(path))
1550 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
1551
1552 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
1553 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIODeviceWeight= out of range");
1554
1555 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1556 CGroupBlockIODeviceWeight *a = NULL;
1557
1558 LIST_FOREACH(device_weights, b, c->blockio_device_weights)
1559 if (path_equal(b->path, path)) {
1560 a = b;
1561 break;
1562 }
1563
1564 if (!a) {
1565 a = new0(CGroupBlockIODeviceWeight, 1);
1566 if (!a)
1567 return -ENOMEM;
1568
1569 a->path = strdup(path);
1570 if (!a->path) {
1571 free(a);
1572 return -ENOMEM;
1573 }
1574 LIST_PREPEND(device_weights, c->blockio_device_weights, a);
1575 }
1576
1577 a->weight = weight;
1578 }
1579
1580 n++;
1581 }
1582
1583 r = sd_bus_message_exit_container(message);
1584 if (r < 0)
1585 return r;
1586
1587 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1588 _cleanup_free_ char *buf = NULL;
1589 _cleanup_fclose_ FILE *f = NULL;
1590 size_t size = 0;
1591
1592 if (n == 0)
1593 while (c->blockio_device_weights)
1594 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
1595
1596 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
1597
1598 f = open_memstream_unlocked(&buf, &size);
1599 if (!f)
1600 return -ENOMEM;
1601
1602 fputs("BlockIODeviceWeight=\n", f);
1603 LIST_FOREACH(device_weights, a, c->blockio_device_weights)
1604 fprintf(f, "BlockIODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
1605
1606 r = fflush_and_check(f);
1607 if (r < 0)
1608 return r;
1609
1610 unit_write_setting(u, flags, name, buf);
1611 }
1612
1613 return 1;
1614
1615 } else if (streq(name, "DevicePolicy")) {
1616 const char *policy;
1617 CGroupDevicePolicy p;
1618
1619 r = sd_bus_message_read(message, "s", &policy);
1620 if (r < 0)
1621 return r;
1622
1623 p = cgroup_device_policy_from_string(policy);
1624 if (p < 0)
1625 return p;
1626
1627 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1628 c->device_policy = p;
1629 unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
1630 unit_write_settingf(u, flags, name, "DevicePolicy=%s", policy);
1631 }
1632
1633 return 1;
1634
1635 } else if (streq(name, "DeviceAllow")) {
1636 const char *path, *rwm;
1637 unsigned n = 0;
1638
1639 r = sd_bus_message_enter_container(message, 'a', "(ss)");
1640 if (r < 0)
1641 return r;
1642
1643 while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
1644
1645 if (!valid_device_allow_pattern(path) || strpbrk(path, WHITESPACE))
1646 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node or pattern");
1647
1648 if (isempty(rwm))
1649 rwm = "rwm";
1650 else if (!in_charset(rwm, "rwm"))
1651 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
1652
1653 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1654 CGroupDeviceAllow *a = NULL;
1655
1656 LIST_FOREACH(device_allow, b, c->device_allow)
1657 if (path_equal(b->path, path)) {
1658 a = b;
1659 break;
1660 }
1661
1662 if (!a) {
1663 a = new0(CGroupDeviceAllow, 1);
1664 if (!a)
1665 return -ENOMEM;
1666
1667 a->path = strdup(path);
1668 if (!a->path) {
1669 free(a);
1670 return -ENOMEM;
1671 }
1672
1673 LIST_PREPEND(device_allow, c->device_allow, a);
1674 }
1675
1676 a->r = strchr(rwm, 'r');
1677 a->w = strchr(rwm, 'w');
1678 a->m = strchr(rwm, 'm');
1679 }
1680
1681 n++;
1682 }
1683 if (r < 0)
1684 return r;
1685
1686 r = sd_bus_message_exit_container(message);
1687 if (r < 0)
1688 return r;
1689
1690 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1691 _cleanup_free_ char *buf = NULL;
1692 _cleanup_fclose_ FILE *f = NULL;
1693 size_t size = 0;
1694
1695 if (n == 0)
1696 while (c->device_allow)
1697 cgroup_context_free_device_allow(c, c->device_allow);
1698
1699 unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
1700
1701 f = open_memstream_unlocked(&buf, &size);
1702 if (!f)
1703 return -ENOMEM;
1704
1705 fputs("DeviceAllow=\n", f);
1706 LIST_FOREACH(device_allow, a, c->device_allow)
1707 fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
1708
1709 r = fflush_and_check(f);
1710 if (r < 0)
1711 return r;
1712 unit_write_setting(u, flags, name, buf);
1713 }
1714
1715 return 1;
1716
1717 } else if (streq(name, "IPAccounting")) {
1718 int b;
1719
1720 r = sd_bus_message_read(message, "b", &b);
1721 if (r < 0)
1722 return r;
1723
1724 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1725 c->ip_accounting = b;
1726
1727 unit_invalidate_cgroup_bpf(u);
1728 unit_write_settingf(u, flags, name, "IPAccounting=%s", yes_no(b));
1729 }
1730
1731 return 1;
1732
1733 } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
1734 _cleanup_set_free_ Set *new_prefixes = NULL;
1735 size_t n = 0;
1736
1737 r = sd_bus_message_enter_container(message, 'a', "(iayu)");
1738 if (r < 0)
1739 return r;
1740
1741 for (;;) {
1742 const void *ap;
1743 int32_t family;
1744 uint32_t prefixlen;
1745 size_t an;
1746
1747 r = sd_bus_message_enter_container(message, 'r', "iayu");
1748 if (r < 0)
1749 return r;
1750 if (r == 0)
1751 break;
1752
1753 r = sd_bus_message_read(message, "i", &family);
1754 if (r < 0)
1755 return r;
1756
1757 if (!IN_SET(family, AF_INET, AF_INET6))
1758 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects IPv4 or IPv6 addresses only.", name);
1759
1760 r = sd_bus_message_read_array(message, 'y', &ap, &an);
1761 if (r < 0)
1762 return r;
1763
1764 if (an != FAMILY_ADDRESS_SIZE(family))
1765 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1766 af_to_name(family), FAMILY_ADDRESS_SIZE(family), an);
1767
1768 r = sd_bus_message_read(message, "u", &prefixlen);
1769 if (r < 0)
1770 return r;
1771
1772 if (prefixlen > FAMILY_ADDRESS_SIZE(family)*8)
1773 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));
1774
1775 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1776 struct in_addr_prefix prefix = {
1777 .family = family,
1778 .prefixlen = prefixlen,
1779 };
1780
1781 memcpy(&prefix.address, ap, an);
1782
1783 r = in_addr_prefix_add(&new_prefixes, &prefix);
1784 if (r < 0)
1785 return r;
1786 }
1787
1788 r = sd_bus_message_exit_container(message);
1789 if (r < 0)
1790 return r;
1791
1792 n++;
1793 }
1794
1795 r = sd_bus_message_exit_container(message);
1796 if (r < 0)
1797 return r;
1798
1799 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1800 _cleanup_free_ char *buf = NULL;
1801 _cleanup_fclose_ FILE *f = NULL;
1802 size_t size = 0;
1803 Set **prefixes;
1804 bool *reduced;
1805
1806 unit_invalidate_cgroup_bpf(u);
1807 f = open_memstream_unlocked(&buf, &size);
1808 if (!f)
1809 return -ENOMEM;
1810
1811 prefixes = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny;
1812 reduced = streq(name, "IPAddressAllow") ? &c->ip_address_allow_reduced : &c->ip_address_deny_reduced;
1813
1814 if (n == 0) {
1815 *reduced = true;
1816 *prefixes = set_free(*prefixes);
1817 fputs(name, f);
1818 fputs("=\n", f);
1819 } else {
1820 *reduced = false;
1821
1822 r = in_addr_prefixes_merge(prefixes, new_prefixes);
1823 if (r < 0)
1824 return r;
1825
1826 const struct in_addr_prefix *p;
1827 SET_FOREACH(p, new_prefixes)
1828 fprintf(f, "%s=%s\n", name,
1829 IN_ADDR_PREFIX_TO_STRING(p->family, &p->address, p->prefixlen));
1830 }
1831
1832 r = fflush_and_check(f);
1833 if (r < 0)
1834 return r;
1835
1836 unit_write_setting(u, flags, name, buf);
1837 }
1838
1839 return 1;
1840 }
1841
1842 if (STR_IN_SET(name, "ManagedOOMSwap", "ManagedOOMMemoryPressure")) {
1843 ManagedOOMMode *cgroup_mode = streq(name, "ManagedOOMSwap") ? &c->moom_swap : &c->moom_mem_pressure;
1844 ManagedOOMMode m;
1845 const char *mode;
1846
1847 if (!UNIT_VTABLE(u)->can_set_managed_oom)
1848 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set %s for this unit type", name);
1849
1850 r = sd_bus_message_read(message, "s", &mode);
1851 if (r < 0)
1852 return r;
1853
1854 m = managed_oom_mode_from_string(mode);
1855 if (m < 0)
1856 return -EINVAL;
1857
1858 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1859 *cgroup_mode = m;
1860 unit_write_settingf(u, flags, name, "%s=%s", name, mode);
1861 }
1862
1863 (void) manager_varlink_send_managed_oom_update(u);
1864 return 1;
1865 }
1866
1867 if (streq(name, "ManagedOOMMemoryPressureLimit")) {
1868 uint32_t v;
1869
1870 if (!UNIT_VTABLE(u)->can_set_managed_oom)
1871 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set %s for this unit type", name);
1872
1873 r = sd_bus_message_read(message, "u", &v);
1874 if (r < 0)
1875 return r;
1876
1877 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1878 c->moom_mem_pressure_limit = v;
1879 unit_write_settingf(u, flags, name,
1880 "ManagedOOMMemoryPressureLimit=" PERMYRIAD_AS_PERCENT_FORMAT_STR,
1881 PERMYRIAD_AS_PERCENT_FORMAT_VAL(UINT32_SCALE_TO_PERMYRIAD(v)));
1882 }
1883
1884 if (c->moom_mem_pressure == MANAGED_OOM_KILL)
1885 (void) manager_varlink_send_managed_oom_update(u);
1886
1887 return 1;
1888 }
1889
1890 if (streq(name, "ManagedOOMPreference")) {
1891 ManagedOOMPreference p;
1892 const char *pref;
1893
1894 r = sd_bus_message_read(message, "s", &pref);
1895 if (r < 0)
1896 return r;
1897
1898 p = managed_oom_preference_from_string(pref);
1899 if (p < 0)
1900 return p;
1901
1902 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1903 c->moom_preference = p;
1904 unit_write_settingf(u, flags, name, "ManagedOOMPreference=%s", pref);
1905 }
1906
1907 return 1;
1908 }
1909 if (STR_IN_SET(name, "SocketBindAllow", "SocketBindDeny")) {
1910 CGroupSocketBindItem **list;
1911 uint16_t nr_ports, port_min;
1912 size_t n = 0;
1913 int32_t family, ip_protocol;
1914
1915 list = streq(name, "SocketBindAllow") ? &c->socket_bind_allow : &c->socket_bind_deny;
1916
1917 r = sd_bus_message_enter_container(message, 'a', "(iiqq)");
1918 if (r < 0)
1919 return r;
1920
1921 while ((r = sd_bus_message_read(message, "(iiqq)", &family, &ip_protocol, &nr_ports, &port_min)) > 0) {
1922
1923 if (!IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6))
1924 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects INET or INET6 family, if specified.", name);
1925
1926 if (!IN_SET(ip_protocol, 0, IPPROTO_TCP, IPPROTO_UDP))
1927 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects TCP or UDP protocol, if specified.", name);
1928
1929 if (port_min + (uint32_t) nr_ports > (1 << 16))
1930 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects maximum port value lesser than 65536.", name);
1931
1932 if (port_min == 0 && nr_ports != 0)
1933 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects port range starting with positive value.", name);
1934
1935 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1936 _cleanup_free_ CGroupSocketBindItem *item = NULL;
1937
1938 item = new(CGroupSocketBindItem, 1);
1939 if (!item)
1940 return log_oom();
1941
1942 *item = (CGroupSocketBindItem) {
1943 .address_family = family,
1944 .ip_protocol = ip_protocol,
1945 .nr_ports = nr_ports,
1946 .port_min = port_min
1947 };
1948
1949 LIST_PREPEND(socket_bind_items, *list, TAKE_PTR(item));
1950 }
1951 n++;
1952 }
1953 if (r < 0)
1954 return r;
1955
1956 r = sd_bus_message_exit_container(message);
1957 if (r < 0)
1958 return r;
1959
1960 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1961 _cleanup_free_ char *buf = NULL;
1962 _cleanup_fclose_ FILE *f = NULL;
1963 size_t size = 0;
1964
1965 if (n == 0)
1966 cgroup_context_remove_socket_bind(list);
1967 else {
1968 if ((u->manager->cgroup_supported & CGROUP_MASK_BPF_SOCKET_BIND) == 0)
1969 log_full(LOG_DEBUG,
1970 "Unit %s configures source compiled BPF programs "
1971 "but the local system does not support that.\n"
1972 "Starting this unit will fail!", u->id);
1973 }
1974
1975 f = open_memstream_unlocked(&buf, &size);
1976 if (!f)
1977 return -ENOMEM;
1978
1979 fprintf(f, "%s:", name);
1980
1981 LIST_FOREACH(socket_bind_items, item, *list)
1982 cgroup_context_dump_socket_bind_item(item, f);
1983
1984 fputc('\n', f);
1985
1986 r = fflush_and_check(f);
1987 if (r < 0)
1988 return r;
1989
1990 unit_write_setting(u, flags, name, buf);
1991 }
1992
1993 return 1;
1994 }
1995 if (streq(name, "RestrictNetworkInterfaces")) {
1996 int is_allow_list;
1997 _cleanup_strv_free_ char **l = NULL;
1998
1999 r = sd_bus_message_enter_container(message, 'r', "bas");
2000 if (r < 0)
2001 return r;
2002
2003 r = sd_bus_message_read(message, "b", &is_allow_list);
2004 if (r < 0)
2005 return r;
2006
2007 r = sd_bus_message_read_strv(message, &l);
2008 if (r < 0)
2009 return r;
2010
2011 r = sd_bus_message_exit_container(message);
2012 if (r < 0)
2013 return r;
2014
2015 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2016 _cleanup_free_ char *joined = NULL;
2017
2018 if (strv_isempty(l)) {
2019 c->restrict_network_interfaces_is_allow_list = false;
2020 c->restrict_network_interfaces = set_free(c->restrict_network_interfaces);
2021
2022 unit_write_settingf(u, flags, name, "%s=", name);
2023 return 1;
2024 }
2025
2026 if (set_isempty(c->restrict_network_interfaces))
2027 c->restrict_network_interfaces_is_allow_list = is_allow_list;
2028
2029 STRV_FOREACH(s, l) {
2030 if (!ifname_valid(*s)) {
2031 log_full(LOG_WARNING, "Invalid interface name, ignoring: %s", *s);
2032 continue;
2033 }
2034 if (c->restrict_network_interfaces_is_allow_list != (bool) is_allow_list)
2035 free(set_remove(c->restrict_network_interfaces, *s));
2036 else {
2037 r = set_put_strdup(&c->restrict_network_interfaces, *s);
2038 if (r < 0)
2039 return log_oom();
2040 }
2041 }
2042
2043 joined = strv_join(l, " ");
2044 if (!joined)
2045 return -ENOMEM;
2046
2047 unit_write_settingf(u, flags, name, "%s=%s%s", name, is_allow_list ? "" : "~", joined);
2048 }
2049
2050 return 1;
2051 }
2052
2053 if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB))
2054 return bus_cgroup_set_transient_property(u, c, name, message, flags, error);
2055
2056 return 0;
2057 }