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