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