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