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"
10 #include "cgroup-util.h"
12 #include "core-varlink.h"
13 #include "dbus-cgroup.h"
14 #include "dbus-util.h"
15 #include "errno-util.h"
18 #include "in-addr-prefix-util.h"
19 #include "ip-protocol-list.h"
20 #include "limits-util.h"
21 #include "parse-util.h"
22 #include "path-util.h"
23 #include "percent-util.h"
24 #include "socket-util.h"
26 BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max
, "t", TasksMax
, tasks_max_resolve
);
28 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy
, cgroup_device_policy
, CGroupDevicePolicy
);
29 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_mode
, managed_oom_mode
, ManagedOOMMode
);
30 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_preference
, managed_oom_preference
, ManagedOOMPreference
);
32 static int property_get_cgroup_mask(
35 const char *interface
,
37 sd_bus_message
*reply
,
39 sd_bus_error
*error
) {
41 CGroupMask
*mask
= userdata
;
47 r
= sd_bus_message_open_container(reply
, 'a', "s");
51 for (CGroupController ctrl
= 0; ctrl
< _CGROUP_CONTROLLER_MAX
; ctrl
++) {
52 if ((*mask
& CGROUP_CONTROLLER_TO_MASK(ctrl
)) == 0)
55 r
= sd_bus_message_append(reply
, "s", cgroup_controller_to_string(ctrl
));
60 return sd_bus_message_close_container(reply
);
63 static int property_get_delegate_controllers(
66 const char *interface
,
68 sd_bus_message
*reply
,
70 sd_bus_error
*error
) {
72 CGroupContext
*c
= userdata
;
79 return sd_bus_message_append(reply
, "as", 0);
81 return property_get_cgroup_mask(bus
, path
, interface
, property
, reply
, &c
->delegate_controllers
, error
);
84 static int property_get_cpuset(
87 const char *interface
,
89 sd_bus_message
*reply
,
91 sd_bus_error
*error
) {
93 CPUSet
*cpus
= userdata
;
94 _cleanup_free_
uint8_t *array
= NULL
;
101 (void) cpu_set_to_dbus(cpus
, &array
, &allocated
);
102 return sd_bus_message_append_array(reply
, 'y', array
, allocated
);
105 static int property_get_io_device_weight(
108 const char *interface
,
109 const char *property
,
110 sd_bus_message
*reply
,
112 sd_bus_error
*error
) {
114 CGroupContext
*c
= userdata
;
115 CGroupIODeviceWeight
*w
;
122 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
126 LIST_FOREACH(device_weights
, w
, c
->io_device_weights
) {
127 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
132 return sd_bus_message_close_container(reply
);
135 static int property_get_io_device_limits(
138 const char *interface
,
139 const char *property
,
140 sd_bus_message
*reply
,
142 sd_bus_error
*error
) {
144 CGroupContext
*c
= userdata
;
145 CGroupIODeviceLimit
*l
;
152 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
156 LIST_FOREACH(device_limits
, l
, c
->io_device_limits
) {
157 CGroupIOLimitType type
;
159 type
= cgroup_io_limit_type_from_string(property
);
160 if (type
< 0 || l
->limits
[type
] == cgroup_io_limit_defaults
[type
])
163 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->limits
[type
]);
168 return sd_bus_message_close_container(reply
);
171 static int property_get_io_device_latency(
174 const char *interface
,
175 const char *property
,
176 sd_bus_message
*reply
,
178 sd_bus_error
*error
) {
180 CGroupContext
*c
= userdata
;
181 CGroupIODeviceLatency
*l
;
188 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
192 LIST_FOREACH(device_latencies
, l
, c
->io_device_latencies
) {
193 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->target_usec
);
198 return sd_bus_message_close_container(reply
);
201 static int property_get_blockio_device_weight(
204 const char *interface
,
205 const char *property
,
206 sd_bus_message
*reply
,
208 sd_bus_error
*error
) {
210 CGroupContext
*c
= userdata
;
211 CGroupBlockIODeviceWeight
*w
;
218 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
222 LIST_FOREACH(device_weights
, w
, c
->blockio_device_weights
) {
223 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
228 return sd_bus_message_close_container(reply
);
231 static int property_get_blockio_device_bandwidths(
234 const char *interface
,
235 const char *property
,
236 sd_bus_message
*reply
,
238 sd_bus_error
*error
) {
240 CGroupContext
*c
= userdata
;
241 CGroupBlockIODeviceBandwidth
*b
;
248 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
252 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
255 if (streq(property
, "BlockIOReadBandwidth"))
260 if (v
== CGROUP_LIMIT_MAX
)
263 r
= sd_bus_message_append(reply
, "(st)", b
->path
, v
);
268 return sd_bus_message_close_container(reply
);
271 static int property_get_device_allow(
274 const char *interface
,
275 const char *property
,
276 sd_bus_message
*reply
,
278 sd_bus_error
*error
) {
280 CGroupContext
*c
= userdata
;
281 CGroupDeviceAllow
*a
;
288 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
292 LIST_FOREACH(device_allow
, a
, c
->device_allow
) {
305 r
= sd_bus_message_append(reply
, "(ss)", a
->path
, rwm
);
310 return sd_bus_message_close_container(reply
);
313 static int property_get_ip_address_access(
316 const char *interface
,
317 const char *property
,
318 sd_bus_message
*reply
,
320 sd_bus_error
*error
) {
322 Set
**prefixes
= userdata
;
323 struct in_addr_prefix
*i
;
328 r
= sd_bus_message_open_container(reply
, 'a', "(iayu)");
332 SET_FOREACH(i
, *prefixes
) {
334 r
= sd_bus_message_open_container(reply
, 'r', "iayu");
338 r
= sd_bus_message_append(reply
, "i", i
->family
);
342 r
= sd_bus_message_append_array(reply
, 'y', &i
->address
, FAMILY_ADDRESS_SIZE(i
->family
));
346 r
= sd_bus_message_append(reply
, "u", (uint32_t) i
->prefixlen
);
350 r
= sd_bus_message_close_container(reply
);
355 return sd_bus_message_close_container(reply
);
358 static int property_get_bpf_foreign_program(
361 const char *interface
,
362 const char *property
,
363 sd_bus_message
*reply
,
365 sd_bus_error
*error
) {
366 CGroupContext
*c
= userdata
;
367 CGroupBPFForeignProgram
*p
;
370 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
374 LIST_FOREACH(programs
, p
, c
->bpf_foreign_programs
) {
375 const char *attach_type
= bpf_cgroup_attach_type_to_string(p
->attach_type
);
377 r
= sd_bus_message_append(reply
, "(ss)", attach_type
, p
->bpffs_path
);
382 return sd_bus_message_close_container(reply
);
385 static int property_get_socket_bind(
388 const char *interface
,
389 const char *property
,
390 sd_bus_message
*reply
,
392 sd_bus_error
*error
) {
393 CGroupSocketBindItem
**items
= userdata
, *i
;
398 r
= sd_bus_message_open_container(reply
, 'a', "(iiqq)");
402 LIST_FOREACH(socket_bind_items
, i
, *items
) {
403 r
= sd_bus_message_append(reply
, "(iiqq)", i
->address_family
, i
->ip_protocol
, i
->nr_ports
, i
->port_min
);
408 return sd_bus_message_close_container(reply
);
411 static int property_get_restrict_network_interfaces(
414 const char *interface
,
415 const char *property
,
416 sd_bus_message
*reply
,
418 sd_bus_error
*error
) {
420 CGroupContext
*c
= userdata
;
427 r
= sd_bus_message_open_container(reply
, 'r', "bas");
431 r
= sd_bus_message_append(reply
, "b", c
->restrict_network_interfaces_is_allow_list
);
435 r
= sd_bus_message_open_container(reply
, 'a', "s");
439 SET_FOREACH(iface
, c
->restrict_network_interfaces
) {
440 r
= sd_bus_message_append(reply
, "s", iface
);
445 r
= sd_bus_message_close_container(reply
);
449 return sd_bus_message_close_container(reply
);
452 const sd_bus_vtable bus_cgroup_vtable
[] = {
453 SD_BUS_VTABLE_START(0),
454 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool
, offsetof(CGroupContext
, delegate
), 0),
455 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers
, 0, 0),
456 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, cpu_accounting
), 0),
457 SD_BUS_PROPERTY("CPUWeight", "t", NULL
, offsetof(CGroupContext
, cpu_weight
), 0),
458 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL
, offsetof(CGroupContext
, startup_cpu_weight
), 0),
459 SD_BUS_PROPERTY("CPUShares", "t", NULL
, offsetof(CGroupContext
, cpu_shares
), 0),
460 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL
, offsetof(CGroupContext
, startup_cpu_shares
), 0),
461 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_per_sec_usec
), 0),
462 SD_BUS_PROPERTY("CPUQuotaPeriodUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_period_usec
), 0),
463 SD_BUS_PROPERTY("AllowedCPUs", "ay", property_get_cpuset
, offsetof(CGroupContext
, cpuset_cpus
), 0),
464 SD_BUS_PROPERTY("StartupAllowedCPUs", "ay", property_get_cpuset
, offsetof(CGroupContext
, startup_cpuset_cpus
), 0),
465 SD_BUS_PROPERTY("AllowedMemoryNodes", "ay", property_get_cpuset
, offsetof(CGroupContext
, cpuset_mems
), 0),
466 SD_BUS_PROPERTY("StartupAllowedMemoryNodes", "ay", property_get_cpuset
, offsetof(CGroupContext
, startup_cpuset_mems
), 0),
467 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, io_accounting
), 0),
468 SD_BUS_PROPERTY("IOWeight", "t", NULL
, offsetof(CGroupContext
, io_weight
), 0),
469 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_io_weight
), 0),
470 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight
, 0, 0),
471 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
472 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
473 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
474 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
475 SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency
, 0, 0),
476 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, blockio_accounting
), 0),
477 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL
, offsetof(CGroupContext
, blockio_weight
), 0),
478 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_blockio_weight
), 0),
479 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight
, 0, 0),
480 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
481 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
482 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_accounting
), 0),
483 SD_BUS_PROPERTY("DefaultMemoryLow", "t", NULL
, offsetof(CGroupContext
, default_memory_low
), 0),
484 SD_BUS_PROPERTY("DefaultMemoryMin", "t", NULL
, offsetof(CGroupContext
, default_memory_min
), 0),
485 SD_BUS_PROPERTY("MemoryMin", "t", NULL
, offsetof(CGroupContext
, memory_min
), 0),
486 SD_BUS_PROPERTY("MemoryLow", "t", NULL
, offsetof(CGroupContext
, memory_low
), 0),
487 SD_BUS_PROPERTY("MemoryHigh", "t", NULL
, offsetof(CGroupContext
, memory_high
), 0),
488 SD_BUS_PROPERTY("MemoryMax", "t", NULL
, offsetof(CGroupContext
, memory_max
), 0),
489 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL
, offsetof(CGroupContext
, memory_swap_max
), 0),
490 SD_BUS_PROPERTY("MemoryLimit", "t", NULL
, offsetof(CGroupContext
, memory_limit
), 0),
491 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
492 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
493 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
494 SD_BUS_PROPERTY("TasksMax", "t", bus_property_get_tasks_max
, offsetof(CGroupContext
, tasks_max
), 0),
495 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, ip_accounting
), 0),
496 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_allow
), 0),
497 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_deny
), 0),
498 SD_BUS_PROPERTY("IPIngressFilterPath", "as", NULL
, offsetof(CGroupContext
, ip_filters_ingress
), 0),
499 SD_BUS_PROPERTY("IPEgressFilterPath", "as", NULL
, offsetof(CGroupContext
, ip_filters_egress
), 0),
500 SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask
, offsetof(CGroupContext
, disable_controllers
), 0),
501 SD_BUS_PROPERTY("ManagedOOMSwap", "s", property_get_managed_oom_mode
, offsetof(CGroupContext
, moom_swap
), 0),
502 SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode
, offsetof(CGroupContext
, moom_mem_pressure
), 0),
503 SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimit", "u", NULL
, offsetof(CGroupContext
, moom_mem_pressure_limit
), 0),
504 SD_BUS_PROPERTY("ManagedOOMPreference", "s", property_get_managed_oom_preference
, offsetof(CGroupContext
, moom_preference
), 0),
505 SD_BUS_PROPERTY("BPFProgram", "a(ss)", property_get_bpf_foreign_program
, 0, 0),
506 SD_BUS_PROPERTY("SocketBindAllow", "a(iiqq)", property_get_socket_bind
, offsetof(CGroupContext
, socket_bind_allow
), 0),
507 SD_BUS_PROPERTY("SocketBindDeny", "a(iiqq)", property_get_socket_bind
, offsetof(CGroupContext
, socket_bind_deny
), 0),
508 SD_BUS_PROPERTY("RestrictNetworkInterfaces", "(bas)", property_get_restrict_network_interfaces
, 0, 0),
512 static int bus_cgroup_set_transient_property(
516 sd_bus_message
*message
,
517 UnitWriteFlags flags
,
518 sd_bus_error
*error
) {
527 flags
|= UNIT_PRIVATE
;
529 if (streq(name
, "Delegate")) {
532 if (!UNIT_VTABLE(u
)->can_delegate
)
533 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
535 r
= sd_bus_message_read(message
, "b", &b
);
539 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
541 c
->delegate_controllers
= b
? _CGROUP_MASK_ALL
: 0;
543 unit_write_settingf(u
, flags
, name
, "Delegate=%s", yes_no(b
));
548 } else if (STR_IN_SET(name
, "DelegateControllers", "DisableControllers")) {
551 if (streq(name
, "DelegateControllers") && !UNIT_VTABLE(u
)->can_delegate
)
552 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
554 r
= sd_bus_message_enter_container(message
, 'a', "s");
562 r
= sd_bus_message_read(message
, "s", &t
);
568 cc
= cgroup_controller_from_string(t
);
570 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown cgroup controller '%s'", t
);
572 mask
|= CGROUP_CONTROLLER_TO_MASK(cc
);
575 r
= sd_bus_message_exit_container(message
);
579 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
580 _cleanup_free_
char *t
= NULL
;
582 r
= cg_mask_to_string(mask
, &t
);
586 if (streq(name
, "DelegateControllers")) {
590 c
->delegate_controllers
= 0;
592 c
->delegate_controllers
|= mask
;
594 unit_write_settingf(u
, flags
, name
, "Delegate=%s", strempty(t
));
596 } else if (streq(name
, "DisableControllers")) {
599 c
->disable_controllers
= 0;
601 c
->disable_controllers
|= mask
;
603 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, strempty(t
));
608 } else if (STR_IN_SET(name
, "IPIngressFilterPath", "IPEgressFilterPath")) {
612 filters
= streq(name
, "IPIngressFilterPath") ? &c
->ip_filters_ingress
: &c
->ip_filters_egress
;
613 r
= sd_bus_message_enter_container(message
, 'a', "s");
620 r
= sd_bus_message_read(message
, "s", &path
);
626 if (!path_is_normalized(path
) || !path_is_absolute(path
))
627 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects a normalized absolute path.", name
);
629 if (!UNIT_WRITE_FLAGS_NOOP(flags
) && !strv_contains(*filters
, path
)) {
630 r
= strv_extend(filters
, path
);
636 r
= sd_bus_message_exit_container(message
);
640 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
641 _cleanup_free_
char *buf
= NULL
;
642 _cleanup_fclose_
FILE *f
= NULL
;
647 *filters
= strv_free(*filters
);
649 unit_invalidate_cgroup_bpf(u
);
650 f
= open_memstream_unlocked(&buf
, &size
);
657 STRV_FOREACH(entry
, *filters
)
658 fprintf(f
, "%s=%s\n", name
, *entry
);
660 r
= fflush_and_check(f
);
664 unit_write_setting(u
, flags
, name
, buf
);
667 r
= bpf_firewall_supported();
670 if (r
!= BPF_FIREWALL_SUPPORTED_WITH_MULTI
) {
671 static bool warned
= false;
673 log_full(warned
? LOG_DEBUG
: LOG_WARNING
,
674 "Transient unit %s configures an IP firewall with BPF, but the local system does not support BPF/cgroup firewalling with multiple filters.\n"
675 "Starting this unit will fail! (This warning is only shown for the first started transient unit using IP firewalling.)", u
->id
);
682 } else if (streq(name
, "BPFProgram")) {
686 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
690 while ((r
= sd_bus_message_read(message
, "(ss)", &a
, &p
)) > 0) {
691 int attach_type
= bpf_cgroup_attach_type_from_string(a
);
693 return sd_bus_error_setf(
695 SD_BUS_ERROR_INVALID_ARGS
,
696 "%s expects a valid BPF attach type, got '%s'.",
699 if (!path_is_normalized(p
) || !path_is_absolute(p
))
700 return sd_bus_error_setf(
702 SD_BUS_ERROR_INVALID_ARGS
,
703 "%s= expects a normalized absolute path.",
706 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
707 r
= cgroup_add_bpf_foreign_program(c
, attach_type
, p
);
716 r
= sd_bus_message_exit_container(message
);
720 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
721 _cleanup_free_
char *buf
= NULL
;
722 _cleanup_fclose_
FILE *f
= NULL
;
723 CGroupBPFForeignProgram
*fp
;
727 while (c
->bpf_foreign_programs
)
728 cgroup_context_remove_bpf_foreign_program(c
, c
->bpf_foreign_programs
);
730 f
= open_memstream_unlocked(&buf
, &size
);
737 LIST_FOREACH(programs
, fp
, c
->bpf_foreign_programs
)
738 fprintf(f
, "%s=%s:%s\n", name
,
739 bpf_cgroup_attach_type_to_string(fp
->attach_type
),
742 r
= fflush_and_check(f
);
746 unit_write_setting(u
, flags
, name
, buf
);
748 if (!LIST_IS_EMPTY(c
->bpf_foreign_programs
)) {
749 r
= bpf_foreign_supported();
754 "Transient unit %s configures a BPF program pinned to BPF "
755 "filesystem, but the local system does not support that.\n"
756 "Starting this unit will fail!", u
->id
);
766 static int bus_cgroup_set_boolean(
771 sd_bus_message
*message
,
772 UnitWriteFlags flags
,
773 sd_bus_error
*error
) {
779 r
= sd_bus_message_read(message
, "b", &b
);
783 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
785 unit_invalidate_cgroup(u
, mask
);
786 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, yes_no(b
));
792 #define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \
793 static int bus_cgroup_set_##function( \
797 sd_bus_message *message, \
798 UnitWriteFlags flags, \
799 sd_bus_error *error) { \
806 r = sd_bus_message_read(message, "t", &v); \
811 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
812 "Value specified in %s is out of range", name); \
814 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
816 unit_invalidate_cgroup(u, mask); \
819 unit_write_settingf(u, flags, name, \
822 unit_write_settingf(u, flags, name, \
823 "%s=%" PRIu64, name, v); \
829 #define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \
830 static int bus_cgroup_set_##function( \
834 sd_bus_message *message, \
835 UnitWriteFlags flags, \
836 sd_bus_error *error) { \
843 r = sd_bus_message_read(message, "t", &v); \
848 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
849 "Value specified in %s is out of range", name); \
851 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
853 unit_invalidate_cgroup(u, mask); \
855 if (v == CGROUP_LIMIT_MAX) \
856 unit_write_settingf(u, flags, name, \
857 "%s=infinity", name); \
859 unit_write_settingf(u, flags, name, \
860 "%s=%" PRIu64, name, v); \
865 static int bus_cgroup_set_##function##_scale( \
869 sd_bus_message *message, \
870 UnitWriteFlags flags, \
871 sd_bus_error *error) { \
879 r = sd_bus_message_read(message, "u", &raw); \
883 v = scale(raw, UINT32_MAX); \
884 if (v < minimum || v >= UINT64_MAX) \
885 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
886 "Value specified in %s is out of range", name); \
888 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
890 unit_invalidate_cgroup(u, mask); \
892 /* Prepare to chop off suffix */ \
893 assert_se(endswith(name, "Scale")); \
895 int scaled = UINT32_SCALE_TO_PERMYRIAD(raw); \
896 unit_write_settingf(u, flags, name, "%.*s=" PERMYRIAD_AS_PERCENT_FORMAT_STR, \
897 (int)(strlen(name) - strlen("Scale")), name, \
898 PERMYRIAD_AS_PERCENT_FORMAT_VAL(scaled)); \
904 DISABLE_WARNING_TYPE_LIMITS
;
905 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight
, CGROUP_MASK_CPU
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
906 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares
, CGROUP_MASK_CPU
, CGROUP_CPU_SHARES_IS_OK
, CGROUP_CPU_SHARES_INVALID
);
907 BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight
, CGROUP_MASK_IO
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
908 BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight
, CGROUP_MASK_BLKIO
, CGROUP_BLKIO_WEIGHT_IS_OK
, CGROUP_BLKIO_WEIGHT_INVALID
);
909 BUS_DEFINE_SET_CGROUP_LIMIT(memory
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 1);
910 BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
911 BUS_DEFINE_SET_CGROUP_LIMIT(swap
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
914 static int bus_cgroup_set_tasks_max(
918 sd_bus_message
*message
,
919 UnitWriteFlags flags
,
920 sd_bus_error
*error
) {
927 r
= sd_bus_message_read(message
, "t", &v
);
932 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
933 "Value specified in %s is out of range", name
);
935 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
936 *p
= (TasksMax
) { .value
= v
, .scale
= 0 }; /* When .scale==0, .value is the absolute value */
937 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
939 if (v
== CGROUP_LIMIT_MAX
)
940 unit_write_settingf(u
, flags
, name
,
941 "%s=infinity", name
);
943 unit_write_settingf(u
, flags
, name
,
944 "%s=%" PRIu64
, name
, v
);
950 static int bus_cgroup_set_tasks_max_scale(
954 sd_bus_message
*message
,
955 UnitWriteFlags flags
,
956 sd_bus_error
*error
) {
963 r
= sd_bus_message_read(message
, "u", &v
);
967 if (v
< 1 || v
>= UINT32_MAX
)
968 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
969 "Value specified in %s is out of range", name
);
971 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
972 *p
= (TasksMax
) { v
, UINT32_MAX
}; /* .scale is not 0, so this is interpreted as v/UINT32_MAX. */
973 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
975 uint32_t scaled
= DIV_ROUND_UP((uint64_t) v
* 100U, (uint64_t) UINT32_MAX
);
976 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu32
".%" PRIu32
"%%", "TasksMax",
977 scaled
/ 10, scaled
% 10);
983 int bus_cgroup_set_property(
987 sd_bus_message
*message
,
988 UnitWriteFlags flags
,
989 sd_bus_error
*error
) {
991 CGroupIOLimitType iol_type
;
999 flags
|= UNIT_PRIVATE
;
1001 if (streq(name
, "CPUAccounting"))
1002 return bus_cgroup_set_boolean(u
, name
, &c
->cpu_accounting
, get_cpu_accounting_mask(), message
, flags
, error
);
1004 if (streq(name
, "CPUWeight"))
1005 return bus_cgroup_set_cpu_weight(u
, name
, &c
->cpu_weight
, message
, flags
, error
);
1007 if (streq(name
, "StartupCPUWeight"))
1008 return bus_cgroup_set_cpu_weight(u
, name
, &c
->startup_cpu_weight
, message
, flags
, error
);
1010 if (streq(name
, "CPUShares"))
1011 return bus_cgroup_set_cpu_shares(u
, name
, &c
->cpu_shares
, message
, flags
, error
);
1013 if (streq(name
, "StartupCPUShares"))
1014 return bus_cgroup_set_cpu_shares(u
, name
, &c
->startup_cpu_shares
, message
, flags
, error
);
1016 if (streq(name
, "IOAccounting"))
1017 return bus_cgroup_set_boolean(u
, name
, &c
->io_accounting
, CGROUP_MASK_IO
, message
, flags
, error
);
1019 if (streq(name
, "IOWeight"))
1020 return bus_cgroup_set_io_weight(u
, name
, &c
->io_weight
, message
, flags
, error
);
1022 if (streq(name
, "StartupIOWeight"))
1023 return bus_cgroup_set_io_weight(u
, name
, &c
->startup_io_weight
, message
, flags
, error
);
1025 if (streq(name
, "BlockIOAccounting"))
1026 return bus_cgroup_set_boolean(u
, name
, &c
->blockio_accounting
, CGROUP_MASK_BLKIO
, message
, flags
, error
);
1028 if (streq(name
, "BlockIOWeight"))
1029 return bus_cgroup_set_blockio_weight(u
, name
, &c
->blockio_weight
, message
, flags
, error
);
1031 if (streq(name
, "StartupBlockIOWeight"))
1032 return bus_cgroup_set_blockio_weight(u
, name
, &c
->startup_blockio_weight
, message
, flags
, error
);
1034 if (streq(name
, "MemoryAccounting"))
1035 return bus_cgroup_set_boolean(u
, name
, &c
->memory_accounting
, CGROUP_MASK_MEMORY
, message
, flags
, error
);
1037 if (streq(name
, "MemoryMin")) {
1038 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->memory_min
, message
, flags
, error
);
1040 c
->memory_min_set
= true;
1044 if (streq(name
, "MemoryLow")) {
1045 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->memory_low
, message
, flags
, error
);
1047 c
->memory_low_set
= true;
1051 if (streq(name
, "DefaultMemoryMin")) {
1052 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->default_memory_min
, message
, flags
, error
);
1054 c
->default_memory_min_set
= true;
1058 if (streq(name
, "DefaultMemoryLow")) {
1059 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->default_memory_low
, message
, flags
, error
);
1061 c
->default_memory_low_set
= true;
1065 if (streq(name
, "MemoryHigh"))
1066 return bus_cgroup_set_memory(u
, name
, &c
->memory_high
, message
, flags
, error
);
1068 if (streq(name
, "MemorySwapMax"))
1069 return bus_cgroup_set_swap(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
1071 if (streq(name
, "MemoryMax"))
1072 return bus_cgroup_set_memory(u
, name
, &c
->memory_max
, message
, flags
, error
);
1074 if (streq(name
, "MemoryLimit"))
1075 return bus_cgroup_set_memory(u
, name
, &c
->memory_limit
, message
, flags
, error
);
1077 if (streq(name
, "MemoryMinScale")) {
1078 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->memory_min
, message
, flags
, error
);
1080 c
->memory_min_set
= true;
1084 if (streq(name
, "MemoryLowScale")) {
1085 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->memory_low
, message
, flags
, error
);
1087 c
->memory_low_set
= true;
1091 if (streq(name
, "DefaultMemoryMinScale")) {
1092 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->default_memory_min
, message
, flags
, error
);
1094 c
->default_memory_min_set
= true;
1098 if (streq(name
, "DefaultMemoryLowScale")) {
1099 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->default_memory_low
, message
, flags
, error
);
1101 c
->default_memory_low_set
= true;
1105 if (streq(name
, "MemoryHighScale"))
1106 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_high
, message
, flags
, error
);
1108 if (streq(name
, "MemorySwapMaxScale"))
1109 return bus_cgroup_set_swap_scale(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
1111 if (streq(name
, "MemoryMaxScale"))
1112 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_max
, message
, flags
, error
);
1114 if (streq(name
, "MemoryLimitScale"))
1115 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_limit
, message
, flags
, error
);
1117 if (streq(name
, "TasksAccounting"))
1118 return bus_cgroup_set_boolean(u
, name
, &c
->tasks_accounting
, CGROUP_MASK_PIDS
, message
, flags
, error
);
1120 if (streq(name
, "TasksMax"))
1121 return bus_cgroup_set_tasks_max(u
, name
, &c
->tasks_max
, message
, flags
, error
);
1123 if (streq(name
, "TasksMaxScale"))
1124 return bus_cgroup_set_tasks_max_scale(u
, name
, &c
->tasks_max
, message
, flags
, error
);
1126 if (streq(name
, "CPUQuotaPerSecUSec")) {
1129 r
= sd_bus_message_read(message
, "t", &u64
);
1134 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "CPUQuotaPerSecUSec= value out of range");
1136 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1137 c
->cpu_quota_per_sec_usec
= u64
;
1138 u
->warned_clamping_cpu_quota_period
= false;
1139 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
1141 if (c
->cpu_quota_per_sec_usec
== USEC_INFINITY
)
1142 unit_write_setting(u
, flags
, "CPUQuota", "CPUQuota=");
1144 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
1146 unit_write_settingf(u
, flags
, "CPUQuota",
1148 (double) (c
->cpu_quota_per_sec_usec
/ 10000));
1153 } else if (streq(name
, "CPUQuotaPeriodUSec")) {
1156 r
= sd_bus_message_read(message
, "t", &u64
);
1160 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1161 c
->cpu_quota_period_usec
= u64
;
1162 u
->warned_clamping_cpu_quota_period
= false;
1163 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
1164 if (c
->cpu_quota_period_usec
== USEC_INFINITY
)
1165 unit_write_setting(u
, flags
, "CPUQuotaPeriodSec", "CPUQuotaPeriodSec=");
1167 unit_write_settingf(u
, flags
, "CPUQuotaPeriodSec",
1168 "CPUQuotaPeriodSec=%s",
1169 FORMAT_TIMESPAN(c
->cpu_quota_period_usec
, 1));
1174 } else if (STR_IN_SET(name
, "AllowedCPUs", "StartupAllowedCPUs", "AllowedMemoryNodes", "StartupAllowedMemoryNodes")) {
1177 _cleanup_(cpu_set_reset
) CPUSet new_set
= {};
1179 r
= sd_bus_message_read_array(message
, 'y', &a
, &n
);
1183 r
= cpu_set_from_dbus(a
, n
, &new_set
);
1187 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1188 _cleanup_free_
char *setstr
= NULL
;
1191 setstr
= cpu_set_to_range_string(&new_set
);
1195 if (streq(name
, "AllowedCPUs"))
1196 set
= &c
->cpuset_cpus
;
1197 else if (streq(name
, "StartupAllowedCPUs"))
1198 set
= &c
->startup_cpuset_cpus
;
1199 else if (streq(name
, "AllowedMemoryNodes"))
1200 set
= &c
->cpuset_mems
;
1201 else if (streq(name
, "StartupAllowedMemoryNodes"))
1202 set
= &c
->startup_cpuset_mems
;
1208 new_set
= (CPUSet
) {};
1210 unit_invalidate_cgroup(u
, CGROUP_MASK_CPUSET
);
1211 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, setstr
);
1216 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
1221 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1225 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
1227 if (!path_is_normalized(path
))
1228 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1230 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1231 CGroupIODeviceLimit
*a
= NULL
, *b
;
1233 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
) {
1234 if (path_equal(path
, b
->path
)) {
1241 CGroupIOLimitType type
;
1243 a
= new0(CGroupIODeviceLimit
, 1);
1247 a
->path
= strdup(path
);
1253 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
1254 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
1256 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
1259 a
->limits
[iol_type
] = u64
;
1267 r
= sd_bus_message_exit_container(message
);
1271 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1272 CGroupIODeviceLimit
*a
;
1273 _cleanup_free_
char *buf
= NULL
;
1274 _cleanup_fclose_
FILE *f
= NULL
;
1278 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
1279 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
1282 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1284 f
= open_memstream_unlocked(&buf
, &size
);
1288 fprintf(f
, "%s=\n", name
);
1289 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
1290 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
1291 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
1293 r
= fflush_and_check(f
);
1296 unit_write_setting(u
, flags
, name
, buf
);
1301 } else if (streq(name
, "IODeviceWeight")) {
1306 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1310 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
1312 if (!path_is_normalized(path
))
1313 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1315 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
1316 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "IODeviceWeight= value out of range");
1318 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1319 CGroupIODeviceWeight
*a
= NULL
, *b
;
1321 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
) {
1322 if (path_equal(b
->path
, path
)) {
1329 a
= new0(CGroupIODeviceWeight
, 1);
1333 a
->path
= strdup(path
);
1338 LIST_PREPEND(device_weights
, c
->io_device_weights
, a
);
1347 r
= sd_bus_message_exit_container(message
);
1351 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1352 _cleanup_free_
char *buf
= NULL
;
1353 _cleanup_fclose_
FILE *f
= NULL
;
1354 CGroupIODeviceWeight
*a
;
1358 while (c
->io_device_weights
)
1359 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
1362 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1364 f
= open_memstream_unlocked(&buf
, &size
);
1368 fputs("IODeviceWeight=\n", f
);
1369 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
1370 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1372 r
= fflush_and_check(f
);
1375 unit_write_setting(u
, flags
, name
, buf
);
1380 } else if (streq(name
, "IODeviceLatencyTargetUSec")) {
1385 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1389 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &target
)) > 0) {
1391 if (!path_is_normalized(path
))
1392 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1394 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1395 CGroupIODeviceLatency
*a
= NULL
, *b
;
1397 LIST_FOREACH(device_latencies
, b
, c
->io_device_latencies
) {
1398 if (path_equal(b
->path
, path
)) {
1405 a
= new0(CGroupIODeviceLatency
, 1);
1409 a
->path
= strdup(path
);
1414 LIST_PREPEND(device_latencies
, c
->io_device_latencies
, a
);
1417 a
->target_usec
= target
;
1423 r
= sd_bus_message_exit_container(message
);
1427 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1428 _cleanup_free_
char *buf
= NULL
;
1429 _cleanup_fclose_
FILE *f
= NULL
;
1430 CGroupIODeviceLatency
*a
;
1434 while (c
->io_device_latencies
)
1435 cgroup_context_free_io_device_latency(c
, c
->io_device_latencies
);
1438 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1440 f
= open_memstream_unlocked(&buf
, &size
);
1444 fputs("IODeviceLatencyTargetSec=\n", f
);
1445 LIST_FOREACH(device_latencies
, a
, c
->io_device_latencies
)
1446 fprintf(f
, "IODeviceLatencyTargetSec=%s %s\n",
1447 a
->path
, FORMAT_TIMESPAN(a
->target_usec
, 1));
1449 r
= fflush_and_check(f
);
1452 unit_write_setting(u
, flags
, name
, buf
);
1457 } else if (STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1463 if (streq(name
, "BlockIOWriteBandwidth"))
1466 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1470 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
1472 if (!path_is_normalized(path
))
1473 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1475 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1476 CGroupBlockIODeviceBandwidth
*a
= NULL
, *b
;
1478 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
1479 if (path_equal(path
, b
->path
)) {
1486 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
1490 a
->rbps
= CGROUP_LIMIT_MAX
;
1491 a
->wbps
= CGROUP_LIMIT_MAX
;
1492 a
->path
= strdup(path
);
1498 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
1512 r
= sd_bus_message_exit_container(message
);
1516 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1517 CGroupBlockIODeviceBandwidth
*a
;
1518 _cleanup_free_
char *buf
= NULL
;
1519 _cleanup_fclose_
FILE *f
= NULL
;
1523 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
1525 a
->rbps
= CGROUP_LIMIT_MAX
;
1527 a
->wbps
= CGROUP_LIMIT_MAX
;
1531 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1533 f
= open_memstream_unlocked(&buf
, &size
);
1538 fputs("BlockIOReadBandwidth=\n", f
);
1539 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
1540 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
1541 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
1543 fputs("BlockIOWriteBandwidth=\n", f
);
1544 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
1545 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
1546 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
1549 r
= fflush_and_check(f
);
1553 unit_write_setting(u
, flags
, name
, buf
);
1558 } else if (streq(name
, "BlockIODeviceWeight")) {
1563 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1567 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
1569 if (!path_is_normalized(path
))
1570 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1572 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
1573 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "BlockIODeviceWeight= out of range");
1575 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1576 CGroupBlockIODeviceWeight
*a
= NULL
, *b
;
1578 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
) {
1579 if (path_equal(b
->path
, path
)) {
1586 a
= new0(CGroupBlockIODeviceWeight
, 1);
1590 a
->path
= strdup(path
);
1595 LIST_PREPEND(device_weights
, c
->blockio_device_weights
, a
);
1604 r
= sd_bus_message_exit_container(message
);
1608 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1609 _cleanup_free_
char *buf
= NULL
;
1610 _cleanup_fclose_
FILE *f
= NULL
;
1611 CGroupBlockIODeviceWeight
*a
;
1615 while (c
->blockio_device_weights
)
1616 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
1619 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1621 f
= open_memstream_unlocked(&buf
, &size
);
1625 fputs("BlockIODeviceWeight=\n", f
);
1626 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
1627 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1629 r
= fflush_and_check(f
);
1633 unit_write_setting(u
, flags
, name
, buf
);
1638 } else if (streq(name
, "DevicePolicy")) {
1640 CGroupDevicePolicy p
;
1642 r
= sd_bus_message_read(message
, "s", &policy
);
1646 p
= cgroup_device_policy_from_string(policy
);
1650 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1651 c
->device_policy
= p
;
1652 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1653 unit_write_settingf(u
, flags
, name
, "DevicePolicy=%s", policy
);
1658 } else if (streq(name
, "DeviceAllow")) {
1659 const char *path
, *rwm
;
1662 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
1666 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
1668 if (!valid_device_allow_pattern(path
) || strpbrk(path
, WHITESPACE
))
1669 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires device node or pattern");
1673 else if (!in_charset(rwm
, "rwm"))
1674 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires combination of rwm flags");
1676 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1677 CGroupDeviceAllow
*a
= NULL
, *b
;
1679 LIST_FOREACH(device_allow
, b
, c
->device_allow
) {
1680 if (path_equal(b
->path
, path
)) {
1687 a
= new0(CGroupDeviceAllow
, 1);
1691 a
->path
= strdup(path
);
1697 LIST_PREPEND(device_allow
, c
->device_allow
, a
);
1700 a
->r
= strchr(rwm
, 'r');
1701 a
->w
= strchr(rwm
, 'w');
1702 a
->m
= strchr(rwm
, 'm');
1710 r
= sd_bus_message_exit_container(message
);
1714 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1715 _cleanup_free_
char *buf
= NULL
;
1716 _cleanup_fclose_
FILE *f
= NULL
;
1717 CGroupDeviceAllow
*a
;
1721 while (c
->device_allow
)
1722 cgroup_context_free_device_allow(c
, c
->device_allow
);
1725 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1727 f
= open_memstream_unlocked(&buf
, &size
);
1731 fputs("DeviceAllow=\n", f
);
1732 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
1733 fprintf(f
, "DeviceAllow=%s %s%s%s\n", a
->path
, a
->r
? "r" : "", a
->w
? "w" : "", a
->m
? "m" : "");
1735 r
= fflush_and_check(f
);
1738 unit_write_setting(u
, flags
, name
, buf
);
1743 } else if (streq(name
, "IPAccounting")) {
1746 r
= sd_bus_message_read(message
, "b", &b
);
1750 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1751 c
->ip_accounting
= b
;
1753 unit_invalidate_cgroup_bpf(u
);
1754 unit_write_settingf(u
, flags
, name
, "IPAccounting=%s", yes_no(b
));
1759 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1760 _cleanup_set_free_ Set
*new_prefixes
= NULL
;
1763 r
= sd_bus_message_enter_container(message
, 'a', "(iayu)");
1773 r
= sd_bus_message_enter_container(message
, 'r', "iayu");
1779 r
= sd_bus_message_read(message
, "i", &family
);
1783 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1784 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects IPv4 or IPv6 addresses only.", name
);
1786 r
= sd_bus_message_read_array(message
, 'y', &ap
, &an
);
1790 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1791 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1792 af_to_name(family
), FAMILY_ADDRESS_SIZE(family
), an
);
1794 r
= sd_bus_message_read(message
, "u", &prefixlen
);
1798 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
)*8)
1799 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
));
1801 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1802 struct in_addr_prefix prefix
= {
1804 .prefixlen
= prefixlen
,
1807 memcpy(&prefix
.address
, ap
, an
);
1809 r
= in_addr_prefix_add(&new_prefixes
, &prefix
);
1814 r
= sd_bus_message_exit_container(message
);
1821 r
= sd_bus_message_exit_container(message
);
1825 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1826 _cleanup_free_
char *buf
= NULL
;
1827 _cleanup_fclose_
FILE *f
= NULL
;
1832 unit_invalidate_cgroup_bpf(u
);
1833 f
= open_memstream_unlocked(&buf
, &size
);
1837 prefixes
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow
: &c
->ip_address_deny
;
1838 reduced
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow_reduced
: &c
->ip_address_deny_reduced
;
1842 *prefixes
= set_free(*prefixes
);
1846 struct in_addr_prefix
*p
;
1850 r
= in_addr_prefixes_merge(prefixes
, new_prefixes
);
1854 SET_FOREACH(p
, new_prefixes
) {
1855 _cleanup_free_
char *buffer
= NULL
;
1857 r
= in_addr_prefix_to_string(p
->family
, &p
->address
, p
->prefixlen
, &buffer
);
1863 fprintf(f
, "%s=%s\n", name
, buffer
);
1867 r
= fflush_and_check(f
);
1871 unit_write_setting(u
, flags
, name
, buf
);
1877 if (STR_IN_SET(name
, "ManagedOOMSwap", "ManagedOOMMemoryPressure")) {
1878 ManagedOOMMode
*cgroup_mode
= streq(name
, "ManagedOOMSwap") ? &c
->moom_swap
: &c
->moom_mem_pressure
;
1882 if (!UNIT_VTABLE(u
)->can_set_managed_oom
)
1883 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot set %s for this unit type", name
);
1885 r
= sd_bus_message_read(message
, "s", &mode
);
1889 m
= managed_oom_mode_from_string(mode
);
1893 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1895 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, mode
);
1898 (void) manager_varlink_send_managed_oom_update(u
);
1902 if (streq(name
, "ManagedOOMMemoryPressureLimit")) {
1905 if (!UNIT_VTABLE(u
)->can_set_managed_oom
)
1906 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot set %s for this unit type", name
);
1908 r
= sd_bus_message_read(message
, "u", &v
);
1912 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1913 c
->moom_mem_pressure_limit
= v
;
1914 unit_write_settingf(u
, flags
, name
,
1915 "ManagedOOMMemoryPressureLimit=" PERMYRIAD_AS_PERCENT_FORMAT_STR
,
1916 PERMYRIAD_AS_PERCENT_FORMAT_VAL(UINT32_SCALE_TO_PERMYRIAD(v
)));
1919 if (c
->moom_mem_pressure
== MANAGED_OOM_KILL
)
1920 (void) manager_varlink_send_managed_oom_update(u
);
1925 if (streq(name
, "ManagedOOMPreference")) {
1926 ManagedOOMPreference p
;
1929 r
= sd_bus_message_read(message
, "s", &pref
);
1933 p
= managed_oom_preference_from_string(pref
);
1937 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1938 c
->moom_preference
= p
;
1939 unit_write_settingf(u
, flags
, name
, "ManagedOOMPreference=%s", pref
);
1944 if (STR_IN_SET(name
, "SocketBindAllow", "SocketBindDeny")) {
1945 CGroupSocketBindItem
**list
;
1946 uint16_t nr_ports
, port_min
;
1948 int32_t family
, ip_protocol
;
1950 list
= streq(name
, "SocketBindAllow") ? &c
->socket_bind_allow
: &c
->socket_bind_deny
;
1952 r
= sd_bus_message_enter_container(message
, 'a', "(iiqq)");
1956 while ((r
= sd_bus_message_read(message
, "(iiqq)", &family
, &ip_protocol
, &nr_ports
, &port_min
)) > 0) {
1958 if (!IN_SET(family
, AF_UNSPEC
, AF_INET
, AF_INET6
))
1959 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects INET or INET6 family, if specified.", name
);
1961 if (!IN_SET(ip_protocol
, 0, IPPROTO_TCP
, IPPROTO_UDP
))
1962 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects TCP or UDP protocol, if specified.", name
);
1964 if (port_min
+ (uint32_t) nr_ports
> (1 << 16))
1965 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects maximum port value lesser than 65536.", name
);
1967 if (port_min
== 0 && nr_ports
!= 0)
1968 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects port range starting with positive value.", name
);
1970 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1971 _cleanup_free_ CGroupSocketBindItem
*item
= NULL
;
1973 item
= new(CGroupSocketBindItem
, 1);
1977 *item
= (CGroupSocketBindItem
) {
1978 .address_family
= family
,
1979 .ip_protocol
= ip_protocol
,
1980 .nr_ports
= nr_ports
,
1981 .port_min
= port_min
1984 LIST_PREPEND(socket_bind_items
, *list
, TAKE_PTR(item
));
1991 r
= sd_bus_message_exit_container(message
);
1995 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1996 _cleanup_free_
char *buf
= NULL
;
1997 _cleanup_fclose_
FILE *f
= NULL
;
1998 CGroupSocketBindItem
*item
;
2002 cgroup_context_remove_socket_bind(list
);
2004 if ((u
->manager
->cgroup_supported
& CGROUP_MASK_BPF_SOCKET_BIND
) == 0)
2006 "Unit %s configures source compiled BPF programs "
2007 "but the local system does not support that.\n"
2008 "Starting this unit will fail!", u
->id
);
2011 f
= open_memstream_unlocked(&buf
, &size
);
2015 fprintf(f
, "%s:", name
);
2017 LIST_FOREACH(socket_bind_items
, item
, *list
)
2018 cgroup_context_dump_socket_bind_item(item
, f
);
2022 r
= fflush_and_check(f
);
2026 unit_write_setting(u
, flags
, name
, buf
);
2031 if (streq(name
, "RestrictNetworkInterfaces")) {
2033 _cleanup_strv_free_
char **l
= NULL
;
2035 r
= sd_bus_message_enter_container(message
, 'r', "bas");
2039 r
= sd_bus_message_read(message
, "b", &is_allow_list
);
2043 r
= sd_bus_message_read_strv(message
, &l
);
2047 r
= sd_bus_message_exit_container(message
);
2051 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2052 _cleanup_free_
char *joined
= NULL
;
2055 if (strv_isempty(l
)) {
2056 c
->restrict_network_interfaces_is_allow_list
= false;
2057 c
->restrict_network_interfaces
= set_free(c
->restrict_network_interfaces
);
2059 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2063 if (set_isempty(c
->restrict_network_interfaces
))
2064 c
->restrict_network_interfaces_is_allow_list
= is_allow_list
;
2066 STRV_FOREACH(s
, l
) {
2067 if (!ifname_valid(*s
)) {
2068 log_full(LOG_WARNING
, "Invalid interface name, ignoring: %s", *s
);
2071 if (c
->restrict_network_interfaces_is_allow_list
!= (bool) is_allow_list
)
2072 free(set_remove(c
->restrict_network_interfaces
, *s
));
2074 r
= set_put_strdup(&c
->restrict_network_interfaces
, *s
);
2080 joined
= strv_join(l
, " ");
2084 unit_write_settingf(u
, flags
, name
, "%s=%s%s", name
, is_allow_list
? "" : "~", joined
);
2090 if (streq(name
, "DisableControllers") || (u
->transient
&& u
->load_state
== UNIT_STUB
))
2091 return bus_cgroup_set_transient_property(u
, c
, name
, message
, flags
, error
);