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