1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "alloc-util.h"
7 #include "bpf-firewall.h"
8 #include "bpf-foreign.h"
9 #include "bus-get-properties.h"
11 #include "cgroup-util.h"
13 #include "core-varlink.h"
14 #include "dbus-cgroup.h"
15 #include "dbus-util.h"
16 #include "errno-util.h"
20 #include "firewall-util.h"
21 #include "in-addr-prefix-util.h"
22 #include "ip-protocol-list.h"
23 #include "limits-util.h"
24 #include "memstream-util.h"
25 #include "parse-util.h"
26 #include "path-util.h"
27 #include "percent-util.h"
28 #include "socket-util.h"
30 BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max
, "t", TasksMax
, tasks_max_resolve
);
31 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_cgroup_pressure_watch
, cgroup_pressure_watch
, CGroupPressureWatch
);
33 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy
, cgroup_device_policy
, CGroupDevicePolicy
);
34 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_mode
, managed_oom_mode
, ManagedOOMMode
);
35 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_preference
, managed_oom_preference
, ManagedOOMPreference
);
37 static int property_get_cgroup_mask(
40 const char *interface
,
42 sd_bus_message
*reply
,
44 sd_bus_error
*error
) {
46 CGroupMask
*mask
= userdata
;
52 r
= sd_bus_message_open_container(reply
, 'a', "s");
56 for (CGroupController ctrl
= 0; ctrl
< _CGROUP_CONTROLLER_MAX
; ctrl
++) {
57 if ((*mask
& CGROUP_CONTROLLER_TO_MASK(ctrl
)) == 0)
60 r
= sd_bus_message_append(reply
, "s", cgroup_controller_to_string(ctrl
));
65 return sd_bus_message_close_container(reply
);
68 static int property_get_delegate_controllers(
71 const char *interface
,
73 sd_bus_message
*reply
,
75 sd_bus_error
*error
) {
77 CGroupContext
*c
= ASSERT_PTR(userdata
);
83 return sd_bus_message_append(reply
, "as", 0);
85 return property_get_cgroup_mask(bus
, path
, interface
, property
, reply
, &c
->delegate_controllers
, error
);
88 static int property_get_cpuset(
91 const char *interface
,
93 sd_bus_message
*reply
,
95 sd_bus_error
*error
) {
97 CPUSet
*cpus
= ASSERT_PTR(userdata
);
98 _cleanup_free_
uint8_t *array
= NULL
;
104 (void) cpu_set_to_dbus(cpus
, &array
, &allocated
);
105 return sd_bus_message_append_array(reply
, 'y', array
, allocated
);
108 static int property_get_io_device_weight(
111 const char *interface
,
112 const char *property
,
113 sd_bus_message
*reply
,
115 sd_bus_error
*error
) {
117 CGroupContext
*c
= ASSERT_PTR(userdata
);
123 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
127 LIST_FOREACH(device_weights
, w
, c
->io_device_weights
) {
128 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
133 return sd_bus_message_close_container(reply
);
136 static int property_get_io_device_limits(
139 const char *interface
,
140 const char *property
,
141 sd_bus_message
*reply
,
143 sd_bus_error
*error
) {
145 CGroupContext
*c
= ASSERT_PTR(userdata
);
151 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
155 LIST_FOREACH(device_limits
, l
, c
->io_device_limits
) {
156 CGroupIOLimitType type
;
158 type
= cgroup_io_limit_type_from_string(property
);
159 if (type
< 0 || l
->limits
[type
] == cgroup_io_limit_defaults
[type
])
162 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->limits
[type
]);
167 return sd_bus_message_close_container(reply
);
170 static int property_get_io_device_latency(
173 const char *interface
,
174 const char *property
,
175 sd_bus_message
*reply
,
177 sd_bus_error
*error
) {
179 CGroupContext
*c
= ASSERT_PTR(userdata
);
185 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
189 LIST_FOREACH(device_latencies
, l
, c
->io_device_latencies
) {
190 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->target_usec
);
195 return sd_bus_message_close_container(reply
);
198 static int property_get_blockio_device_weight(
201 const char *interface
,
202 const char *property
,
203 sd_bus_message
*reply
,
205 sd_bus_error
*error
) {
207 CGroupContext
*c
= ASSERT_PTR(userdata
);
213 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
217 LIST_FOREACH(device_weights
, w
, c
->blockio_device_weights
) {
218 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
223 return sd_bus_message_close_container(reply
);
226 static int property_get_blockio_device_bandwidths(
229 const char *interface
,
230 const char *property
,
231 sd_bus_message
*reply
,
233 sd_bus_error
*error
) {
235 CGroupContext
*c
= ASSERT_PTR(userdata
);
241 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
245 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
248 if (streq(property
, "BlockIOReadBandwidth"))
253 if (v
== CGROUP_LIMIT_MAX
)
256 r
= sd_bus_message_append(reply
, "(st)", b
->path
, v
);
261 return sd_bus_message_close_container(reply
);
264 static int property_get_device_allow(
267 const char *interface
,
268 const char *property
,
269 sd_bus_message
*reply
,
271 sd_bus_error
*error
) {
273 CGroupContext
*c
= ASSERT_PTR(userdata
);
279 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
283 LIST_FOREACH(device_allow
, a
, c
->device_allow
) {
296 r
= sd_bus_message_append(reply
, "(ss)", a
->path
, rwm
);
301 return sd_bus_message_close_container(reply
);
304 static int property_get_ip_address_access(
307 const char *interface
,
308 const char *property
,
309 sd_bus_message
*reply
,
311 sd_bus_error
*error
) {
313 Set
**prefixes
= ASSERT_PTR(userdata
);
314 struct in_addr_prefix
*i
;
317 r
= sd_bus_message_open_container(reply
, 'a', "(iayu)");
321 SET_FOREACH(i
, *prefixes
) {
323 r
= sd_bus_message_open_container(reply
, 'r', "iayu");
327 r
= sd_bus_message_append(reply
, "i", i
->family
);
331 r
= sd_bus_message_append_array(reply
, 'y', &i
->address
, FAMILY_ADDRESS_SIZE(i
->family
));
335 r
= sd_bus_message_append(reply
, "u", (uint32_t) i
->prefixlen
);
339 r
= sd_bus_message_close_container(reply
);
344 return sd_bus_message_close_container(reply
);
347 static int property_get_bpf_foreign_program(
350 const char *interface
,
351 const char *property
,
352 sd_bus_message
*reply
,
354 sd_bus_error
*error
) {
355 CGroupContext
*c
= userdata
;
358 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
362 LIST_FOREACH(programs
, p
, c
->bpf_foreign_programs
) {
363 const char *attach_type
= bpf_cgroup_attach_type_to_string(p
->attach_type
);
365 r
= sd_bus_message_append(reply
, "(ss)", attach_type
, p
->bpffs_path
);
370 return sd_bus_message_close_container(reply
);
373 static int property_get_socket_bind(
376 const char *interface
,
377 const char *property
,
378 sd_bus_message
*reply
,
380 sd_bus_error
*error
) {
382 CGroupSocketBindItem
**items
= ASSERT_PTR(userdata
);
385 r
= sd_bus_message_open_container(reply
, 'a', "(iiqq)");
389 LIST_FOREACH(socket_bind_items
, i
, *items
) {
390 r
= sd_bus_message_append(reply
, "(iiqq)", i
->address_family
, i
->ip_protocol
, i
->nr_ports
, i
->port_min
);
395 return sd_bus_message_close_container(reply
);
398 static int property_get_restrict_network_interfaces(
401 const char *interface
,
402 const char *property
,
403 sd_bus_message
*reply
,
405 sd_bus_error
*error
) {
407 CGroupContext
*c
= ASSERT_PTR(userdata
);
413 r
= sd_bus_message_open_container(reply
, 'r', "bas");
417 r
= sd_bus_message_append(reply
, "b", c
->restrict_network_interfaces_is_allow_list
);
421 r
= bus_message_append_string_set(reply
, c
->restrict_network_interfaces
);
425 return sd_bus_message_close_container(reply
);
428 static int property_get_cgroup_nft_set(
431 const char *interface
,
432 const char *property
,
433 sd_bus_message
*reply
,
435 sd_bus_error
*error
) {
437 CGroupContext
*c
= userdata
;
443 r
= sd_bus_message_open_container(reply
, 'a', "(iiss)");
447 FOREACH_ARRAY(nft_set
, c
->nft_set_context
.sets
, c
->nft_set_context
.n_sets
) {
448 r
= sd_bus_message_append(reply
, "(iiss)", nft_set
->source
, nft_set
->nfproto
, nft_set
->table
, nft_set
->set
);
453 return sd_bus_message_close_container(reply
);
456 const sd_bus_vtable bus_cgroup_vtable
[] = {
457 SD_BUS_VTABLE_START(0),
458 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool
, offsetof(CGroupContext
, delegate
), 0),
459 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers
, 0, 0),
460 SD_BUS_PROPERTY("DelegateSubgroup", "s", NULL
, offsetof(CGroupContext
, delegate_subgroup
), 0),
461 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, cpu_accounting
), 0),
462 SD_BUS_PROPERTY("CPUWeight", "t", NULL
, offsetof(CGroupContext
, cpu_weight
), 0),
463 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL
, offsetof(CGroupContext
, startup_cpu_weight
), 0),
464 SD_BUS_PROPERTY("CPUShares", "t", NULL
, offsetof(CGroupContext
, cpu_shares
), 0),
465 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL
, offsetof(CGroupContext
, startup_cpu_shares
), 0),
466 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_per_sec_usec
), 0),
467 SD_BUS_PROPERTY("CPUQuotaPeriodUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_period_usec
), 0),
468 SD_BUS_PROPERTY("AllowedCPUs", "ay", property_get_cpuset
, offsetof(CGroupContext
, cpuset_cpus
), 0),
469 SD_BUS_PROPERTY("StartupAllowedCPUs", "ay", property_get_cpuset
, offsetof(CGroupContext
, startup_cpuset_cpus
), 0),
470 SD_BUS_PROPERTY("AllowedMemoryNodes", "ay", property_get_cpuset
, offsetof(CGroupContext
, cpuset_mems
), 0),
471 SD_BUS_PROPERTY("StartupAllowedMemoryNodes", "ay", property_get_cpuset
, offsetof(CGroupContext
, startup_cpuset_mems
), 0),
472 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, io_accounting
), 0),
473 SD_BUS_PROPERTY("IOWeight", "t", NULL
, offsetof(CGroupContext
, io_weight
), 0),
474 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_io_weight
), 0),
475 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight
, 0, 0),
476 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
477 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
478 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
479 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
480 SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency
, 0, 0),
481 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, blockio_accounting
), 0),
482 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL
, offsetof(CGroupContext
, blockio_weight
), 0),
483 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_blockio_weight
), 0),
484 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight
, 0, 0),
485 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
486 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
487 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_accounting
), 0),
488 SD_BUS_PROPERTY("DefaultMemoryLow", "t", NULL
, offsetof(CGroupContext
, default_memory_low
), 0),
489 SD_BUS_PROPERTY("DefaultStartupMemoryLow", "t", NULL
, offsetof(CGroupContext
, default_startup_memory_low
), 0),
490 SD_BUS_PROPERTY("DefaultMemoryMin", "t", NULL
, offsetof(CGroupContext
, default_memory_min
), 0),
491 SD_BUS_PROPERTY("MemoryMin", "t", NULL
, offsetof(CGroupContext
, memory_min
), 0),
492 SD_BUS_PROPERTY("MemoryLow", "t", NULL
, offsetof(CGroupContext
, memory_low
), 0),
493 SD_BUS_PROPERTY("StartupMemoryLow", "t", NULL
, offsetof(CGroupContext
, startup_memory_low
), 0),
494 SD_BUS_PROPERTY("MemoryHigh", "t", NULL
, offsetof(CGroupContext
, memory_high
), 0),
495 SD_BUS_PROPERTY("StartupMemoryHigh", "t", NULL
, offsetof(CGroupContext
, startup_memory_high
), 0),
496 SD_BUS_PROPERTY("MemoryMax", "t", NULL
, offsetof(CGroupContext
, memory_max
), 0),
497 SD_BUS_PROPERTY("StartupMemoryMax", "t", NULL
, offsetof(CGroupContext
, startup_memory_max
), 0),
498 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL
, offsetof(CGroupContext
, memory_swap_max
), 0),
499 SD_BUS_PROPERTY("StartupMemorySwapMax", "t", NULL
, offsetof(CGroupContext
, startup_memory_swap_max
), 0),
500 SD_BUS_PROPERTY("MemoryZSwapMax", "t", NULL
, offsetof(CGroupContext
, memory_zswap_max
), 0),
501 SD_BUS_PROPERTY("StartupMemoryZSwapMax", "t", NULL
, offsetof(CGroupContext
, startup_memory_zswap_max
), 0),
502 SD_BUS_PROPERTY("MemoryLimit", "t", NULL
, offsetof(CGroupContext
, memory_limit
), 0),
503 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
504 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
505 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
506 SD_BUS_PROPERTY("TasksMax", "t", bus_property_get_tasks_max
, offsetof(CGroupContext
, tasks_max
), 0),
507 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, ip_accounting
), 0),
508 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_allow
), 0),
509 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_deny
), 0),
510 SD_BUS_PROPERTY("IPIngressFilterPath", "as", NULL
, offsetof(CGroupContext
, ip_filters_ingress
), 0),
511 SD_BUS_PROPERTY("IPEgressFilterPath", "as", NULL
, offsetof(CGroupContext
, ip_filters_egress
), 0),
512 SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask
, offsetof(CGroupContext
, disable_controllers
), 0),
513 SD_BUS_PROPERTY("ManagedOOMSwap", "s", property_get_managed_oom_mode
, offsetof(CGroupContext
, moom_swap
), 0),
514 SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode
, offsetof(CGroupContext
, moom_mem_pressure
), 0),
515 SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimit", "u", NULL
, offsetof(CGroupContext
, moom_mem_pressure_limit
), 0),
516 SD_BUS_PROPERTY("ManagedOOMPreference", "s", property_get_managed_oom_preference
, offsetof(CGroupContext
, moom_preference
), 0),
517 SD_BUS_PROPERTY("BPFProgram", "a(ss)", property_get_bpf_foreign_program
, 0, 0),
518 SD_BUS_PROPERTY("SocketBindAllow", "a(iiqq)", property_get_socket_bind
, offsetof(CGroupContext
, socket_bind_allow
), 0),
519 SD_BUS_PROPERTY("SocketBindDeny", "a(iiqq)", property_get_socket_bind
, offsetof(CGroupContext
, socket_bind_deny
), 0),
520 SD_BUS_PROPERTY("RestrictNetworkInterfaces", "(bas)", property_get_restrict_network_interfaces
, 0, 0),
521 SD_BUS_PROPERTY("MemoryPressureWatch", "s", bus_property_get_cgroup_pressure_watch
, offsetof(CGroupContext
, memory_pressure_watch
), 0),
522 SD_BUS_PROPERTY("MemoryPressureThresholdUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, memory_pressure_threshold_usec
), 0),
523 SD_BUS_PROPERTY("NFTSet", "a(iiss)", property_get_cgroup_nft_set
, 0, 0),
527 static int bus_cgroup_set_transient_property(
531 sd_bus_message
*message
,
532 UnitWriteFlags flags
,
533 sd_bus_error
*error
) {
542 flags
|= UNIT_PRIVATE
;
544 if (streq(name
, "Delegate")) {
547 if (!UNIT_VTABLE(u
)->can_delegate
)
548 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
550 r
= sd_bus_message_read(message
, "b", &b
);
554 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
556 c
->delegate_controllers
= b
? _CGROUP_MASK_ALL
: 0;
558 unit_write_settingf(u
, flags
, name
, "Delegate=%s", yes_no(b
));
563 } else if (streq(name
, "DelegateSubgroup")) {
566 if (!UNIT_VTABLE(u
)->can_delegate
)
567 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
569 r
= sd_bus_message_read(message
, "s", &s
);
573 if (!isempty(s
) && cg_needs_escape(s
))
574 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid control group name: %s", s
);
576 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
578 c
->delegate_subgroup
= mfree(c
->delegate_subgroup
);
580 r
= free_and_strdup_warn(&c
->delegate_subgroup
, s
);
585 unit_write_settingf(u
, flags
, name
, "DelegateSubgroup=%s", s
);
590 } else if (STR_IN_SET(name
, "DelegateControllers", "DisableControllers")) {
593 if (streq(name
, "DelegateControllers") && !UNIT_VTABLE(u
)->can_delegate
)
594 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
596 r
= sd_bus_message_enter_container(message
, 'a', "s");
604 r
= sd_bus_message_read(message
, "s", &t
);
610 cc
= cgroup_controller_from_string(t
);
612 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown cgroup controller '%s'", t
);
614 mask
|= CGROUP_CONTROLLER_TO_MASK(cc
);
617 r
= sd_bus_message_exit_container(message
);
621 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
622 _cleanup_free_
char *t
= NULL
;
624 r
= cg_mask_to_string(mask
, &t
);
628 if (streq(name
, "DelegateControllers")) {
632 c
->delegate_controllers
= 0;
634 c
->delegate_controllers
|= mask
;
636 unit_write_settingf(u
, flags
, name
, "Delegate=%s", strempty(t
));
638 } else if (streq(name
, "DisableControllers")) {
641 c
->disable_controllers
= 0;
643 c
->disable_controllers
|= mask
;
645 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, strempty(t
));
650 } else if (STR_IN_SET(name
, "IPIngressFilterPath", "IPEgressFilterPath")) {
654 filters
= streq(name
, "IPIngressFilterPath") ? &c
->ip_filters_ingress
: &c
->ip_filters_egress
;
655 r
= sd_bus_message_enter_container(message
, 'a', "s");
662 r
= sd_bus_message_read(message
, "s", &path
);
668 if (!path_is_normalized(path
) || !path_is_absolute(path
))
669 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects a normalized absolute path.", name
);
671 if (!UNIT_WRITE_FLAGS_NOOP(flags
) && !strv_contains(*filters
, path
)) {
672 r
= strv_extend(filters
, path
);
678 r
= sd_bus_message_exit_container(message
);
682 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
683 _cleanup_(memstream_done
) MemStream m
= {};
684 _cleanup_free_
char *buf
= NULL
;
688 *filters
= strv_free(*filters
);
690 unit_invalidate_cgroup_bpf(u
);
692 f
= memstream_init(&m
);
699 STRV_FOREACH(entry
, *filters
)
700 fprintf(f
, "%s=%s\n", name
, *entry
);
702 r
= memstream_finalize(&m
, &buf
, NULL
);
706 unit_write_setting(u
, flags
, name
, buf
);
709 r
= bpf_firewall_supported();
712 if (r
!= BPF_FIREWALL_SUPPORTED_WITH_MULTI
) {
713 static bool warned
= false;
715 log_full(warned
? LOG_DEBUG
: LOG_WARNING
,
716 "Transient unit %s configures an IP firewall with BPF, but the local system does not support BPF/cgroup firewalling with multiple filters.\n"
717 "Starting this unit will fail! (This warning is only shown for the first started transient unit using IP firewalling.)", u
->id
);
724 } else if (streq(name
, "BPFProgram")) {
728 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
732 while ((r
= sd_bus_message_read(message
, "(ss)", &a
, &p
)) > 0) {
733 int attach_type
= bpf_cgroup_attach_type_from_string(a
);
735 return sd_bus_error_setf(
737 SD_BUS_ERROR_INVALID_ARGS
,
738 "%s expects a valid BPF attach type, got '%s'.",
741 if (!path_is_normalized(p
) || !path_is_absolute(p
))
742 return sd_bus_error_setf(
744 SD_BUS_ERROR_INVALID_ARGS
,
745 "%s= expects a normalized absolute path.",
748 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
749 r
= cgroup_add_bpf_foreign_program(c
, attach_type
, p
);
758 r
= sd_bus_message_exit_container(message
);
762 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
763 _cleanup_(memstream_done
) MemStream m
= {};
764 _cleanup_free_
char *buf
= NULL
;
768 while (c
->bpf_foreign_programs
)
769 cgroup_context_remove_bpf_foreign_program(c
, c
->bpf_foreign_programs
);
771 f
= memstream_init(&m
);
778 LIST_FOREACH(programs
, fp
, c
->bpf_foreign_programs
)
779 fprintf(f
, "%s=%s:%s\n", name
,
780 bpf_cgroup_attach_type_to_string(fp
->attach_type
),
783 r
= memstream_finalize(&m
, &buf
, NULL
);
787 unit_write_setting(u
, flags
, name
, buf
);
789 if (c
->bpf_foreign_programs
) {
790 r
= bpf_foreign_supported();
795 "Transient unit %s configures a BPF program pinned to BPF "
796 "filesystem, but the local system does not support that.\n"
797 "Starting this unit will fail!", u
->id
);
803 } else if (streq(name
, "MemoryPressureWatch")) {
804 CGroupPressureWatch p
;
807 r
= sd_bus_message_read(message
, "s", &t
);
812 p
= _CGROUP_PRESSURE_WATCH_INVALID
;
814 p
= cgroup_pressure_watch_from_string(t
);
819 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
820 c
->memory_pressure_watch
= p
;
821 unit_write_settingf(u
, flags
, name
, "MemoryPressureWatch=%s", strempty(cgroup_pressure_watch_to_string(p
)));
826 } else if (streq(name
, "MemoryPressureThresholdUSec")) {
829 r
= sd_bus_message_read(message
, "t", &t
);
833 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
834 c
->memory_pressure_threshold_usec
= t
;
837 unit_write_setting(u
, flags
, name
, "MemoryPressureThresholdUSec=");
839 unit_write_settingf(u
, flags
, name
, "MemoryPressureThresholdUSec=%" PRIu64
, t
);
848 static int bus_cgroup_set_boolean(
853 sd_bus_message
*message
,
854 UnitWriteFlags flags
,
855 sd_bus_error
*error
) {
861 r
= sd_bus_message_read(message
, "b", &b
);
865 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
867 unit_invalidate_cgroup(u
, mask
);
868 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, yes_no(b
));
874 #define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \
875 static int bus_cgroup_set_##function( \
879 sd_bus_message *message, \
880 UnitWriteFlags flags, \
881 sd_bus_error *error) { \
888 r = sd_bus_message_read(message, "t", &v); \
893 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
894 "Value specified in %s is out of range", name); \
896 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
898 unit_invalidate_cgroup(u, mask); \
901 unit_write_settingf(u, flags, name, \
904 unit_write_settingf(u, flags, name, \
905 "%s=%" PRIu64, name, v); \
911 #define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \
912 static int bus_cgroup_set_##function( \
916 sd_bus_message *message, \
917 UnitWriteFlags flags, \
918 sd_bus_error *error) { \
925 r = sd_bus_message_read(message, "t", &v); \
930 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
931 "Value specified in %s is out of range", name); \
933 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
935 unit_invalidate_cgroup(u, mask); \
937 if (v == CGROUP_LIMIT_MAX) \
938 unit_write_settingf(u, flags, name, \
939 "%s=infinity", name); \
941 unit_write_settingf(u, flags, name, \
942 "%s=%" PRIu64, name, v); \
947 static int bus_cgroup_set_##function##_scale( \
951 sd_bus_message *message, \
952 UnitWriteFlags flags, \
953 sd_bus_error *error) { \
961 r = sd_bus_message_read(message, "u", &raw); \
965 v = scale(raw, UINT32_MAX); \
966 if (v < minimum || v >= UINT64_MAX) \
967 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
968 "Value specified in %s is out of range", name); \
970 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
972 unit_invalidate_cgroup(u, mask); \
974 /* Prepare to chop off suffix */ \
975 assert_se(endswith(name, "Scale")); \
977 int scaled = UINT32_SCALE_TO_PERMYRIAD(raw); \
978 unit_write_settingf(u, flags, name, "%.*s=" PERMYRIAD_AS_PERCENT_FORMAT_STR, \
979 (int)(strlen(name) - strlen("Scale")), name, \
980 PERMYRIAD_AS_PERCENT_FORMAT_VAL(scaled)); \
986 DISABLE_WARNING_TYPE_LIMITS
;
987 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares
, CGROUP_MASK_CPU
, CGROUP_CPU_SHARES_IS_OK
, CGROUP_CPU_SHARES_INVALID
);
988 BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight
, CGROUP_MASK_IO
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
989 BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight
, CGROUP_MASK_BLKIO
, CGROUP_BLKIO_WEIGHT_IS_OK
, CGROUP_BLKIO_WEIGHT_INVALID
);
990 BUS_DEFINE_SET_CGROUP_LIMIT(memory
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 1);
991 BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
992 BUS_DEFINE_SET_CGROUP_LIMIT(swap
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
993 BUS_DEFINE_SET_CGROUP_LIMIT(zswap
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
996 static int bus_cgroup_set_cpu_weight(
1000 sd_bus_message
*message
,
1001 UnitWriteFlags flags
,
1002 sd_bus_error
*error
) {
1006 r
= sd_bus_message_read(message
, "t", &v
);
1009 if (!CGROUP_WEIGHT_IS_OK(v
) && v
!= CGROUP_WEIGHT_IDLE
)
1010 return sd_bus_error_setf(
1011 error
, SD_BUS_ERROR_INVALID_ARGS
, "Value specified in %s is out of range", name
);
1012 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1014 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
1015 if (v
== CGROUP_WEIGHT_INVALID
)
1016 unit_write_settingf(u
, flags
, name
, "%s=", name
);
1017 else if (v
== CGROUP_WEIGHT_IDLE
)
1018 unit_write_settingf(u
, flags
, name
, "%s=idle", name
);
1020 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu64
, name
, v
);
1025 static int bus_cgroup_set_tasks_max(
1029 sd_bus_message
*message
,
1030 UnitWriteFlags flags
,
1031 sd_bus_error
*error
) {
1038 r
= sd_bus_message_read(message
, "t", &v
);
1043 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
1044 "Value specified in %s is out of range", name
);
1046 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1047 *p
= (TasksMax
) { .value
= v
, .scale
= 0 }; /* When .scale==0, .value is the absolute value */
1048 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1050 if (v
== CGROUP_LIMIT_MAX
)
1051 unit_write_settingf(u
, flags
, name
,
1052 "%s=infinity", name
);
1054 unit_write_settingf(u
, flags
, name
,
1055 "%s=%" PRIu64
, name
, v
);
1061 static int bus_cgroup_set_tasks_max_scale(
1065 sd_bus_message
*message
,
1066 UnitWriteFlags flags
,
1067 sd_bus_error
*error
) {
1074 r
= sd_bus_message_read(message
, "u", &v
);
1078 if (v
< 1 || v
>= UINT32_MAX
)
1079 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
1080 "Value specified in %s is out of range", name
);
1082 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1083 *p
= (TasksMax
) { v
, UINT32_MAX
}; /* .scale is not 0, so this is interpreted as v/UINT32_MAX. */
1084 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1086 uint32_t scaled
= DIV_ROUND_UP((uint64_t) v
* 100U, (uint64_t) UINT32_MAX
);
1087 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu32
".%" PRIu32
"%%", "TasksMax",
1088 scaled
/ 10, scaled
% 10);
1094 int bus_cgroup_set_property(
1098 sd_bus_message
*message
,
1099 UnitWriteFlags flags
,
1100 sd_bus_error
*error
) {
1102 CGroupIOLimitType iol_type
;
1110 flags
|= UNIT_PRIVATE
;
1112 if (streq(name
, "CPUAccounting"))
1113 return bus_cgroup_set_boolean(u
, name
, &c
->cpu_accounting
, get_cpu_accounting_mask(), message
, flags
, error
);
1115 if (streq(name
, "CPUWeight"))
1116 return bus_cgroup_set_cpu_weight(u
, name
, &c
->cpu_weight
, message
, flags
, error
);
1118 if (streq(name
, "StartupCPUWeight"))
1119 return bus_cgroup_set_cpu_weight(u
, name
, &c
->startup_cpu_weight
, message
, flags
, error
);
1121 if (streq(name
, "CPUShares"))
1122 return bus_cgroup_set_cpu_shares(u
, name
, &c
->cpu_shares
, message
, flags
, error
);
1124 if (streq(name
, "StartupCPUShares"))
1125 return bus_cgroup_set_cpu_shares(u
, name
, &c
->startup_cpu_shares
, message
, flags
, error
);
1127 if (streq(name
, "IOAccounting"))
1128 return bus_cgroup_set_boolean(u
, name
, &c
->io_accounting
, CGROUP_MASK_IO
, message
, flags
, error
);
1130 if (streq(name
, "IOWeight"))
1131 return bus_cgroup_set_io_weight(u
, name
, &c
->io_weight
, message
, flags
, error
);
1133 if (streq(name
, "StartupIOWeight"))
1134 return bus_cgroup_set_io_weight(u
, name
, &c
->startup_io_weight
, message
, flags
, error
);
1136 if (streq(name
, "BlockIOAccounting"))
1137 return bus_cgroup_set_boolean(u
, name
, &c
->blockio_accounting
, CGROUP_MASK_BLKIO
, message
, flags
, error
);
1139 if (streq(name
, "BlockIOWeight"))
1140 return bus_cgroup_set_blockio_weight(u
, name
, &c
->blockio_weight
, message
, flags
, error
);
1142 if (streq(name
, "StartupBlockIOWeight"))
1143 return bus_cgroup_set_blockio_weight(u
, name
, &c
->startup_blockio_weight
, message
, flags
, error
);
1145 if (streq(name
, "MemoryAccounting"))
1146 return bus_cgroup_set_boolean(u
, name
, &c
->memory_accounting
, CGROUP_MASK_MEMORY
, message
, flags
, error
);
1148 if (streq(name
, "MemoryMin")) {
1149 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->memory_min
, message
, flags
, error
);
1151 c
->memory_min_set
= true;
1155 if (streq(name
, "MemoryLow")) {
1156 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->memory_low
, message
, flags
, error
);
1158 c
->memory_low_set
= true;
1162 if (streq(name
, "StartupMemoryLow")) {
1163 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->startup_memory_low
, message
, flags
, error
);
1165 c
->startup_memory_low_set
= true;
1169 if (streq(name
, "DefaultMemoryMin")) {
1170 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->default_memory_min
, message
, flags
, error
);
1172 c
->default_memory_min_set
= true;
1176 if (streq(name
, "DefaultMemoryLow")) {
1177 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->default_memory_low
, message
, flags
, error
);
1179 c
->default_memory_low_set
= true;
1183 if (streq(name
, "DefaultStartupMemoryLow")) {
1184 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->default_startup_memory_low
, message
, flags
, error
);
1186 c
->default_startup_memory_low_set
= true;
1190 if (streq(name
, "MemoryHigh"))
1191 return bus_cgroup_set_memory(u
, name
, &c
->memory_high
, message
, flags
, error
);
1193 if (streq(name
, "StartupMemoryHigh")) {
1194 r
= bus_cgroup_set_memory(u
, name
, &c
->startup_memory_high
, message
, flags
, error
);
1196 c
->startup_memory_high_set
= true;
1200 if (streq(name
, "MemorySwapMax"))
1201 return bus_cgroup_set_swap(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
1203 if (streq(name
, "StartupMemorySwapMax")) {
1204 r
= bus_cgroup_set_swap(u
, name
, &c
->startup_memory_swap_max
, message
, flags
, error
);
1206 c
->startup_memory_swap_max_set
= true;
1210 if (streq(name
, "MemoryZSwapMax"))
1211 return bus_cgroup_set_zswap(u
, name
, &c
->memory_zswap_max
, message
, flags
, error
);
1213 if (streq(name
, "StartupMemoryZSwapMax")) {
1214 r
= bus_cgroup_set_zswap(u
, name
, &c
->startup_memory_zswap_max
, message
, flags
, error
);
1216 c
->startup_memory_zswap_max_set
= true;
1220 if (streq(name
, "MemoryMax"))
1221 return bus_cgroup_set_memory(u
, name
, &c
->memory_max
, message
, flags
, error
);
1223 if (streq(name
, "StartupMemoryMax")) {
1224 r
= bus_cgroup_set_memory(u
, name
, &c
->startup_memory_max
, message
, flags
, error
);
1226 c
->startup_memory_max_set
= true;
1230 if (streq(name
, "MemoryLimit"))
1231 return bus_cgroup_set_memory(u
, name
, &c
->memory_limit
, message
, flags
, error
);
1233 if (streq(name
, "MemoryMinScale")) {
1234 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->memory_min
, message
, flags
, error
);
1236 c
->memory_min_set
= true;
1240 if (streq(name
, "MemoryLowScale")) {
1241 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->memory_low
, message
, flags
, error
);
1243 c
->memory_low_set
= true;
1247 if (streq(name
, "DefaultMemoryMinScale")) {
1248 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->default_memory_min
, message
, flags
, error
);
1250 c
->default_memory_min_set
= true;
1254 if (streq(name
, "DefaultMemoryLowScale")) {
1255 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->default_memory_low
, message
, flags
, error
);
1257 c
->default_memory_low_set
= true;
1261 if (streq(name
, "MemoryHighScale"))
1262 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_high
, message
, flags
, error
);
1264 if (streq(name
, "MemorySwapMaxScale"))
1265 return bus_cgroup_set_swap_scale(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
1267 if (streq(name
, "MemoryZSwapMaxScale"))
1268 return bus_cgroup_set_zswap_scale(u
, name
, &c
->memory_zswap_max
, message
, flags
, error
);
1270 if (streq(name
, "MemoryMaxScale"))
1271 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_max
, message
, flags
, error
);
1273 if (streq(name
, "MemoryLimitScale"))
1274 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_limit
, message
, flags
, error
);
1276 if (streq(name
, "TasksAccounting"))
1277 return bus_cgroup_set_boolean(u
, name
, &c
->tasks_accounting
, CGROUP_MASK_PIDS
, message
, flags
, error
);
1279 if (streq(name
, "TasksMax"))
1280 return bus_cgroup_set_tasks_max(u
, name
, &c
->tasks_max
, message
, flags
, error
);
1282 if (streq(name
, "TasksMaxScale"))
1283 return bus_cgroup_set_tasks_max_scale(u
, name
, &c
->tasks_max
, message
, flags
, error
);
1285 if (streq(name
, "CPUQuotaPerSecUSec")) {
1288 r
= sd_bus_message_read(message
, "t", &u64
);
1293 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "CPUQuotaPerSecUSec= value out of range");
1295 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1296 c
->cpu_quota_per_sec_usec
= u64
;
1297 u
->warned_clamping_cpu_quota_period
= false;
1298 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
1300 if (c
->cpu_quota_per_sec_usec
== USEC_INFINITY
)
1301 unit_write_setting(u
, flags
, "CPUQuota", "CPUQuota=");
1303 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
1305 unit_write_settingf(u
, flags
, "CPUQuota",
1307 (double) (c
->cpu_quota_per_sec_usec
/ 10000));
1312 } else if (streq(name
, "CPUQuotaPeriodUSec")) {
1315 r
= sd_bus_message_read(message
, "t", &u64
);
1319 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1320 c
->cpu_quota_period_usec
= u64
;
1321 u
->warned_clamping_cpu_quota_period
= false;
1322 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
1323 if (c
->cpu_quota_period_usec
== USEC_INFINITY
)
1324 unit_write_setting(u
, flags
, "CPUQuotaPeriodSec", "CPUQuotaPeriodSec=");
1326 unit_write_settingf(u
, flags
, "CPUQuotaPeriodSec",
1327 "CPUQuotaPeriodSec=%s",
1328 FORMAT_TIMESPAN(c
->cpu_quota_period_usec
, 1));
1333 } else if (STR_IN_SET(name
, "AllowedCPUs", "StartupAllowedCPUs", "AllowedMemoryNodes", "StartupAllowedMemoryNodes")) {
1336 _cleanup_(cpu_set_reset
) CPUSet new_set
= {};
1338 r
= sd_bus_message_read_array(message
, 'y', &a
, &n
);
1342 r
= cpu_set_from_dbus(a
, n
, &new_set
);
1346 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1347 _cleanup_free_
char *setstr
= NULL
;
1350 setstr
= cpu_set_to_range_string(&new_set
);
1354 if (streq(name
, "AllowedCPUs"))
1355 set
= &c
->cpuset_cpus
;
1356 else if (streq(name
, "StartupAllowedCPUs"))
1357 set
= &c
->startup_cpuset_cpus
;
1358 else if (streq(name
, "AllowedMemoryNodes"))
1359 set
= &c
->cpuset_mems
;
1360 else if (streq(name
, "StartupAllowedMemoryNodes"))
1361 set
= &c
->startup_cpuset_mems
;
1367 new_set
= (CPUSet
) {};
1369 unit_invalidate_cgroup(u
, CGROUP_MASK_CPUSET
);
1370 unit_write_settingf(u
, flags
, name
, "%s=\n%s=%s", name
, name
, setstr
);
1375 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
1380 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1384 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
1386 if (!path_is_normalized(path
))
1387 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1389 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1390 CGroupIODeviceLimit
*a
= NULL
;
1392 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
)
1393 if (path_equal(path
, b
->path
)) {
1399 CGroupIOLimitType type
;
1401 a
= new0(CGroupIODeviceLimit
, 1);
1405 a
->path
= strdup(path
);
1411 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
1412 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
1414 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
1417 a
->limits
[iol_type
] = u64
;
1425 r
= sd_bus_message_exit_container(message
);
1429 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1430 _cleanup_(memstream_done
) MemStream m
= {};
1431 _cleanup_free_
char *buf
= NULL
;
1435 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
1436 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
1438 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1440 f
= memstream_init(&m
);
1444 fprintf(f
, "%s=\n", name
);
1445 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
1446 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
1447 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
1449 r
= memstream_finalize(&m
, &buf
, NULL
);
1453 unit_write_setting(u
, flags
, name
, buf
);
1458 } else if (streq(name
, "IODeviceWeight")) {
1463 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1467 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
1469 if (!path_is_normalized(path
))
1470 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1472 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
1473 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "IODeviceWeight= value out of range");
1475 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1476 CGroupIODeviceWeight
*a
= NULL
;
1478 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
)
1479 if (path_equal(b
->path
, path
)) {
1485 a
= new0(CGroupIODeviceWeight
, 1);
1489 a
->path
= strdup(path
);
1494 LIST_PREPEND(device_weights
, c
->io_device_weights
, a
);
1503 r
= sd_bus_message_exit_container(message
);
1507 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1508 _cleanup_(memstream_done
) MemStream m
= {};
1509 _cleanup_free_
char *buf
= NULL
;
1513 while (c
->io_device_weights
)
1514 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
1516 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1518 f
= memstream_init(&m
);
1522 fputs("IODeviceWeight=\n", f
);
1523 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
1524 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1526 r
= memstream_finalize(&m
, &buf
, NULL
);
1530 unit_write_setting(u
, flags
, name
, buf
);
1535 } else if (streq(name
, "IODeviceLatencyTargetUSec")) {
1540 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1544 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &target
)) > 0) {
1546 if (!path_is_normalized(path
))
1547 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1549 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1550 CGroupIODeviceLatency
*a
= NULL
;
1552 LIST_FOREACH(device_latencies
, b
, c
->io_device_latencies
)
1553 if (path_equal(b
->path
, path
)) {
1559 a
= new0(CGroupIODeviceLatency
, 1);
1563 a
->path
= strdup(path
);
1568 LIST_PREPEND(device_latencies
, c
->io_device_latencies
, a
);
1571 a
->target_usec
= target
;
1577 r
= sd_bus_message_exit_container(message
);
1581 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1582 _cleanup_(memstream_done
) MemStream m
= {};
1583 _cleanup_free_
char *buf
= NULL
;
1587 while (c
->io_device_latencies
)
1588 cgroup_context_free_io_device_latency(c
, c
->io_device_latencies
);
1590 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1592 f
= memstream_init(&m
);
1596 fputs("IODeviceLatencyTargetSec=\n", f
);
1597 LIST_FOREACH(device_latencies
, a
, c
->io_device_latencies
)
1598 fprintf(f
, "IODeviceLatencyTargetSec=%s %s\n",
1599 a
->path
, FORMAT_TIMESPAN(a
->target_usec
, 1));
1601 r
= memstream_finalize(&m
, &buf
, NULL
);
1605 unit_write_setting(u
, flags
, name
, buf
);
1610 } else if (STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1616 read
= streq(name
, "BlockIOReadBandwidth");
1618 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1622 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
1624 if (!path_is_normalized(path
))
1625 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1627 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1628 CGroupBlockIODeviceBandwidth
*a
= NULL
;
1630 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
)
1631 if (path_equal(path
, b
->path
)) {
1637 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
1641 a
->rbps
= CGROUP_LIMIT_MAX
;
1642 a
->wbps
= CGROUP_LIMIT_MAX
;
1643 a
->path
= strdup(path
);
1649 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
1663 r
= sd_bus_message_exit_container(message
);
1667 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1668 _cleanup_(memstream_done
) MemStream m
= {};
1669 _cleanup_free_
char *buf
= NULL
;
1673 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
1675 a
->rbps
= CGROUP_LIMIT_MAX
;
1677 a
->wbps
= CGROUP_LIMIT_MAX
;
1680 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1682 f
= memstream_init(&m
);
1687 fputs("BlockIOReadBandwidth=\n", f
);
1688 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
1689 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
1690 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
1692 fputs("BlockIOWriteBandwidth=\n", f
);
1693 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
1694 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
1695 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
1698 r
= memstream_finalize(&m
, &buf
, NULL
);
1702 unit_write_setting(u
, flags
, name
, buf
);
1707 } else if (streq(name
, "BlockIODeviceWeight")) {
1712 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1716 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
1718 if (!path_is_normalized(path
))
1719 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1721 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
1722 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "BlockIODeviceWeight= out of range");
1724 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1725 CGroupBlockIODeviceWeight
*a
= NULL
;
1727 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
)
1728 if (path_equal(b
->path
, path
)) {
1734 a
= new0(CGroupBlockIODeviceWeight
, 1);
1738 a
->path
= strdup(path
);
1743 LIST_PREPEND(device_weights
, c
->blockio_device_weights
, a
);
1752 r
= sd_bus_message_exit_container(message
);
1756 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1757 _cleanup_(memstream_done
) MemStream m
= {};
1758 _cleanup_free_
char *buf
= NULL
;
1762 while (c
->blockio_device_weights
)
1763 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
1765 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1767 f
= memstream_init(&m
);
1771 fputs("BlockIODeviceWeight=\n", f
);
1772 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
1773 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1775 r
= memstream_finalize(&m
, &buf
, NULL
);
1779 unit_write_setting(u
, flags
, name
, buf
);
1784 } else if (streq(name
, "DevicePolicy")) {
1786 CGroupDevicePolicy p
;
1788 r
= sd_bus_message_read(message
, "s", &policy
);
1792 p
= cgroup_device_policy_from_string(policy
);
1796 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1797 c
->device_policy
= p
;
1798 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1799 unit_write_settingf(u
, flags
, name
, "DevicePolicy=%s", policy
);
1804 } else if (streq(name
, "DeviceAllow")) {
1805 const char *path
, *rwm
;
1808 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
1812 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
1814 if (!valid_device_allow_pattern(path
) || strpbrk(path
, WHITESPACE
))
1815 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires device node or pattern");
1819 else if (!in_charset(rwm
, "rwm"))
1820 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires combination of rwm flags");
1822 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1823 CGroupDeviceAllow
*a
= NULL
;
1825 LIST_FOREACH(device_allow
, b
, c
->device_allow
)
1826 if (path_equal(b
->path
, path
)) {
1832 a
= new0(CGroupDeviceAllow
, 1);
1836 a
->path
= strdup(path
);
1842 LIST_PREPEND(device_allow
, c
->device_allow
, a
);
1845 a
->r
= strchr(rwm
, 'r');
1846 a
->w
= strchr(rwm
, 'w');
1847 a
->m
= strchr(rwm
, 'm');
1855 r
= sd_bus_message_exit_container(message
);
1859 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1860 _cleanup_(memstream_done
) MemStream m
= {};
1861 _cleanup_free_
char *buf
= NULL
;
1865 while (c
->device_allow
)
1866 cgroup_context_free_device_allow(c
, c
->device_allow
);
1868 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1870 f
= memstream_init(&m
);
1874 fputs("DeviceAllow=\n", f
);
1875 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
1876 fprintf(f
, "DeviceAllow=%s %s%s%s\n", a
->path
, a
->r
? "r" : "", a
->w
? "w" : "", a
->m
? "m" : "");
1878 r
= memstream_finalize(&m
, &buf
, NULL
);
1882 unit_write_setting(u
, flags
, name
, buf
);
1887 } else if (streq(name
, "IPAccounting")) {
1890 r
= sd_bus_message_read(message
, "b", &b
);
1894 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1895 c
->ip_accounting
= b
;
1897 unit_invalidate_cgroup_bpf(u
);
1898 unit_write_settingf(u
, flags
, name
, "IPAccounting=%s", yes_no(b
));
1903 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1904 _cleanup_set_free_ Set
*new_prefixes
= NULL
;
1907 r
= sd_bus_message_enter_container(message
, 'a', "(iayu)");
1917 r
= sd_bus_message_enter_container(message
, 'r', "iayu");
1923 r
= sd_bus_message_read(message
, "i", &family
);
1927 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1928 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects IPv4 or IPv6 addresses only.", name
);
1930 r
= sd_bus_message_read_array(message
, 'y', &ap
, &an
);
1934 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1935 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1936 af_to_name(family
), FAMILY_ADDRESS_SIZE(family
), an
);
1938 r
= sd_bus_message_read(message
, "u", &prefixlen
);
1942 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
)*8)
1943 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Prefix length %" PRIu32
" too large for address family %s.", prefixlen
, af_to_name(family
));
1945 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1946 struct in_addr_prefix prefix
= {
1948 .prefixlen
= prefixlen
,
1951 memcpy(&prefix
.address
, ap
, an
);
1953 r
= in_addr_prefix_add(&new_prefixes
, &prefix
);
1958 r
= sd_bus_message_exit_container(message
);
1965 r
= sd_bus_message_exit_container(message
);
1969 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1970 _cleanup_(memstream_done
) MemStream m
= {};
1971 _cleanup_free_
char *buf
= NULL
;
1976 unit_invalidate_cgroup_bpf(u
);
1978 f
= memstream_init(&m
);
1982 prefixes
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow
: &c
->ip_address_deny
;
1983 reduced
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow_reduced
: &c
->ip_address_deny_reduced
;
1987 *prefixes
= set_free(*prefixes
);
1993 r
= in_addr_prefixes_merge(prefixes
, new_prefixes
);
1997 const struct in_addr_prefix
*p
;
1998 SET_FOREACH(p
, new_prefixes
)
1999 fprintf(f
, "%s=%s\n", name
,
2000 IN_ADDR_PREFIX_TO_STRING(p
->family
, &p
->address
, p
->prefixlen
));
2003 r
= memstream_finalize(&m
, &buf
, NULL
);
2007 unit_write_setting(u
, flags
, name
, buf
);
2013 if (STR_IN_SET(name
, "ManagedOOMSwap", "ManagedOOMMemoryPressure")) {
2014 ManagedOOMMode
*cgroup_mode
= streq(name
, "ManagedOOMSwap") ? &c
->moom_swap
: &c
->moom_mem_pressure
;
2018 if (!UNIT_VTABLE(u
)->can_set_managed_oom
)
2019 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot set %s for this unit type", name
);
2021 r
= sd_bus_message_read(message
, "s", &mode
);
2025 m
= managed_oom_mode_from_string(mode
);
2029 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2031 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, mode
);
2034 (void) manager_varlink_send_managed_oom_update(u
);
2038 if (streq(name
, "ManagedOOMMemoryPressureLimit")) {
2041 if (!UNIT_VTABLE(u
)->can_set_managed_oom
)
2042 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot set %s for this unit type", name
);
2044 r
= sd_bus_message_read(message
, "u", &v
);
2048 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2049 c
->moom_mem_pressure_limit
= v
;
2050 unit_write_settingf(u
, flags
, name
,
2051 "ManagedOOMMemoryPressureLimit=" PERMYRIAD_AS_PERCENT_FORMAT_STR
,
2052 PERMYRIAD_AS_PERCENT_FORMAT_VAL(UINT32_SCALE_TO_PERMYRIAD(v
)));
2055 if (c
->moom_mem_pressure
== MANAGED_OOM_KILL
)
2056 (void) manager_varlink_send_managed_oom_update(u
);
2061 if (streq(name
, "ManagedOOMPreference")) {
2062 ManagedOOMPreference p
;
2065 r
= sd_bus_message_read(message
, "s", &pref
);
2069 p
= managed_oom_preference_from_string(pref
);
2073 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2074 c
->moom_preference
= p
;
2075 unit_write_settingf(u
, flags
, name
, "ManagedOOMPreference=%s", pref
);
2080 if (STR_IN_SET(name
, "SocketBindAllow", "SocketBindDeny")) {
2081 CGroupSocketBindItem
**list
;
2082 uint16_t nr_ports
, port_min
;
2084 int32_t family
, ip_protocol
;
2086 list
= streq(name
, "SocketBindAllow") ? &c
->socket_bind_allow
: &c
->socket_bind_deny
;
2088 r
= sd_bus_message_enter_container(message
, 'a', "(iiqq)");
2092 while ((r
= sd_bus_message_read(message
, "(iiqq)", &family
, &ip_protocol
, &nr_ports
, &port_min
)) > 0) {
2094 if (!IN_SET(family
, AF_UNSPEC
, AF_INET
, AF_INET6
))
2095 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects INET or INET6 family, if specified.", name
);
2097 if (!IN_SET(ip_protocol
, 0, IPPROTO_TCP
, IPPROTO_UDP
))
2098 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects TCP or UDP protocol, if specified.", name
);
2100 if (port_min
+ (uint32_t) nr_ports
> (1 << 16))
2101 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects maximum port value lesser than 65536.", name
);
2103 if (port_min
== 0 && nr_ports
!= 0)
2104 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects port range starting with positive value.", name
);
2106 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2107 _cleanup_free_ CGroupSocketBindItem
*item
= NULL
;
2109 item
= new(CGroupSocketBindItem
, 1);
2113 *item
= (CGroupSocketBindItem
) {
2114 .address_family
= family
,
2115 .ip_protocol
= ip_protocol
,
2116 .nr_ports
= nr_ports
,
2117 .port_min
= port_min
2120 LIST_PREPEND(socket_bind_items
, *list
, TAKE_PTR(item
));
2127 r
= sd_bus_message_exit_container(message
);
2131 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2132 _cleanup_(memstream_done
) MemStream m
= {};
2133 _cleanup_free_
char *buf
= NULL
;
2137 cgroup_context_remove_socket_bind(list
);
2139 if ((u
->manager
->cgroup_supported
& CGROUP_MASK_BPF_SOCKET_BIND
) == 0)
2141 "Unit %s configures source compiled BPF programs "
2142 "but the local system does not support that.\n"
2143 "Starting this unit will fail!", u
->id
);
2146 f
= memstream_init(&m
);
2151 fprintf(f
, "%s=\n", name
);
2153 LIST_FOREACH(socket_bind_items
, item
, *list
) {
2154 fprintf(f
, "%s=", name
);
2155 cgroup_context_dump_socket_bind_item(item
, f
);
2159 r
= memstream_finalize(&m
, &buf
, NULL
);
2163 unit_write_setting(u
, flags
, name
, buf
);
2168 if (streq(name
, "RestrictNetworkInterfaces")) {
2170 _cleanup_strv_free_
char **l
= NULL
;
2172 r
= sd_bus_message_enter_container(message
, 'r', "bas");
2176 r
= sd_bus_message_read(message
, "b", &is_allow_list
);
2180 r
= sd_bus_message_read_strv(message
, &l
);
2184 r
= sd_bus_message_exit_container(message
);
2188 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2189 _cleanup_free_
char *joined
= NULL
;
2191 if (strv_isempty(l
)) {
2192 c
->restrict_network_interfaces_is_allow_list
= false;
2193 c
->restrict_network_interfaces
= set_free_free(c
->restrict_network_interfaces
);
2195 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2199 if (set_isempty(c
->restrict_network_interfaces
))
2200 c
->restrict_network_interfaces_is_allow_list
= is_allow_list
;
2202 STRV_FOREACH(s
, l
) {
2203 if (!ifname_valid(*s
)) {
2204 log_full(LOG_WARNING
, "Invalid interface name, ignoring: %s", *s
);
2207 if (c
->restrict_network_interfaces_is_allow_list
!= (bool) is_allow_list
)
2208 free(set_remove(c
->restrict_network_interfaces
, *s
));
2210 r
= set_put_strdup(&c
->restrict_network_interfaces
, *s
);
2216 joined
= strv_join(l
, " ");
2220 unit_write_settingf(u
, flags
, name
, "%s=%s%s", name
, is_allow_list
? "" : "~", joined
);
2226 if (streq(name
, "NFTSet")) {
2227 int source
, nfproto
;
2228 const char *table
, *set
;
2231 r
= sd_bus_message_enter_container(message
, 'a', "(iiss)");
2235 while ((r
= sd_bus_message_read(message
, "(iiss)", &source
, &nfproto
, &table
, &set
)) > 0) {
2236 const char *source_name
, *nfproto_name
;
2238 if (!IN_SET(source
, NFT_SET_SOURCE_CGROUP
, NFT_SET_SOURCE_USER
, NFT_SET_SOURCE_GROUP
))
2239 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid source %d.", source
);
2241 source_name
= nft_set_source_to_string(source
);
2242 assert(source_name
);
2244 nfproto_name
= nfproto_to_string(nfproto
);
2246 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid protocol %d.", nfproto
);
2248 if (!nft_identifier_valid(table
)) {
2249 _cleanup_free_
char *esc
= NULL
;
2251 esc
= cescape(table
);
2252 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid NFT table name %s.", strna(esc
));
2255 if (!nft_identifier_valid(set
)) {
2256 _cleanup_free_
char *esc
= NULL
;
2259 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid NFT set name %s.", strna(esc
));
2262 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2263 r
= nft_set_add(&c
->nft_set_context
, source
, nfproto
, table
, set
);
2267 unit_write_settingf(
2268 u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
,
2282 r
= sd_bus_message_exit_container(message
);
2286 if (empty
&& !UNIT_WRITE_FLAGS_NOOP(flags
)) {
2287 nft_set_context_clear(&c
->nft_set_context
);
2288 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2295 if (streq(name
, "DisableControllers") || (u
->transient
&& u
->load_state
== UNIT_STUB
))
2296 return bus_cgroup_set_transient_property(u
, c
, name
, message
, flags
, error
);