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