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