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