1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include "alloc-util.h"
5 #include "bpf-program.h"
6 #include "bus-get-properties.h"
7 #include "bus-message-util.h"
9 #include "cgroup-util.h"
10 #include "dbus-cgroup.h"
12 #include "firewall-util.h"
13 #include "in-addr-prefix-util.h"
14 #include "limits-util.h"
16 #include "memstream-util.h"
17 #include "parse-util.h"
18 #include "path-util.h"
19 #include "percent-util.h"
21 #include "socket-util.h"
22 #include "string-util.h"
26 BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max
, "t", CGroupTasksMax
, cgroup_tasks_max_resolve
);
27 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_cgroup_pressure_watch
, cgroup_pressure_watch
, CGroupPressureWatch
);
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
);
33 static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_blockio_ast
, "a(st)", 0);
35 static int property_get_cgroup_mask(
38 const char *interface
,
40 sd_bus_message
*reply
,
42 sd_bus_error
*error
) {
44 CGroupMask
*mask
= userdata
;
50 r
= sd_bus_message_open_container(reply
, 'a', "s");
54 for (CGroupController ctrl
= 0; ctrl
< _CGROUP_CONTROLLER_MAX
; ctrl
++) {
55 if ((*mask
& CGROUP_CONTROLLER_TO_MASK(ctrl
)) == 0)
58 r
= sd_bus_message_append(reply
, "s", cgroup_controller_to_string(ctrl
));
63 return sd_bus_message_close_container(reply
);
66 static int property_get_delegate_controllers(
69 const char *interface
,
71 sd_bus_message
*reply
,
73 sd_bus_error
*error
) {
75 CGroupContext
*c
= ASSERT_PTR(userdata
);
81 return sd_bus_message_append(reply
, "as", 0);
83 return property_get_cgroup_mask(bus
, path
, interface
, property
, reply
, &c
->delegate_controllers
, error
);
86 static int property_get_cpuset(
89 const char *interface
,
91 sd_bus_message
*reply
,
93 sd_bus_error
*error
) {
95 CPUSet
*cpus
= ASSERT_PTR(userdata
);
96 _cleanup_free_
uint8_t *array
= NULL
;
102 (void) cpu_set_to_dbus(cpus
, &array
, &allocated
);
103 return sd_bus_message_append_array(reply
, 'y', array
, allocated
);
106 static int property_get_io_device_weight(
109 const char *interface
,
110 const char *property
,
111 sd_bus_message
*reply
,
113 sd_bus_error
*error
) {
115 CGroupContext
*c
= ASSERT_PTR(userdata
);
121 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
125 LIST_FOREACH(device_weights
, w
, c
->io_device_weights
) {
126 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
131 return sd_bus_message_close_container(reply
);
134 static int property_get_io_device_limits(
137 const char *interface
,
138 const char *property
,
139 sd_bus_message
*reply
,
141 sd_bus_error
*error
) {
143 CGroupContext
*c
= ASSERT_PTR(userdata
);
149 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
153 LIST_FOREACH(device_limits
, l
, c
->io_device_limits
) {
154 CGroupIOLimitType type
;
156 type
= cgroup_io_limit_type_from_string(property
);
157 if (type
< 0 || l
->limits
[type
] == cgroup_io_limit_defaults
[type
])
160 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->limits
[type
]);
165 return sd_bus_message_close_container(reply
);
168 static int property_get_io_device_latency(
171 const char *interface
,
172 const char *property
,
173 sd_bus_message
*reply
,
175 sd_bus_error
*error
) {
177 CGroupContext
*c
= ASSERT_PTR(userdata
);
183 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
187 LIST_FOREACH(device_latencies
, l
, c
->io_device_latencies
) {
188 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->target_usec
);
193 return sd_bus_message_close_container(reply
);
196 static int property_get_device_allow(
199 const char *interface
,
200 const char *property
,
201 sd_bus_message
*reply
,
203 sd_bus_error
*error
) {
205 CGroupContext
*c
= ASSERT_PTR(userdata
);
211 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
215 LIST_FOREACH(device_allow
, a
, c
->device_allow
) {
216 r
= sd_bus_message_append(reply
, "(ss)", a
->path
, cgroup_device_permissions_to_string(a
->permissions
));
221 return sd_bus_message_close_container(reply
);
224 static int property_get_ip_address_access(
227 const char *interface
,
228 const char *property
,
229 sd_bus_message
*reply
,
231 sd_bus_error
*error
) {
233 Set
**prefixes
= ASSERT_PTR(userdata
);
234 struct in_addr_prefix
*i
;
237 r
= sd_bus_message_open_container(reply
, 'a', "(iayu)");
241 SET_FOREACH(i
, *prefixes
) {
243 r
= sd_bus_message_open_container(reply
, 'r', "iayu");
247 r
= sd_bus_message_append(reply
, "i", i
->family
);
251 r
= sd_bus_message_append_array(reply
, 'y', &i
->address
, FAMILY_ADDRESS_SIZE(i
->family
));
255 r
= sd_bus_message_append(reply
, "u", (uint32_t) i
->prefixlen
);
259 r
= sd_bus_message_close_container(reply
);
264 return sd_bus_message_close_container(reply
);
267 static int property_get_bpf_foreign_program(
270 const char *interface
,
271 const char *property
,
272 sd_bus_message
*reply
,
274 sd_bus_error
*error
) {
275 CGroupContext
*c
= userdata
;
278 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
282 LIST_FOREACH(programs
, p
, c
->bpf_foreign_programs
) {
283 const char *attach_type
= bpf_cgroup_attach_type_to_string(p
->attach_type
);
285 r
= sd_bus_message_append(reply
, "(ss)", attach_type
, p
->bpffs_path
);
290 return sd_bus_message_close_container(reply
);
293 static int property_get_socket_bind(
296 const char *interface
,
297 const char *property
,
298 sd_bus_message
*reply
,
300 sd_bus_error
*error
) {
302 CGroupSocketBindItem
**items
= ASSERT_PTR(userdata
);
305 r
= sd_bus_message_open_container(reply
, 'a', "(iiqq)");
309 LIST_FOREACH(socket_bind_items
, i
, *items
) {
310 r
= sd_bus_message_append(reply
, "(iiqq)", i
->address_family
, i
->ip_protocol
, i
->nr_ports
, i
->port_min
);
315 return sd_bus_message_close_container(reply
);
318 static int property_get_restrict_network_interfaces(
321 const char *interface
,
322 const char *property
,
323 sd_bus_message
*reply
,
325 sd_bus_error
*error
) {
327 CGroupContext
*c
= ASSERT_PTR(userdata
);
333 r
= sd_bus_message_open_container(reply
, 'r', "bas");
337 r
= sd_bus_message_append(reply
, "b", c
->restrict_network_interfaces_is_allow_list
);
341 r
= bus_message_append_string_set(reply
, c
->restrict_network_interfaces
);
345 return sd_bus_message_close_container(reply
);
348 static int property_get_cgroup_nft_set(
351 const char *interface
,
352 const char *property
,
353 sd_bus_message
*reply
,
355 sd_bus_error
*error
) {
357 CGroupContext
*c
= userdata
;
363 r
= sd_bus_message_open_container(reply
, 'a', "(iiss)");
367 FOREACH_ARRAY(nft_set
, c
->nft_set_context
.sets
, c
->nft_set_context
.n_sets
) {
368 r
= sd_bus_message_append(reply
, "(iiss)", nft_set
->source
, nft_set
->nfproto
, nft_set
->table
, nft_set
->set
);
373 return sd_bus_message_close_container(reply
);
376 const sd_bus_vtable bus_cgroup_vtable
[] = {
377 SD_BUS_VTABLE_START(0),
378 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool
, offsetof(CGroupContext
, delegate
), 0),
379 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers
, 0, 0),
380 SD_BUS_PROPERTY("DelegateSubgroup", "s", NULL
, offsetof(CGroupContext
, delegate_subgroup
), 0),
381 SD_BUS_PROPERTY("CPUWeight", "t", NULL
, offsetof(CGroupContext
, cpu_weight
), 0),
382 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL
, offsetof(CGroupContext
, startup_cpu_weight
), 0),
383 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_per_sec_usec
), 0),
384 SD_BUS_PROPERTY("CPUQuotaPeriodUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_period_usec
), 0),
385 SD_BUS_PROPERTY("AllowedCPUs", "ay", property_get_cpuset
, offsetof(CGroupContext
, cpuset_cpus
), 0),
386 SD_BUS_PROPERTY("StartupAllowedCPUs", "ay", property_get_cpuset
, offsetof(CGroupContext
, startup_cpuset_cpus
), 0),
387 SD_BUS_PROPERTY("AllowedMemoryNodes", "ay", property_get_cpuset
, offsetof(CGroupContext
, cpuset_mems
), 0),
388 SD_BUS_PROPERTY("StartupAllowedMemoryNodes", "ay", property_get_cpuset
, offsetof(CGroupContext
, startup_cpuset_mems
), 0),
389 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, io_accounting
), 0),
390 SD_BUS_PROPERTY("IOWeight", "t", NULL
, offsetof(CGroupContext
, io_weight
), 0),
391 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_io_weight
), 0),
392 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight
, 0, 0),
393 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
394 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
395 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
396 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
397 SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency
, 0, 0),
398 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_accounting
), 0),
399 SD_BUS_PROPERTY("DefaultMemoryLow", "t", NULL
, offsetof(CGroupContext
, default_memory_low
), 0),
400 SD_BUS_PROPERTY("DefaultStartupMemoryLow", "t", NULL
, offsetof(CGroupContext
, default_startup_memory_low
), 0),
401 SD_BUS_PROPERTY("DefaultMemoryMin", "t", NULL
, offsetof(CGroupContext
, default_memory_min
), 0),
402 SD_BUS_PROPERTY("MemoryMin", "t", NULL
, offsetof(CGroupContext
, memory_min
), 0),
403 SD_BUS_PROPERTY("MemoryLow", "t", NULL
, offsetof(CGroupContext
, memory_low
), 0),
404 SD_BUS_PROPERTY("StartupMemoryLow", "t", NULL
, offsetof(CGroupContext
, startup_memory_low
), 0),
405 SD_BUS_PROPERTY("MemoryHigh", "t", NULL
, offsetof(CGroupContext
, memory_high
), 0),
406 SD_BUS_PROPERTY("StartupMemoryHigh", "t", NULL
, offsetof(CGroupContext
, startup_memory_high
), 0),
407 SD_BUS_PROPERTY("MemoryMax", "t", NULL
, offsetof(CGroupContext
, memory_max
), 0),
408 SD_BUS_PROPERTY("StartupMemoryMax", "t", NULL
, offsetof(CGroupContext
, startup_memory_max
), 0),
409 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL
, offsetof(CGroupContext
, memory_swap_max
), 0),
410 SD_BUS_PROPERTY("StartupMemorySwapMax", "t", NULL
, offsetof(CGroupContext
, startup_memory_swap_max
), 0),
411 SD_BUS_PROPERTY("MemoryZSwapMax", "t", NULL
, offsetof(CGroupContext
, memory_zswap_max
), 0),
412 SD_BUS_PROPERTY("StartupMemoryZSwapMax", "t", NULL
, offsetof(CGroupContext
, startup_memory_zswap_max
), 0),
413 SD_BUS_PROPERTY("MemoryZSwapWriteback", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_zswap_writeback
), 0),
414 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
415 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
416 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
417 SD_BUS_PROPERTY("TasksMax", "t", bus_property_get_tasks_max
, offsetof(CGroupContext
, tasks_max
), 0),
418 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, ip_accounting
), 0),
419 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_allow
), 0),
420 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_deny
), 0),
421 SD_BUS_PROPERTY("IPIngressFilterPath", "as", NULL
, offsetof(CGroupContext
, ip_filters_ingress
), 0),
422 SD_BUS_PROPERTY("IPEgressFilterPath", "as", NULL
, offsetof(CGroupContext
, ip_filters_egress
), 0),
423 SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask
, offsetof(CGroupContext
, disable_controllers
), 0),
424 SD_BUS_PROPERTY("ManagedOOMSwap", "s", property_get_managed_oom_mode
, offsetof(CGroupContext
, moom_swap
), 0),
425 SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode
, offsetof(CGroupContext
, moom_mem_pressure
), 0),
426 SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimit", "u", NULL
, offsetof(CGroupContext
, moom_mem_pressure_limit
), 0),
427 SD_BUS_PROPERTY("ManagedOOMMemoryPressureDurationUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, moom_mem_pressure_duration_usec
), 0),
428 SD_BUS_PROPERTY("ManagedOOMPreference", "s", property_get_managed_oom_preference
, offsetof(CGroupContext
, moom_preference
), 0),
429 SD_BUS_PROPERTY("BPFProgram", "a(ss)", property_get_bpf_foreign_program
, 0, 0),
430 SD_BUS_PROPERTY("SocketBindAllow", "a(iiqq)", property_get_socket_bind
, offsetof(CGroupContext
, socket_bind_allow
), 0),
431 SD_BUS_PROPERTY("SocketBindDeny", "a(iiqq)", property_get_socket_bind
, offsetof(CGroupContext
, socket_bind_deny
), 0),
432 SD_BUS_PROPERTY("RestrictNetworkInterfaces", "(bas)", property_get_restrict_network_interfaces
, 0, 0),
433 SD_BUS_PROPERTY("MemoryPressureWatch", "s", bus_property_get_cgroup_pressure_watch
, offsetof(CGroupContext
, memory_pressure_watch
), 0),
434 SD_BUS_PROPERTY("MemoryPressureThresholdUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, memory_pressure_threshold_usec
), 0),
435 SD_BUS_PROPERTY("NFTSet", "a(iiss)", property_get_cgroup_nft_set
, 0, 0),
436 SD_BUS_PROPERTY("CoredumpReceive", "b", bus_property_get_bool
, offsetof(CGroupContext
, coredump_receive
), 0),
438 /* deprecated cgroup v1 properties */
439 SD_BUS_PROPERTY("MemoryLimit", "t", bus_property_get_uint64_max
, 0, SD_BUS_VTABLE_DEPRECATED
|SD_BUS_VTABLE_HIDDEN
),
440 SD_BUS_PROPERTY("CPUShares", "t", bus_property_get_uint64_max
, 0, SD_BUS_VTABLE_DEPRECATED
|SD_BUS_VTABLE_HIDDEN
),
441 SD_BUS_PROPERTY("StartupCPUShares", "t", bus_property_get_uint64_max
, 0, SD_BUS_VTABLE_DEPRECATED
|SD_BUS_VTABLE_HIDDEN
),
442 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool_false
, 0, SD_BUS_VTABLE_DEPRECATED
|SD_BUS_VTABLE_HIDDEN
),
443 SD_BUS_PROPERTY("BlockIOWeight", "t", bus_property_get_uint64_max
, 0, SD_BUS_VTABLE_DEPRECATED
|SD_BUS_VTABLE_HIDDEN
),
444 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", bus_property_get_uint64_max
, 0, SD_BUS_VTABLE_DEPRECATED
|SD_BUS_VTABLE_HIDDEN
),
445 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_ast
, 0, SD_BUS_VTABLE_DEPRECATED
|SD_BUS_VTABLE_HIDDEN
),
446 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_ast
, 0, SD_BUS_VTABLE_DEPRECATED
|SD_BUS_VTABLE_HIDDEN
),
447 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_ast
, 0, SD_BUS_VTABLE_DEPRECATED
|SD_BUS_VTABLE_HIDDEN
),
448 /* since kernel v4.15 CPU accounting requires no controller, i.e. is available everywhere */
449 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool_true
, 0, SD_BUS_VTABLE_DEPRECATED
|SD_BUS_VTABLE_HIDDEN
),
454 static int bus_cgroup_set_transient_property(
458 sd_bus_message
*message
,
459 UnitWriteFlags flags
,
460 sd_bus_error
*error
) {
469 flags
|= UNIT_PRIVATE
;
471 if (streq(name
, "Delegate")) {
474 if (!UNIT_VTABLE(u
)->can_delegate
)
475 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
477 r
= sd_bus_message_read(message
, "b", &b
);
481 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
483 c
->delegate_controllers
= b
? CGROUP_MASK_DELEGATE
: 0;
485 unit_write_settingf(u
, flags
, name
, "Delegate=%s", yes_no(b
));
490 } else if (streq(name
, "DelegateSubgroup")) {
493 if (!UNIT_VTABLE(u
)->can_delegate
)
494 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
496 r
= sd_bus_message_read(message
, "s", &s
);
500 if (!isempty(s
) && cg_needs_escape(s
))
501 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid control group name: %s", s
);
503 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
505 c
->delegate_subgroup
= mfree(c
->delegate_subgroup
);
507 r
= free_and_strdup_warn(&c
->delegate_subgroup
, s
);
512 unit_write_settingf(u
, flags
, name
, "DelegateSubgroup=%s", s
);
517 } else if (STR_IN_SET(name
, "DelegateControllers", "DisableControllers")) {
520 if (streq(name
, "DelegateControllers") && !UNIT_VTABLE(u
)->can_delegate
)
521 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
523 r
= sd_bus_message_enter_container(message
, 'a', "s");
531 r
= sd_bus_message_read(message
, "s", &t
);
537 cc
= cgroup_controller_from_string(t
);
539 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown cgroup controller '%s'", t
);
541 mask
|= CGROUP_CONTROLLER_TO_MASK(cc
);
544 r
= sd_bus_message_exit_container(message
);
548 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
549 _cleanup_free_
char *t
= NULL
;
551 r
= cg_mask_to_string(mask
, &t
);
555 if (streq(name
, "DelegateControllers")) {
559 c
->delegate_controllers
= 0;
561 c
->delegate_controllers
|= mask
;
563 unit_write_settingf(u
, flags
, name
, "Delegate=%s", strempty(t
));
565 } else if (streq(name
, "DisableControllers")) {
568 c
->disable_controllers
= 0;
570 c
->disable_controllers
|= mask
;
572 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, strempty(t
));
577 } else if (STR_IN_SET(name
, "IPIngressFilterPath", "IPEgressFilterPath")) {
581 filters
= streq(name
, "IPIngressFilterPath") ? &c
->ip_filters_ingress
: &c
->ip_filters_egress
;
582 r
= sd_bus_message_enter_container(message
, 'a', "s");
589 r
= sd_bus_message_read(message
, "s", &path
);
595 if (!path_is_normalized(path
) || !path_is_absolute(path
))
596 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects a normalized absolute path.", name
);
598 if (!UNIT_WRITE_FLAGS_NOOP(flags
) && !strv_contains(*filters
, path
)) {
599 r
= strv_extend(filters
, path
);
605 r
= sd_bus_message_exit_container(message
);
609 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
610 _cleanup_(memstream_done
) MemStream m
= {};
611 _cleanup_free_
char *buf
= NULL
;
615 *filters
= strv_free(*filters
);
617 unit_invalidate_cgroup_bpf(u
);
619 f
= memstream_init(&m
);
626 STRV_FOREACH(entry
, *filters
)
627 fprintf(f
, "%s=%s\n", name
, *entry
);
629 r
= memstream_finalize(&m
, &buf
, NULL
);
633 unit_write_setting(u
, flags
, name
, buf
);
635 if (*filters
&& bpf_program_supported() <= 0) {
636 static bool warned
= false;
638 log_full(warned
? LOG_DEBUG
: LOG_WARNING
,
639 "Transient unit %s configures an IP firewall with BPF, but the local system does not support BPF/cgroup firewalling with multiple filters.\n"
640 "Starting this unit will fail! (This warning is only shown for the first started transient unit using IP firewalling.)", u
->id
);
646 } else if (streq(name
, "BPFProgram")) {
650 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
654 while ((r
= sd_bus_message_read(message
, "(ss)", &a
, &p
)) > 0) {
655 int attach_type
= bpf_cgroup_attach_type_from_string(a
);
657 return sd_bus_error_setf(
659 SD_BUS_ERROR_INVALID_ARGS
,
660 "%s expects a valid BPF attach type, got '%s'.",
663 if (!path_is_normalized(p
) || !path_is_absolute(p
))
664 return sd_bus_error_setf(
666 SD_BUS_ERROR_INVALID_ARGS
,
667 "%s= expects a normalized absolute path.",
670 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
671 r
= cgroup_context_add_bpf_foreign_program(c
, attach_type
, p
);
680 r
= sd_bus_message_exit_container(message
);
684 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
685 _cleanup_(memstream_done
) MemStream m
= {};
686 _cleanup_free_
char *buf
= NULL
;
690 while (c
->bpf_foreign_programs
)
691 cgroup_context_remove_bpf_foreign_program(c
, c
->bpf_foreign_programs
);
693 f
= memstream_init(&m
);
700 LIST_FOREACH(programs
, fp
, c
->bpf_foreign_programs
)
701 fprintf(f
, "%s=%s:%s\n", name
,
702 bpf_cgroup_attach_type_to_string(fp
->attach_type
),
705 r
= memstream_finalize(&m
, &buf
, NULL
);
709 unit_write_setting(u
, flags
, name
, buf
);
714 } else if (streq(name
, "MemoryPressureWatch")) {
715 CGroupPressureWatch p
;
718 r
= sd_bus_message_read(message
, "s", &t
);
723 p
= _CGROUP_PRESSURE_WATCH_INVALID
;
725 p
= cgroup_pressure_watch_from_string(t
);
730 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
731 c
->memory_pressure_watch
= p
;
732 unit_write_settingf(u
, flags
, name
, "MemoryPressureWatch=%s", strempty(cgroup_pressure_watch_to_string(p
)));
737 } else if (streq(name
, "MemoryPressureThresholdUSec")) {
740 r
= sd_bus_message_read(message
, "t", &t
);
744 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
745 c
->memory_pressure_threshold_usec
= t
;
748 unit_write_setting(u
, flags
, name
, "MemoryPressureThresholdUSec=");
750 unit_write_settingf(u
, flags
, name
, "MemoryPressureThresholdUSec=%" PRIu64
, t
);
754 } else if (streq(name
, "CoredumpReceive")) {
757 if (!UNIT_VTABLE(u
)->can_delegate
)
758 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
760 r
= sd_bus_message_read(message
, "b", &b
);
764 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
765 c
->coredump_receive
= b
;
767 unit_write_settingf(u
, flags
, name
, "CoredumpReceive=%s", yes_no(b
));
776 static int bus_cgroup_set_boolean(
781 sd_bus_message
*message
,
782 UnitWriteFlags flags
,
783 sd_bus_error
*error
) {
789 r
= sd_bus_message_read(message
, "b", &b
);
793 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
795 unit_invalidate_cgroup(u
, mask
);
796 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, yes_no(b
));
802 #define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \
803 static int bus_cgroup_set_##function( \
807 sd_bus_message *message, \
808 UnitWriteFlags flags, \
809 sd_bus_error *error) { \
816 r = sd_bus_message_read(message, "t", &v); \
821 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
822 "Value specified in %s is out of range", name); \
824 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
826 unit_invalidate_cgroup(u, mask); \
829 unit_write_settingf(u, flags, name, \
832 unit_write_settingf(u, flags, name, \
833 "%s=%" PRIu64, name, v); \
839 #define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \
840 static int bus_cgroup_set_##function( \
844 sd_bus_message *message, \
845 UnitWriteFlags flags, \
846 sd_bus_error *error) { \
853 r = sd_bus_message_read(message, "t", &v); \
858 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
859 "Value specified in %s is out of range", name); \
861 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
863 unit_invalidate_cgroup(u, mask); \
865 if (v == CGROUP_LIMIT_MAX) \
866 unit_write_settingf(u, flags, name, \
867 "%s=infinity", name); \
869 unit_write_settingf(u, flags, name, \
870 "%s=%" PRIu64, name, v); \
875 static int bus_cgroup_set_##function##_scale( \
879 sd_bus_message *message, \
880 UnitWriteFlags flags, \
881 sd_bus_error *error) { \
889 r = sd_bus_message_read(message, "u", &raw); \
893 v = scale(raw, UINT32_MAX); \
894 if (v < minimum || v >= UINT64_MAX) \
895 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
896 "Value specified in %s is out of range", name); \
898 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
900 unit_invalidate_cgroup(u, mask); \
902 /* Prepare to chop off suffix */ \
903 assert_se(endswith(name, "Scale")); \
905 int scaled = UINT32_SCALE_TO_PERMYRIAD(raw); \
906 unit_write_settingf(u, flags, name, "%.*s=" PERMYRIAD_AS_PERCENT_FORMAT_STR, \
907 (int)(strlen(name) - strlen("Scale")), name, \
908 PERMYRIAD_AS_PERCENT_FORMAT_VAL(scaled)); \
914 DISABLE_WARNING_TYPE_LIMITS
;
915 BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight
, CGROUP_MASK_IO
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
916 BUS_DEFINE_SET_CGROUP_LIMIT(memory
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 1);
917 BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
918 BUS_DEFINE_SET_CGROUP_LIMIT(swap
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
919 BUS_DEFINE_SET_CGROUP_LIMIT(zswap
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
922 static int bus_cgroup_set_cpu_weight(
926 sd_bus_message
*message
,
927 UnitWriteFlags flags
,
928 sd_bus_error
*error
) {
932 r
= sd_bus_message_read(message
, "t", &v
);
935 if (!CGROUP_WEIGHT_IS_OK(v
) && v
!= CGROUP_WEIGHT_IDLE
)
936 return sd_bus_error_setf(
937 error
, SD_BUS_ERROR_INVALID_ARGS
, "Value specified in %s is out of range", name
);
938 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
940 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
941 if (v
== CGROUP_WEIGHT_INVALID
)
942 unit_write_settingf(u
, flags
, name
, "%s=", name
);
943 else if (v
== CGROUP_WEIGHT_IDLE
)
944 unit_write_settingf(u
, flags
, name
, "%s=idle", name
);
946 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu64
, name
, v
);
951 static int bus_cgroup_set_tasks_max(
955 sd_bus_message
*message
,
956 UnitWriteFlags flags
,
957 sd_bus_error
*error
) {
964 r
= sd_bus_message_read(message
, "t", &v
);
969 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
970 "Value specified in %s is out of range", name
);
972 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
973 *p
= (CGroupTasksMax
) { .value
= v
, .scale
= 0 }; /* When .scale==0, .value is the absolute value */
974 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
976 if (v
== CGROUP_LIMIT_MAX
)
977 unit_write_settingf(u
, flags
, name
,
978 "%s=infinity", name
);
980 unit_write_settingf(u
, flags
, name
,
981 "%s=%" PRIu64
, name
, v
);
987 static int bus_cgroup_set_tasks_max_scale(
991 sd_bus_message
*message
,
992 UnitWriteFlags flags
,
993 sd_bus_error
*error
) {
1000 r
= sd_bus_message_read(message
, "u", &v
);
1004 if (v
< 1 || v
>= UINT32_MAX
)
1005 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
1006 "Value specified in %s is out of range", name
);
1008 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1009 *p
= (CGroupTasksMax
) { v
, UINT32_MAX
}; /* .scale is not 0, so this is interpreted as v/UINT32_MAX. */
1010 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1012 uint32_t scaled
= DIV_ROUND_UP((uint64_t) v
* 100U, (uint64_t) UINT32_MAX
);
1013 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu32
".%" PRIu32
"%%", "TasksMax",
1014 scaled
/ 10, scaled
% 10);
1020 int bus_cgroup_set_property(
1024 sd_bus_message
*message
,
1025 UnitWriteFlags flags
,
1026 sd_bus_error
*error
) {
1028 CGroupIOLimitType iol_type
;
1036 flags
|= UNIT_PRIVATE
;
1038 if (streq(name
, "CPUWeight"))
1039 return bus_cgroup_set_cpu_weight(u
, name
, &c
->cpu_weight
, message
, flags
, error
);
1041 if (streq(name
, "StartupCPUWeight"))
1042 return bus_cgroup_set_cpu_weight(u
, name
, &c
->startup_cpu_weight
, message
, flags
, error
);
1044 if (streq(name
, "IOAccounting"))
1045 return bus_cgroup_set_boolean(u
, name
, &c
->io_accounting
, CGROUP_MASK_IO
, message
, flags
, error
);
1047 if (streq(name
, "IOWeight"))
1048 return bus_cgroup_set_io_weight(u
, name
, &c
->io_weight
, message
, flags
, error
);
1050 if (streq(name
, "StartupIOWeight"))
1051 return bus_cgroup_set_io_weight(u
, name
, &c
->startup_io_weight
, message
, flags
, error
);
1053 if (streq(name
, "MemoryAccounting"))
1054 return bus_cgroup_set_boolean(u
, name
, &c
->memory_accounting
, CGROUP_MASK_MEMORY
, message
, flags
, error
);
1056 if (streq(name
, "MemoryMin")) {
1057 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->memory_min
, message
, flags
, error
);
1059 c
->memory_min_set
= true;
1063 if (streq(name
, "MemoryLow")) {
1064 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->memory_low
, message
, flags
, error
);
1066 c
->memory_low_set
= true;
1070 if (streq(name
, "StartupMemoryLow")) {
1071 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->startup_memory_low
, message
, flags
, error
);
1073 c
->startup_memory_low_set
= true;
1077 if (streq(name
, "DefaultMemoryMin")) {
1078 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->default_memory_min
, message
, flags
, error
);
1080 c
->default_memory_min_set
= true;
1084 if (streq(name
, "DefaultMemoryLow")) {
1085 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->default_memory_low
, message
, flags
, error
);
1087 c
->default_memory_low_set
= true;
1091 if (streq(name
, "DefaultStartupMemoryLow")) {
1092 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->default_startup_memory_low
, message
, flags
, error
);
1094 c
->default_startup_memory_low_set
= true;
1098 if (streq(name
, "MemoryHigh"))
1099 return bus_cgroup_set_memory(u
, name
, &c
->memory_high
, message
, flags
, error
);
1101 if (streq(name
, "StartupMemoryHigh")) {
1102 r
= bus_cgroup_set_memory(u
, name
, &c
->startup_memory_high
, message
, flags
, error
);
1104 c
->startup_memory_high_set
= true;
1108 if (streq(name
, "MemorySwapMax"))
1109 return bus_cgroup_set_swap(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
1111 if (streq(name
, "StartupMemorySwapMax")) {
1112 r
= bus_cgroup_set_swap(u
, name
, &c
->startup_memory_swap_max
, message
, flags
, error
);
1114 c
->startup_memory_swap_max_set
= true;
1118 if (streq(name
, "MemoryZSwapMax"))
1119 return bus_cgroup_set_zswap(u
, name
, &c
->memory_zswap_max
, message
, flags
, error
);
1121 if (streq(name
, "StartupMemoryZSwapMax")) {
1122 r
= bus_cgroup_set_zswap(u
, name
, &c
->startup_memory_zswap_max
, message
, flags
, error
);
1124 c
->startup_memory_zswap_max_set
= true;
1128 if (streq(name
, "MemoryMax"))
1129 return bus_cgroup_set_memory(u
, name
, &c
->memory_max
, message
, flags
, error
);
1131 if (streq(name
, "StartupMemoryMax")) {
1132 r
= bus_cgroup_set_memory(u
, name
, &c
->startup_memory_max
, message
, flags
, error
);
1134 c
->startup_memory_max_set
= true;
1138 if (streq(name
, "MemoryMinScale")) {
1139 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->memory_min
, message
, flags
, error
);
1141 c
->memory_min_set
= true;
1145 if (streq(name
, "MemoryLowScale")) {
1146 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->memory_low
, message
, flags
, error
);
1148 c
->memory_low_set
= true;
1152 if (streq(name
, "DefaultMemoryMinScale")) {
1153 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->default_memory_min
, message
, flags
, error
);
1155 c
->default_memory_min_set
= true;
1159 if (streq(name
, "DefaultMemoryLowScale")) {
1160 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->default_memory_low
, message
, flags
, error
);
1162 c
->default_memory_low_set
= true;
1166 if (streq(name
, "MemoryHighScale"))
1167 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_high
, message
, flags
, error
);
1169 if (streq(name
, "MemorySwapMaxScale"))
1170 return bus_cgroup_set_swap_scale(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
1172 if (streq(name
, "MemoryZSwapMaxScale"))
1173 return bus_cgroup_set_zswap_scale(u
, name
, &c
->memory_zswap_max
, message
, flags
, error
);
1175 if (streq(name
, "MemoryMaxScale"))
1176 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_max
, message
, flags
, error
);
1178 if (streq(name
, "MemoryZSwapWriteback"))
1179 return bus_cgroup_set_boolean(u
, name
, &c
->memory_zswap_writeback
, CGROUP_MASK_MEMORY
, message
, flags
, error
);
1181 if (streq(name
, "TasksAccounting"))
1182 return bus_cgroup_set_boolean(u
, name
, &c
->tasks_accounting
, CGROUP_MASK_PIDS
, message
, flags
, error
);
1184 if (streq(name
, "TasksMax"))
1185 return bus_cgroup_set_tasks_max(u
, name
, &c
->tasks_max
, message
, flags
, error
);
1187 if (streq(name
, "TasksMaxScale"))
1188 return bus_cgroup_set_tasks_max_scale(u
, name
, &c
->tasks_max
, message
, flags
, error
);
1190 if (streq(name
, "CPUQuotaPerSecUSec")) {
1193 r
= sd_bus_message_read(message
, "t", &u64
);
1198 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "CPUQuotaPerSecUSec= value out of range");
1200 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1201 c
->cpu_quota_per_sec_usec
= u64
;
1202 CGroupRuntime
*crt
= unit_get_cgroup_runtime(u
);
1204 crt
->warned_clamping_cpu_quota_period
= false;
1205 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
1207 if (c
->cpu_quota_per_sec_usec
== USEC_INFINITY
)
1208 unit_write_setting(u
, flags
, "CPUQuota", "CPUQuota=");
1210 unit_write_settingf(u
, flags
, "CPUQuota",
1211 "CPUQuota=" USEC_FMT
".%02" PRI_USEC
"%%",
1212 c
->cpu_quota_per_sec_usec
/ 10000,
1213 (c
->cpu_quota_per_sec_usec
% 10000) / 100);
1218 } else if (streq(name
, "CPUQuotaPeriodUSec")) {
1221 r
= sd_bus_message_read(message
, "t", &u64
);
1225 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1226 c
->cpu_quota_period_usec
= u64
;
1227 CGroupRuntime
*crt
= unit_get_cgroup_runtime(u
);
1229 crt
->warned_clamping_cpu_quota_period
= false;
1230 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
1231 if (c
->cpu_quota_period_usec
== USEC_INFINITY
)
1232 unit_write_setting(u
, flags
, "CPUQuotaPeriodSec", "CPUQuotaPeriodSec=");
1234 unit_write_settingf(u
, flags
, "CPUQuotaPeriodSec",
1235 "CPUQuotaPeriodSec=%s",
1236 FORMAT_TIMESPAN(c
->cpu_quota_period_usec
, 1));
1241 } else if (STR_IN_SET(name
, "AllowedCPUs", "StartupAllowedCPUs", "AllowedMemoryNodes", "StartupAllowedMemoryNodes")) {
1244 _cleanup_(cpu_set_done
) CPUSet new_set
= {};
1246 r
= sd_bus_message_read_array(message
, 'y', &a
, &n
);
1250 r
= cpu_set_from_dbus(a
, n
, &new_set
);
1254 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1255 _cleanup_free_
char *setstr
= NULL
;
1258 setstr
= cpu_set_to_range_string(&new_set
);
1262 if (streq(name
, "AllowedCPUs"))
1263 set
= &c
->cpuset_cpus
;
1264 else if (streq(name
, "StartupAllowedCPUs"))
1265 set
= &c
->startup_cpuset_cpus
;
1266 else if (streq(name
, "AllowedMemoryNodes"))
1267 set
= &c
->cpuset_mems
;
1268 else if (streq(name
, "StartupAllowedMemoryNodes"))
1269 set
= &c
->startup_cpuset_mems
;
1271 assert_not_reached();
1273 cpu_set_done_and_replace(*set
, new_set
);
1275 unit_invalidate_cgroup(u
, CGROUP_MASK_CPUSET
);
1276 unit_write_settingf(u
, flags
, name
, "%s=\n%s=%s", name
, name
, setstr
);
1281 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
1286 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1290 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
1292 if (!path_is_normalized(path
))
1293 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1295 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1296 CGroupIODeviceLimit
*a
= NULL
;
1298 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
)
1299 if (path_equal(path
, b
->path
)) {
1305 CGroupIOLimitType type
;
1307 a
= new0(CGroupIODeviceLimit
, 1);
1311 a
->path
= strdup(path
);
1317 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
1318 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
1320 LIST_APPEND(device_limits
, c
->io_device_limits
, a
);
1323 a
->limits
[iol_type
] = u64
;
1331 r
= sd_bus_message_exit_container(message
);
1335 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1336 _cleanup_(memstream_done
) MemStream m
= {};
1337 _cleanup_free_
char *buf
= NULL
;
1341 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
1342 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
1344 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1346 f
= memstream_init(&m
);
1350 fprintf(f
, "%s=\n", name
);
1351 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
1352 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
1353 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
1355 r
= memstream_finalize(&m
, &buf
, NULL
);
1359 unit_write_setting(u
, flags
, name
, buf
);
1364 } else if (streq(name
, "IODeviceWeight")) {
1369 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1373 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
1375 if (!path_is_normalized(path
))
1376 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1378 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
1379 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "IODeviceWeight= value out of range");
1381 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1382 CGroupIODeviceWeight
*a
= NULL
;
1384 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
)
1385 if (path_equal(b
->path
, path
)) {
1391 a
= new0(CGroupIODeviceWeight
, 1);
1395 a
->path
= strdup(path
);
1400 LIST_APPEND(device_weights
, c
->io_device_weights
, a
);
1409 r
= sd_bus_message_exit_container(message
);
1413 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1414 _cleanup_(memstream_done
) MemStream m
= {};
1415 _cleanup_free_
char *buf
= NULL
;
1419 while (c
->io_device_weights
)
1420 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
1422 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1424 f
= memstream_init(&m
);
1428 fputs("IODeviceWeight=\n", f
);
1429 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
1430 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1432 r
= memstream_finalize(&m
, &buf
, NULL
);
1436 unit_write_setting(u
, flags
, name
, buf
);
1441 } else if (streq(name
, "IODeviceLatencyTargetUSec")) {
1446 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1450 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &target
)) > 0) {
1452 if (!path_is_normalized(path
))
1453 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1455 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1456 CGroupIODeviceLatency
*a
= NULL
;
1458 LIST_FOREACH(device_latencies
, b
, c
->io_device_latencies
)
1459 if (path_equal(b
->path
, path
)) {
1465 a
= new0(CGroupIODeviceLatency
, 1);
1469 a
->path
= strdup(path
);
1474 LIST_APPEND(device_latencies
, c
->io_device_latencies
, a
);
1477 a
->target_usec
= target
;
1483 r
= sd_bus_message_exit_container(message
);
1487 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1488 _cleanup_(memstream_done
) MemStream m
= {};
1489 _cleanup_free_
char *buf
= NULL
;
1493 while (c
->io_device_latencies
)
1494 cgroup_context_free_io_device_latency(c
, c
->io_device_latencies
);
1496 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1498 f
= memstream_init(&m
);
1502 fputs("IODeviceLatencyTargetSec=\n", f
);
1503 LIST_FOREACH(device_latencies
, a
, c
->io_device_latencies
)
1504 fprintf(f
, "IODeviceLatencyTargetSec=%s %s\n",
1505 a
->path
, FORMAT_TIMESPAN(a
->target_usec
, 1));
1507 r
= memstream_finalize(&m
, &buf
, NULL
);
1511 unit_write_setting(u
, flags
, name
, buf
);
1516 } else if (streq(name
, "DevicePolicy")) {
1518 CGroupDevicePolicy p
;
1520 r
= sd_bus_message_read(message
, "s", &policy
);
1524 p
= cgroup_device_policy_from_string(policy
);
1528 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1529 c
->device_policy
= p
;
1530 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1531 unit_write_settingf(u
, flags
, name
, "DevicePolicy=%s", policy
);
1536 } else if (streq(name
, "DeviceAllow")) {
1537 const char *path
, *rwm
;
1540 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
1544 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
1545 CGroupDevicePermissions p
;
1547 if (!valid_device_allow_pattern(path
) || strpbrk(path
, WHITESPACE
))
1548 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires device node or pattern");
1551 p
= _CGROUP_DEVICE_PERMISSIONS_ALL
;
1553 p
= cgroup_device_permissions_from_string(rwm
);
1555 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires combination of rwm flags");
1558 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1559 r
= cgroup_context_add_or_update_device_allow(c
, path
, p
);
1569 r
= sd_bus_message_exit_container(message
);
1573 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1574 _cleanup_(memstream_done
) MemStream m
= {};
1575 _cleanup_free_
char *buf
= NULL
;
1579 while (c
->device_allow
)
1580 cgroup_context_free_device_allow(c
, c
->device_allow
);
1582 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1584 f
= memstream_init(&m
);
1588 fputs("DeviceAllow=\n", f
);
1589 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
1590 fprintf(f
, "DeviceAllow=%s %s\n", a
->path
, cgroup_device_permissions_to_string(a
->permissions
));
1592 r
= memstream_finalize(&m
, &buf
, NULL
);
1596 unit_write_setting(u
, flags
, name
, buf
);
1601 } else if (streq(name
, "IPAccounting")) {
1604 r
= sd_bus_message_read(message
, "b", &b
);
1608 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1609 c
->ip_accounting
= b
;
1611 unit_invalidate_cgroup_bpf(u
);
1612 unit_write_settingf(u
, flags
, name
, "IPAccounting=%s", yes_no(b
));
1617 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1618 _cleanup_set_free_ Set
*new_prefixes
= NULL
;
1621 r
= sd_bus_message_enter_container(message
, 'a', "(iayu)");
1626 r
= sd_bus_message_enter_container(message
, 'r', "iayu");
1632 struct in_addr_prefix prefix
;
1633 r
= bus_message_read_in_addr_auto(message
, error
, &prefix
.family
, &prefix
.address
);
1638 r
= sd_bus_message_read(message
, "u", &prefixlen
);
1642 if (prefixlen
> FAMILY_ADDRESS_SIZE(prefix
.family
)*8)
1643 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
1644 "Prefix length %" PRIu32
" too large for address family %s.",
1645 prefixlen
, af_to_name(prefix
.family
));
1647 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1648 prefix
.prefixlen
= (uint8_t) prefixlen
;
1650 r
= in_addr_prefix_add(&new_prefixes
, &prefix
);
1655 r
= sd_bus_message_exit_container(message
);
1662 r
= sd_bus_message_exit_container(message
);
1666 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1667 _cleanup_(memstream_done
) MemStream m
= {};
1668 _cleanup_free_
char *buf
= NULL
;
1673 unit_invalidate_cgroup_bpf(u
);
1675 f
= memstream_init(&m
);
1679 prefixes
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow
: &c
->ip_address_deny
;
1680 reduced
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow_reduced
: &c
->ip_address_deny_reduced
;
1687 *prefixes
= set_free(*prefixes
);
1691 r
= in_addr_prefixes_merge(prefixes
, new_prefixes
);
1695 const struct in_addr_prefix
*p
;
1696 SET_FOREACH(p
, *prefixes
)
1697 fprintf(f
, "%s=%s\n", name
,
1698 IN_ADDR_PREFIX_TO_STRING(p
->family
, &p
->address
, p
->prefixlen
));
1701 r
= memstream_finalize(&m
, &buf
, NULL
);
1705 unit_write_setting(u
, flags
, name
, buf
);
1711 if (STR_IN_SET(name
, "ManagedOOMSwap", "ManagedOOMMemoryPressure")) {
1712 ManagedOOMMode
*cgroup_mode
= streq(name
, "ManagedOOMSwap") ? &c
->moom_swap
: &c
->moom_mem_pressure
;
1716 if (!UNIT_VTABLE(u
)->can_set_managed_oom
)
1717 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot set %s for this unit type", name
);
1719 r
= sd_bus_message_read(message
, "s", &mode
);
1723 m
= managed_oom_mode_from_string(mode
);
1727 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1729 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, mode
);
1732 (void) manager_varlink_send_managed_oom_update(u
);
1736 if (streq(name
, "ManagedOOMMemoryPressureLimit")) {
1739 if (!UNIT_VTABLE(u
)->can_set_managed_oom
)
1740 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot set %s for this unit type", name
);
1742 r
= sd_bus_message_read(message
, "u", &v
);
1746 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1747 c
->moom_mem_pressure_limit
= v
;
1748 unit_write_settingf(u
, flags
, name
,
1749 "ManagedOOMMemoryPressureLimit=" PERMYRIAD_AS_PERCENT_FORMAT_STR
,
1750 PERMYRIAD_AS_PERCENT_FORMAT_VAL(UINT32_SCALE_TO_PERMYRIAD(v
)));
1753 if (c
->moom_mem_pressure
== MANAGED_OOM_KILL
)
1754 (void) manager_varlink_send_managed_oom_update(u
);
1759 if (streq(name
, "ManagedOOMMemoryPressureDurationUSec")) {
1762 if (!UNIT_VTABLE(u
)->can_set_managed_oom
)
1763 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot set %s for this unit type", name
);
1765 r
= sd_bus_message_read(message
, "t", &t
);
1769 if (t
< 1 * USEC_PER_SEC
)
1770 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= must be at least 1s, got %s", name
,
1771 FORMAT_TIMESPAN(t
, USEC_PER_SEC
));
1773 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1774 c
->memory_pressure_threshold_usec
= t
;
1775 if (c
->memory_pressure_threshold_usec
== USEC_INFINITY
)
1776 unit_write_setting(u
, flags
, name
, "ManagedOOMMemoryPressureDurationSec=");
1778 unit_write_settingf(u
, flags
, name
,
1779 "ManagedOOMMemoryPressureDurationSec=%s",
1780 FORMAT_TIMESPAN(c
->memory_pressure_threshold_usec
, 1));
1783 if (c
->moom_mem_pressure
== MANAGED_OOM_KILL
)
1784 (void) manager_varlink_send_managed_oom_update(u
);
1789 if (streq(name
, "ManagedOOMPreference")) {
1790 ManagedOOMPreference p
;
1793 r
= sd_bus_message_read(message
, "s", &pref
);
1797 p
= managed_oom_preference_from_string(pref
);
1801 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1802 c
->moom_preference
= p
;
1803 unit_write_settingf(u
, flags
, name
, "ManagedOOMPreference=%s", pref
);
1808 if (STR_IN_SET(name
, "SocketBindAllow", "SocketBindDeny")) {
1809 CGroupSocketBindItem
**list
;
1810 uint16_t nr_ports
, port_min
;
1812 int32_t family
, ip_protocol
;
1814 list
= streq(name
, "SocketBindAllow") ? &c
->socket_bind_allow
: &c
->socket_bind_deny
;
1816 r
= sd_bus_message_enter_container(message
, 'a', "(iiqq)");
1820 while ((r
= sd_bus_message_read(message
, "(iiqq)", &family
, &ip_protocol
, &nr_ports
, &port_min
)) > 0) {
1822 if (!IN_SET(family
, AF_UNSPEC
, AF_INET
, AF_INET6
))
1823 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects INET or INET6 family, if specified.", name
);
1825 if (!IN_SET(ip_protocol
, 0, IPPROTO_TCP
, IPPROTO_UDP
))
1826 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects TCP or UDP protocol, if specified.", name
);
1828 if (port_min
+ (uint32_t) nr_ports
> (1 << 16))
1829 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects maximum port value lesser than 65536.", name
);
1831 if (port_min
== 0 && nr_ports
!= 0)
1832 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects port range starting with positive value.", name
);
1834 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1835 _cleanup_free_ CGroupSocketBindItem
*item
= NULL
;
1837 item
= new(CGroupSocketBindItem
, 1);
1841 *item
= (CGroupSocketBindItem
) {
1842 .address_family
= family
,
1843 .ip_protocol
= ip_protocol
,
1844 .nr_ports
= nr_ports
,
1845 .port_min
= port_min
1848 LIST_PREPEND(socket_bind_items
, *list
, TAKE_PTR(item
));
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 cgroup_context_remove_socket_bind(list
);
1867 if ((u
->manager
->cgroup_supported
& CGROUP_MASK_BPF_SOCKET_BIND
) == 0)
1869 "Unit %s configures source compiled BPF programs "
1870 "but the local system does not support that.\n"
1871 "Starting this unit will fail!", u
->id
);
1874 f
= memstream_init(&m
);
1879 fprintf(f
, "%s=\n", name
);
1881 LIST_FOREACH(socket_bind_items
, item
, *list
) {
1882 fprintf(f
, "%s=", name
);
1883 cgroup_context_dump_socket_bind_item(item
, f
);
1887 r
= memstream_finalize(&m
, &buf
, NULL
);
1891 unit_write_setting(u
, flags
, name
, buf
);
1896 if (streq(name
, "RestrictNetworkInterfaces")) {
1898 _cleanup_strv_free_
char **l
= NULL
;
1900 r
= sd_bus_message_enter_container(message
, 'r', "bas");
1904 r
= sd_bus_message_read(message
, "b", &is_allow_list
);
1908 r
= sd_bus_message_read_strv(message
, &l
);
1912 r
= sd_bus_message_exit_container(message
);
1916 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1917 _cleanup_free_
char *joined
= NULL
;
1919 if (strv_isempty(l
)) {
1920 c
->restrict_network_interfaces_is_allow_list
= false;
1921 c
->restrict_network_interfaces
= set_free(c
->restrict_network_interfaces
);
1923 unit_write_settingf(u
, flags
, name
, "%s=", name
);
1927 if (set_isempty(c
->restrict_network_interfaces
))
1928 c
->restrict_network_interfaces_is_allow_list
= is_allow_list
;
1930 STRV_FOREACH(s
, l
) {
1931 if (!ifname_valid_full(*s
, IFNAME_VALID_ALTERNATIVE
)) {
1932 log_full(LOG_WARNING
, "Invalid interface name, ignoring: %s", *s
);
1935 if (c
->restrict_network_interfaces_is_allow_list
!= (bool) is_allow_list
)
1936 free(set_remove(c
->restrict_network_interfaces
, *s
));
1938 r
= set_put_strdup(&c
->restrict_network_interfaces
, *s
);
1944 joined
= strv_join(l
, " ");
1948 unit_write_settingf(u
, flags
, name
, "%s=%s%s", name
, is_allow_list
? "" : "~", joined
);
1954 if (streq(name
, "NFTSet")) {
1955 int source
, nfproto
;
1956 const char *table
, *set
;
1959 r
= sd_bus_message_enter_container(message
, 'a', "(iiss)");
1963 while ((r
= sd_bus_message_read(message
, "(iiss)", &source
, &nfproto
, &table
, &set
)) > 0) {
1964 const char *source_name
, *nfproto_name
;
1966 if (!IN_SET(source
, NFT_SET_SOURCE_CGROUP
, NFT_SET_SOURCE_USER
, NFT_SET_SOURCE_GROUP
))
1967 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid source %d.", source
);
1969 source_name
= nft_set_source_to_string(source
);
1970 assert(source_name
);
1972 nfproto_name
= nfproto_to_string(nfproto
);
1974 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid protocol %d.", nfproto
);
1976 if (!nft_identifier_valid(table
)) {
1977 _cleanup_free_
char *esc
= NULL
;
1979 esc
= cescape(table
);
1980 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid NFT table name %s.", strna(esc
));
1983 if (!nft_identifier_valid(set
)) {
1984 _cleanup_free_
char *esc
= NULL
;
1987 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid NFT set name %s.", strna(esc
));
1990 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1991 r
= nft_set_add(&c
->nft_set_context
, source
, nfproto
, table
, set
);
1995 unit_write_settingf(
1996 u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
,
2010 r
= sd_bus_message_exit_container(message
);
2014 if (empty
&& !UNIT_WRITE_FLAGS_NOOP(flags
)) {
2015 nft_set_context_clear(&c
->nft_set_context
);
2016 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2022 /* deprecated CGroup v1 properties */
2023 if (STR_IN_SET(name
,
2028 "BlockIOAccounting",
2030 "StartupBlockIOWeight",
2031 "BlockIODeviceWeight",
2032 "BlockIOReadBandwidth",
2033 "BlockIOWriteBandwidth",
2034 "CPUAccounting")) { /* see comment in bus_cgroup_vtable */
2036 r
= sd_bus_message_skip(message
, NULL
);
2044 if (streq(name
, "DisableControllers") || (u
->transient
&& u
->load_state
== UNIT_STUB
))
2045 return bus_cgroup_set_transient_property(u
, c
, name
, message
, flags
, error
);