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