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("AllowedMemoryNodes", "ay", property_get_cpuset
, offsetof(CGroupContext
, cpuset_mems
), 0),
465 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, io_accounting
), 0),
466 SD_BUS_PROPERTY("IOWeight", "t", NULL
, offsetof(CGroupContext
, io_weight
), 0),
467 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_io_weight
), 0),
468 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight
, 0, 0),
469 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
470 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
471 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
472 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
473 SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency
, 0, 0),
474 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, blockio_accounting
), 0),
475 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL
, offsetof(CGroupContext
, blockio_weight
), 0),
476 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_blockio_weight
), 0),
477 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight
, 0, 0),
478 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
479 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
480 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_accounting
), 0),
481 SD_BUS_PROPERTY("DefaultMemoryLow", "t", NULL
, offsetof(CGroupContext
, default_memory_low
), 0),
482 SD_BUS_PROPERTY("DefaultMemoryMin", "t", NULL
, offsetof(CGroupContext
, default_memory_min
), 0),
483 SD_BUS_PROPERTY("MemoryMin", "t", NULL
, offsetof(CGroupContext
, memory_min
), 0),
484 SD_BUS_PROPERTY("MemoryLow", "t", NULL
, offsetof(CGroupContext
, memory_low
), 0),
485 SD_BUS_PROPERTY("MemoryHigh", "t", NULL
, offsetof(CGroupContext
, memory_high
), 0),
486 SD_BUS_PROPERTY("MemoryMax", "t", NULL
, offsetof(CGroupContext
, memory_max
), 0),
487 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL
, offsetof(CGroupContext
, memory_swap_max
), 0),
488 SD_BUS_PROPERTY("MemoryLimit", "t", NULL
, offsetof(CGroupContext
, memory_limit
), 0),
489 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
490 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
491 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
492 SD_BUS_PROPERTY("TasksMax", "t", bus_property_get_tasks_max
, offsetof(CGroupContext
, tasks_max
), 0),
493 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, ip_accounting
), 0),
494 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_allow
), 0),
495 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_deny
), 0),
496 SD_BUS_PROPERTY("IPIngressFilterPath", "as", NULL
, offsetof(CGroupContext
, ip_filters_ingress
), 0),
497 SD_BUS_PROPERTY("IPEgressFilterPath", "as", NULL
, offsetof(CGroupContext
, ip_filters_egress
), 0),
498 SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask
, offsetof(CGroupContext
, disable_controllers
), 0),
499 SD_BUS_PROPERTY("ManagedOOMSwap", "s", property_get_managed_oom_mode
, offsetof(CGroupContext
, moom_swap
), 0),
500 SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode
, offsetof(CGroupContext
, moom_mem_pressure
), 0),
501 SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimit", "u", NULL
, offsetof(CGroupContext
, moom_mem_pressure_limit
), 0),
502 SD_BUS_PROPERTY("ManagedOOMPreference", "s", property_get_managed_oom_preference
, offsetof(CGroupContext
, moom_preference
), 0),
503 SD_BUS_PROPERTY("BPFProgram", "a(ss)", property_get_bpf_foreign_program
, 0, 0),
504 SD_BUS_PROPERTY("SocketBindAllow", "a(iiqq)", property_get_socket_bind
, offsetof(CGroupContext
, socket_bind_allow
), 0),
505 SD_BUS_PROPERTY("SocketBindDeny", "a(iiqq)", property_get_socket_bind
, offsetof(CGroupContext
, socket_bind_deny
), 0),
506 SD_BUS_PROPERTY("RestrictNetworkInterfaces", "(bas)", property_get_restrict_network_interfaces
, 0, 0),
510 static int bus_cgroup_set_transient_property(
514 sd_bus_message
*message
,
515 UnitWriteFlags flags
,
516 sd_bus_error
*error
) {
525 flags
|= UNIT_PRIVATE
;
527 if (streq(name
, "Delegate")) {
530 if (!UNIT_VTABLE(u
)->can_delegate
)
531 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
533 r
= sd_bus_message_read(message
, "b", &b
);
537 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
539 c
->delegate_controllers
= b
? _CGROUP_MASK_ALL
: 0;
541 unit_write_settingf(u
, flags
, name
, "Delegate=%s", yes_no(b
));
546 } else if (STR_IN_SET(name
, "DelegateControllers", "DisableControllers")) {
549 if (streq(name
, "DelegateControllers") && !UNIT_VTABLE(u
)->can_delegate
)
550 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
552 r
= sd_bus_message_enter_container(message
, 'a', "s");
560 r
= sd_bus_message_read(message
, "s", &t
);
566 cc
= cgroup_controller_from_string(t
);
568 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown cgroup controller '%s'", t
);
570 mask
|= CGROUP_CONTROLLER_TO_MASK(cc
);
573 r
= sd_bus_message_exit_container(message
);
577 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
578 _cleanup_free_
char *t
= NULL
;
580 r
= cg_mask_to_string(mask
, &t
);
584 if (streq(name
, "DelegateControllers")) {
588 c
->delegate_controllers
= 0;
590 c
->delegate_controllers
|= mask
;
592 unit_write_settingf(u
, flags
, name
, "Delegate=%s", strempty(t
));
594 } else if (streq(name
, "DisableControllers")) {
597 c
->disable_controllers
= 0;
599 c
->disable_controllers
|= mask
;
601 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, strempty(t
));
606 } else if (STR_IN_SET(name
, "IPIngressFilterPath", "IPEgressFilterPath")) {
610 filters
= streq(name
, "IPIngressFilterPath") ? &c
->ip_filters_ingress
: &c
->ip_filters_egress
;
611 r
= sd_bus_message_enter_container(message
, 'a', "s");
618 r
= sd_bus_message_read(message
, "s", &path
);
624 if (!path_is_normalized(path
) || !path_is_absolute(path
))
625 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects a normalized absolute path.", name
);
627 if (!UNIT_WRITE_FLAGS_NOOP(flags
) && !strv_contains(*filters
, path
)) {
628 r
= strv_extend(filters
, path
);
634 r
= sd_bus_message_exit_container(message
);
638 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
639 _cleanup_free_
char *buf
= NULL
;
640 _cleanup_fclose_
FILE *f
= NULL
;
645 *filters
= strv_free(*filters
);
647 unit_invalidate_cgroup_bpf(u
);
648 f
= open_memstream_unlocked(&buf
, &size
);
655 STRV_FOREACH(entry
, *filters
)
656 fprintf(f
, "%s=%s\n", name
, *entry
);
658 r
= fflush_and_check(f
);
662 unit_write_setting(u
, flags
, name
, buf
);
665 r
= bpf_firewall_supported();
668 if (r
!= BPF_FIREWALL_SUPPORTED_WITH_MULTI
) {
669 static bool warned
= false;
671 log_full(warned
? LOG_DEBUG
: LOG_WARNING
,
672 "Transient unit %s configures an IP firewall with BPF, but the local system does not support BPF/cgroup firewalling with multiple filters.\n"
673 "Starting this unit will fail! (This warning is only shown for the first started transient unit using IP firewalling.)", u
->id
);
680 } else if (streq(name
, "BPFProgram")) {
684 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
688 while ((r
= sd_bus_message_read(message
, "(ss)", &a
, &p
)) > 0) {
689 int attach_type
= bpf_cgroup_attach_type_from_string(a
);
691 return sd_bus_error_setf(
693 SD_BUS_ERROR_INVALID_ARGS
,
694 "%s expects a valid BPF attach type, got '%s'.",
697 if (!path_is_normalized(p
) || !path_is_absolute(p
))
698 return sd_bus_error_setf(
700 SD_BUS_ERROR_INVALID_ARGS
,
701 "%s= expects a normalized absolute path.",
704 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
705 r
= cgroup_add_bpf_foreign_program(c
, attach_type
, p
);
714 r
= sd_bus_message_exit_container(message
);
718 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
719 _cleanup_free_
char *buf
= NULL
;
720 _cleanup_fclose_
FILE *f
= NULL
;
721 CGroupBPFForeignProgram
*fp
;
725 while (c
->bpf_foreign_programs
)
726 cgroup_context_remove_bpf_foreign_program(c
, c
->bpf_foreign_programs
);
728 f
= open_memstream_unlocked(&buf
, &size
);
735 LIST_FOREACH(programs
, fp
, c
->bpf_foreign_programs
)
736 fprintf(f
, "%s=%s:%s\n", name
,
737 bpf_cgroup_attach_type_to_string(fp
->attach_type
),
740 r
= fflush_and_check(f
);
744 unit_write_setting(u
, flags
, name
, buf
);
746 if (!LIST_IS_EMPTY(c
->bpf_foreign_programs
)) {
747 r
= bpf_foreign_supported();
752 "Transient unit %s configures a BPF program pinned to BPF "
753 "filesystem, but the local system does not support that.\n"
754 "Starting this unit will fail!", u
->id
);
764 static int bus_cgroup_set_boolean(
769 sd_bus_message
*message
,
770 UnitWriteFlags flags
,
771 sd_bus_error
*error
) {
777 r
= sd_bus_message_read(message
, "b", &b
);
781 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
783 unit_invalidate_cgroup(u
, mask
);
784 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, yes_no(b
));
790 #define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \
791 static int bus_cgroup_set_##function( \
795 sd_bus_message *message, \
796 UnitWriteFlags flags, \
797 sd_bus_error *error) { \
804 r = sd_bus_message_read(message, "t", &v); \
809 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
810 "Value specified in %s is out of range", name); \
812 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
814 unit_invalidate_cgroup(u, mask); \
817 unit_write_settingf(u, flags, name, \
820 unit_write_settingf(u, flags, name, \
821 "%s=%" PRIu64, name, v); \
827 #define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \
828 static int bus_cgroup_set_##function( \
832 sd_bus_message *message, \
833 UnitWriteFlags flags, \
834 sd_bus_error *error) { \
841 r = sd_bus_message_read(message, "t", &v); \
846 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
847 "Value specified in %s is out of range", name); \
849 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
851 unit_invalidate_cgroup(u, mask); \
853 if (v == CGROUP_LIMIT_MAX) \
854 unit_write_settingf(u, flags, name, \
855 "%s=infinity", name); \
857 unit_write_settingf(u, flags, name, \
858 "%s=%" PRIu64, name, v); \
863 static int bus_cgroup_set_##function##_scale( \
867 sd_bus_message *message, \
868 UnitWriteFlags flags, \
869 sd_bus_error *error) { \
877 r = sd_bus_message_read(message, "u", &raw); \
881 v = scale(raw, UINT32_MAX); \
882 if (v < minimum || v >= UINT64_MAX) \
883 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
884 "Value specified in %s is out of range", name); \
886 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
888 unit_invalidate_cgroup(u, mask); \
890 /* Prepare to chop off suffix */ \
891 assert_se(endswith(name, "Scale")); \
893 int scaled = UINT32_SCALE_TO_PERMYRIAD(raw); \
894 unit_write_settingf(u, flags, name, "%.*s=" PERMYRIAD_AS_PERCENT_FORMAT_STR, \
895 (int)(strlen(name) - strlen("Scale")), name, \
896 PERMYRIAD_AS_PERCENT_FORMAT_VAL(scaled)); \
902 DISABLE_WARNING_TYPE_LIMITS
;
903 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight
, CGROUP_MASK_CPU
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
904 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares
, CGROUP_MASK_CPU
, CGROUP_CPU_SHARES_IS_OK
, CGROUP_CPU_SHARES_INVALID
);
905 BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight
, CGROUP_MASK_IO
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
906 BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight
, CGROUP_MASK_BLKIO
, CGROUP_BLKIO_WEIGHT_IS_OK
, CGROUP_BLKIO_WEIGHT_INVALID
);
907 BUS_DEFINE_SET_CGROUP_LIMIT(memory
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 1);
908 BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
909 BUS_DEFINE_SET_CGROUP_LIMIT(swap
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
912 static int bus_cgroup_set_tasks_max(
916 sd_bus_message
*message
,
917 UnitWriteFlags flags
,
918 sd_bus_error
*error
) {
925 r
= sd_bus_message_read(message
, "t", &v
);
930 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
931 "Value specified in %s is out of range", name
);
933 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
934 *p
= (TasksMax
) { .value
= v
, .scale
= 0 }; /* When .scale==0, .value is the absolute value */
935 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
937 if (v
== CGROUP_LIMIT_MAX
)
938 unit_write_settingf(u
, flags
, name
,
939 "%s=infinity", name
);
941 unit_write_settingf(u
, flags
, name
,
942 "%s=%" PRIu64
, name
, v
);
948 static int bus_cgroup_set_tasks_max_scale(
952 sd_bus_message
*message
,
953 UnitWriteFlags flags
,
954 sd_bus_error
*error
) {
961 r
= sd_bus_message_read(message
, "u", &v
);
965 if (v
< 1 || v
>= UINT32_MAX
)
966 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
967 "Value specified in %s is out of range", name
);
969 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
970 *p
= (TasksMax
) { v
, UINT32_MAX
}; /* .scale is not 0, so this is interpreted as v/UINT32_MAX. */
971 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
973 uint32_t scaled
= DIV_ROUND_UP((uint64_t) v
* 100U, (uint64_t) UINT32_MAX
);
974 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu32
".%" PRIu32
"%%", "TasksMax",
975 scaled
/ 10, scaled
% 10);
981 int bus_cgroup_set_property(
985 sd_bus_message
*message
,
986 UnitWriteFlags flags
,
987 sd_bus_error
*error
) {
989 CGroupIOLimitType iol_type
;
997 flags
|= UNIT_PRIVATE
;
999 if (streq(name
, "CPUAccounting"))
1000 return bus_cgroup_set_boolean(u
, name
, &c
->cpu_accounting
, get_cpu_accounting_mask(), message
, flags
, error
);
1002 if (streq(name
, "CPUWeight"))
1003 return bus_cgroup_set_cpu_weight(u
, name
, &c
->cpu_weight
, message
, flags
, error
);
1005 if (streq(name
, "StartupCPUWeight"))
1006 return bus_cgroup_set_cpu_weight(u
, name
, &c
->startup_cpu_weight
, message
, flags
, error
);
1008 if (streq(name
, "CPUShares"))
1009 return bus_cgroup_set_cpu_shares(u
, name
, &c
->cpu_shares
, message
, flags
, error
);
1011 if (streq(name
, "StartupCPUShares"))
1012 return bus_cgroup_set_cpu_shares(u
, name
, &c
->startup_cpu_shares
, message
, flags
, error
);
1014 if (streq(name
, "IOAccounting"))
1015 return bus_cgroup_set_boolean(u
, name
, &c
->io_accounting
, CGROUP_MASK_IO
, message
, flags
, error
);
1017 if (streq(name
, "IOWeight"))
1018 return bus_cgroup_set_io_weight(u
, name
, &c
->io_weight
, message
, flags
, error
);
1020 if (streq(name
, "StartupIOWeight"))
1021 return bus_cgroup_set_io_weight(u
, name
, &c
->startup_io_weight
, message
, flags
, error
);
1023 if (streq(name
, "BlockIOAccounting"))
1024 return bus_cgroup_set_boolean(u
, name
, &c
->blockio_accounting
, CGROUP_MASK_BLKIO
, message
, flags
, error
);
1026 if (streq(name
, "BlockIOWeight"))
1027 return bus_cgroup_set_blockio_weight(u
, name
, &c
->blockio_weight
, message
, flags
, error
);
1029 if (streq(name
, "StartupBlockIOWeight"))
1030 return bus_cgroup_set_blockio_weight(u
, name
, &c
->startup_blockio_weight
, message
, flags
, error
);
1032 if (streq(name
, "MemoryAccounting"))
1033 return bus_cgroup_set_boolean(u
, name
, &c
->memory_accounting
, CGROUP_MASK_MEMORY
, message
, flags
, error
);
1035 if (streq(name
, "MemoryMin")) {
1036 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->memory_min
, message
, flags
, error
);
1038 c
->memory_min_set
= true;
1042 if (streq(name
, "MemoryLow")) {
1043 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->memory_low
, message
, flags
, error
);
1045 c
->memory_low_set
= true;
1049 if (streq(name
, "DefaultMemoryMin")) {
1050 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->default_memory_min
, message
, flags
, error
);
1052 c
->default_memory_min_set
= true;
1056 if (streq(name
, "DefaultMemoryLow")) {
1057 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->default_memory_low
, message
, flags
, error
);
1059 c
->default_memory_low_set
= true;
1063 if (streq(name
, "MemoryHigh"))
1064 return bus_cgroup_set_memory(u
, name
, &c
->memory_high
, message
, flags
, error
);
1066 if (streq(name
, "MemorySwapMax"))
1067 return bus_cgroup_set_swap(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
1069 if (streq(name
, "MemoryMax"))
1070 return bus_cgroup_set_memory(u
, name
, &c
->memory_max
, message
, flags
, error
);
1072 if (streq(name
, "MemoryLimit"))
1073 return bus_cgroup_set_memory(u
, name
, &c
->memory_limit
, message
, flags
, error
);
1075 if (streq(name
, "MemoryMinScale")) {
1076 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->memory_min
, message
, flags
, error
);
1078 c
->memory_min_set
= true;
1082 if (streq(name
, "MemoryLowScale")) {
1083 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->memory_low
, message
, flags
, error
);
1085 c
->memory_low_set
= true;
1089 if (streq(name
, "DefaultMemoryMinScale")) {
1090 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->default_memory_min
, message
, flags
, error
);
1092 c
->default_memory_min_set
= true;
1096 if (streq(name
, "DefaultMemoryLowScale")) {
1097 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->default_memory_low
, message
, flags
, error
);
1099 c
->default_memory_low_set
= true;
1103 if (streq(name
, "MemoryHighScale"))
1104 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_high
, message
, flags
, error
);
1106 if (streq(name
, "MemorySwapMaxScale"))
1107 return bus_cgroup_set_swap_scale(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
1109 if (streq(name
, "MemoryMaxScale"))
1110 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_max
, message
, flags
, error
);
1112 if (streq(name
, "MemoryLimitScale"))
1113 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_limit
, message
, flags
, error
);
1115 if (streq(name
, "TasksAccounting"))
1116 return bus_cgroup_set_boolean(u
, name
, &c
->tasks_accounting
, CGROUP_MASK_PIDS
, message
, flags
, error
);
1118 if (streq(name
, "TasksMax"))
1119 return bus_cgroup_set_tasks_max(u
, name
, &c
->tasks_max
, message
, flags
, error
);
1121 if (streq(name
, "TasksMaxScale"))
1122 return bus_cgroup_set_tasks_max_scale(u
, name
, &c
->tasks_max
, message
, flags
, error
);
1124 if (streq(name
, "CPUQuotaPerSecUSec")) {
1127 r
= sd_bus_message_read(message
, "t", &u64
);
1132 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "CPUQuotaPerSecUSec= value out of range");
1134 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1135 c
->cpu_quota_per_sec_usec
= u64
;
1136 u
->warned_clamping_cpu_quota_period
= false;
1137 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
1139 if (c
->cpu_quota_per_sec_usec
== USEC_INFINITY
)
1140 unit_write_setting(u
, flags
, "CPUQuota", "CPUQuota=");
1142 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
1144 unit_write_settingf(u
, flags
, "CPUQuota",
1146 (double) (c
->cpu_quota_per_sec_usec
/ 10000));
1151 } else if (streq(name
, "CPUQuotaPeriodUSec")) {
1154 r
= sd_bus_message_read(message
, "t", &u64
);
1158 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1159 c
->cpu_quota_period_usec
= u64
;
1160 u
->warned_clamping_cpu_quota_period
= false;
1161 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
1162 if (c
->cpu_quota_period_usec
== USEC_INFINITY
)
1163 unit_write_setting(u
, flags
, "CPUQuotaPeriodSec", "CPUQuotaPeriodSec=");
1165 unit_write_settingf(u
, flags
, "CPUQuotaPeriodSec",
1166 "CPUQuotaPeriodSec=%s",
1167 FORMAT_TIMESPAN(c
->cpu_quota_period_usec
, 1));
1172 } else if (STR_IN_SET(name
, "AllowedCPUs", "AllowedMemoryNodes")) {
1175 _cleanup_(cpu_set_reset
) CPUSet new_set
= {};
1177 r
= sd_bus_message_read_array(message
, 'y', &a
, &n
);
1181 r
= cpu_set_from_dbus(a
, n
, &new_set
);
1185 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1186 _cleanup_free_
char *setstr
= NULL
;
1189 setstr
= cpu_set_to_range_string(&new_set
);
1193 if (streq(name
, "AllowedCPUs"))
1194 set
= &c
->cpuset_cpus
;
1196 set
= &c
->cpuset_mems
;
1200 new_set
= (CPUSet
) {};
1202 unit_invalidate_cgroup(u
, CGROUP_MASK_CPUSET
);
1203 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, setstr
);
1208 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
1213 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1217 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
1219 if (!path_is_normalized(path
))
1220 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1222 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1223 CGroupIODeviceLimit
*a
= NULL
, *b
;
1225 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
) {
1226 if (path_equal(path
, b
->path
)) {
1233 CGroupIOLimitType type
;
1235 a
= new0(CGroupIODeviceLimit
, 1);
1239 a
->path
= strdup(path
);
1245 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
1246 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
1248 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
1251 a
->limits
[iol_type
] = u64
;
1259 r
= sd_bus_message_exit_container(message
);
1263 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1264 CGroupIODeviceLimit
*a
;
1265 _cleanup_free_
char *buf
= NULL
;
1266 _cleanup_fclose_
FILE *f
= NULL
;
1270 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
1271 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
1274 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1276 f
= open_memstream_unlocked(&buf
, &size
);
1280 fprintf(f
, "%s=\n", name
);
1281 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
1282 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
1283 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
1285 r
= fflush_and_check(f
);
1288 unit_write_setting(u
, flags
, name
, buf
);
1293 } else if (streq(name
, "IODeviceWeight")) {
1298 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1302 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
1304 if (!path_is_normalized(path
))
1305 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1307 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
1308 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "IODeviceWeight= value out of range");
1310 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1311 CGroupIODeviceWeight
*a
= NULL
, *b
;
1313 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
) {
1314 if (path_equal(b
->path
, path
)) {
1321 a
= new0(CGroupIODeviceWeight
, 1);
1325 a
->path
= strdup(path
);
1330 LIST_PREPEND(device_weights
, c
->io_device_weights
, a
);
1339 r
= sd_bus_message_exit_container(message
);
1343 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1344 _cleanup_free_
char *buf
= NULL
;
1345 _cleanup_fclose_
FILE *f
= NULL
;
1346 CGroupIODeviceWeight
*a
;
1350 while (c
->io_device_weights
)
1351 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
1354 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1356 f
= open_memstream_unlocked(&buf
, &size
);
1360 fputs("IODeviceWeight=\n", f
);
1361 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
1362 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1364 r
= fflush_and_check(f
);
1367 unit_write_setting(u
, flags
, name
, buf
);
1372 } else if (streq(name
, "IODeviceLatencyTargetUSec")) {
1377 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1381 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &target
)) > 0) {
1383 if (!path_is_normalized(path
))
1384 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1386 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1387 CGroupIODeviceLatency
*a
= NULL
, *b
;
1389 LIST_FOREACH(device_latencies
, b
, c
->io_device_latencies
) {
1390 if (path_equal(b
->path
, path
)) {
1397 a
= new0(CGroupIODeviceLatency
, 1);
1401 a
->path
= strdup(path
);
1406 LIST_PREPEND(device_latencies
, c
->io_device_latencies
, a
);
1409 a
->target_usec
= target
;
1415 r
= sd_bus_message_exit_container(message
);
1419 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1420 _cleanup_free_
char *buf
= NULL
;
1421 _cleanup_fclose_
FILE *f
= NULL
;
1422 CGroupIODeviceLatency
*a
;
1426 while (c
->io_device_latencies
)
1427 cgroup_context_free_io_device_latency(c
, c
->io_device_latencies
);
1430 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1432 f
= open_memstream_unlocked(&buf
, &size
);
1436 fputs("IODeviceLatencyTargetSec=\n", f
);
1437 LIST_FOREACH(device_latencies
, a
, c
->io_device_latencies
)
1438 fprintf(f
, "IODeviceLatencyTargetSec=%s %s\n",
1439 a
->path
, FORMAT_TIMESPAN(a
->target_usec
, 1));
1441 r
= fflush_and_check(f
);
1444 unit_write_setting(u
, flags
, name
, buf
);
1449 } else if (STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1455 if (streq(name
, "BlockIOWriteBandwidth"))
1458 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1462 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
1464 if (!path_is_normalized(path
))
1465 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1467 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1468 CGroupBlockIODeviceBandwidth
*a
= NULL
, *b
;
1470 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
1471 if (path_equal(path
, b
->path
)) {
1478 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
1482 a
->rbps
= CGROUP_LIMIT_MAX
;
1483 a
->wbps
= CGROUP_LIMIT_MAX
;
1484 a
->path
= strdup(path
);
1490 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
1504 r
= sd_bus_message_exit_container(message
);
1508 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1509 CGroupBlockIODeviceBandwidth
*a
;
1510 _cleanup_free_
char *buf
= NULL
;
1511 _cleanup_fclose_
FILE *f
= NULL
;
1515 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
1517 a
->rbps
= CGROUP_LIMIT_MAX
;
1519 a
->wbps
= CGROUP_LIMIT_MAX
;
1523 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1525 f
= open_memstream_unlocked(&buf
, &size
);
1530 fputs("BlockIOReadBandwidth=\n", f
);
1531 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
1532 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
1533 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
1535 fputs("BlockIOWriteBandwidth=\n", f
);
1536 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
1537 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
1538 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
1541 r
= fflush_and_check(f
);
1545 unit_write_setting(u
, flags
, name
, buf
);
1550 } else if (streq(name
, "BlockIODeviceWeight")) {
1555 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1559 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
1561 if (!path_is_normalized(path
))
1562 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1564 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
1565 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "BlockIODeviceWeight= out of range");
1567 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1568 CGroupBlockIODeviceWeight
*a
= NULL
, *b
;
1570 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
) {
1571 if (path_equal(b
->path
, path
)) {
1578 a
= new0(CGroupBlockIODeviceWeight
, 1);
1582 a
->path
= strdup(path
);
1587 LIST_PREPEND(device_weights
, c
->blockio_device_weights
, a
);
1596 r
= sd_bus_message_exit_container(message
);
1600 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1601 _cleanup_free_
char *buf
= NULL
;
1602 _cleanup_fclose_
FILE *f
= NULL
;
1603 CGroupBlockIODeviceWeight
*a
;
1607 while (c
->blockio_device_weights
)
1608 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
1611 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1613 f
= open_memstream_unlocked(&buf
, &size
);
1617 fputs("BlockIODeviceWeight=\n", f
);
1618 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
1619 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1621 r
= fflush_and_check(f
);
1625 unit_write_setting(u
, flags
, name
, buf
);
1630 } else if (streq(name
, "DevicePolicy")) {
1632 CGroupDevicePolicy p
;
1634 r
= sd_bus_message_read(message
, "s", &policy
);
1638 p
= cgroup_device_policy_from_string(policy
);
1642 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1643 c
->device_policy
= p
;
1644 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1645 unit_write_settingf(u
, flags
, name
, "DevicePolicy=%s", policy
);
1650 } else if (streq(name
, "DeviceAllow")) {
1651 const char *path
, *rwm
;
1654 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
1658 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
1660 if (!valid_device_allow_pattern(path
) || strpbrk(path
, WHITESPACE
))
1661 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires device node or pattern");
1665 else if (!in_charset(rwm
, "rwm"))
1666 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires combination of rwm flags");
1668 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1669 CGroupDeviceAllow
*a
= NULL
, *b
;
1671 LIST_FOREACH(device_allow
, b
, c
->device_allow
) {
1672 if (path_equal(b
->path
, path
)) {
1679 a
= new0(CGroupDeviceAllow
, 1);
1683 a
->path
= strdup(path
);
1689 LIST_PREPEND(device_allow
, c
->device_allow
, a
);
1692 a
->r
= strchr(rwm
, 'r');
1693 a
->w
= strchr(rwm
, 'w');
1694 a
->m
= strchr(rwm
, 'm');
1702 r
= sd_bus_message_exit_container(message
);
1706 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1707 _cleanup_free_
char *buf
= NULL
;
1708 _cleanup_fclose_
FILE *f
= NULL
;
1709 CGroupDeviceAllow
*a
;
1713 while (c
->device_allow
)
1714 cgroup_context_free_device_allow(c
, c
->device_allow
);
1717 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1719 f
= open_memstream_unlocked(&buf
, &size
);
1723 fputs("DeviceAllow=\n", f
);
1724 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
1725 fprintf(f
, "DeviceAllow=%s %s%s%s\n", a
->path
, a
->r
? "r" : "", a
->w
? "w" : "", a
->m
? "m" : "");
1727 r
= fflush_and_check(f
);
1730 unit_write_setting(u
, flags
, name
, buf
);
1735 } else if (streq(name
, "IPAccounting")) {
1738 r
= sd_bus_message_read(message
, "b", &b
);
1742 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1743 c
->ip_accounting
= b
;
1745 unit_invalidate_cgroup_bpf(u
);
1746 unit_write_settingf(u
, flags
, name
, "IPAccounting=%s", yes_no(b
));
1751 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1752 _cleanup_set_free_ Set
*new_prefixes
= NULL
;
1755 r
= sd_bus_message_enter_container(message
, 'a', "(iayu)");
1765 r
= sd_bus_message_enter_container(message
, 'r', "iayu");
1771 r
= sd_bus_message_read(message
, "i", &family
);
1775 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1776 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects IPv4 or IPv6 addresses only.", name
);
1778 r
= sd_bus_message_read_array(message
, 'y', &ap
, &an
);
1782 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1783 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1784 af_to_name(family
), FAMILY_ADDRESS_SIZE(family
), an
);
1786 r
= sd_bus_message_read(message
, "u", &prefixlen
);
1790 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
)*8)
1791 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
));
1793 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1794 struct in_addr_prefix prefix
= {
1796 .prefixlen
= prefixlen
,
1799 memcpy(&prefix
.address
, ap
, an
);
1801 r
= in_addr_prefix_add(&new_prefixes
, &prefix
);
1806 r
= sd_bus_message_exit_container(message
);
1813 r
= sd_bus_message_exit_container(message
);
1817 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1818 _cleanup_free_
char *buf
= NULL
;
1819 _cleanup_fclose_
FILE *f
= NULL
;
1824 unit_invalidate_cgroup_bpf(u
);
1825 f
= open_memstream_unlocked(&buf
, &size
);
1829 prefixes
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow
: &c
->ip_address_deny
;
1830 reduced
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow_reduced
: &c
->ip_address_deny_reduced
;
1834 *prefixes
= set_free(*prefixes
);
1838 struct in_addr_prefix
*p
;
1842 r
= in_addr_prefixes_merge(prefixes
, new_prefixes
);
1846 SET_FOREACH(p
, new_prefixes
) {
1847 _cleanup_free_
char *buffer
= NULL
;
1849 r
= in_addr_prefix_to_string(p
->family
, &p
->address
, p
->prefixlen
, &buffer
);
1855 fprintf(f
, "%s=%s\n", name
, buffer
);
1859 r
= fflush_and_check(f
);
1863 unit_write_setting(u
, flags
, name
, buf
);
1869 if (STR_IN_SET(name
, "ManagedOOMSwap", "ManagedOOMMemoryPressure")) {
1870 ManagedOOMMode
*cgroup_mode
= streq(name
, "ManagedOOMSwap") ? &c
->moom_swap
: &c
->moom_mem_pressure
;
1874 if (!UNIT_VTABLE(u
)->can_set_managed_oom
)
1875 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot set %s for this unit type", name
);
1877 r
= sd_bus_message_read(message
, "s", &mode
);
1881 m
= managed_oom_mode_from_string(mode
);
1885 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1887 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, mode
);
1890 (void) manager_varlink_send_managed_oom_update(u
);
1894 if (streq(name
, "ManagedOOMMemoryPressureLimit")) {
1897 if (!UNIT_VTABLE(u
)->can_set_managed_oom
)
1898 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot set %s for this unit type", name
);
1900 r
= sd_bus_message_read(message
, "u", &v
);
1904 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1905 c
->moom_mem_pressure_limit
= v
;
1906 unit_write_settingf(u
, flags
, name
,
1907 "ManagedOOMMemoryPressureLimit=" PERMYRIAD_AS_PERCENT_FORMAT_STR
,
1908 PERMYRIAD_AS_PERCENT_FORMAT_VAL(UINT32_SCALE_TO_PERMYRIAD(v
)));
1911 if (c
->moom_mem_pressure
== MANAGED_OOM_KILL
)
1912 (void) manager_varlink_send_managed_oom_update(u
);
1917 if (streq(name
, "ManagedOOMPreference")) {
1918 ManagedOOMPreference p
;
1921 r
= sd_bus_message_read(message
, "s", &pref
);
1925 p
= managed_oom_preference_from_string(pref
);
1929 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1930 c
->moom_preference
= p
;
1931 unit_write_settingf(u
, flags
, name
, "ManagedOOMPreference=%s", pref
);
1936 if (STR_IN_SET(name
, "SocketBindAllow", "SocketBindDeny")) {
1937 CGroupSocketBindItem
**list
;
1938 uint16_t nr_ports
, port_min
;
1940 int32_t family
, ip_protocol
;
1942 list
= streq(name
, "SocketBindAllow") ? &c
->socket_bind_allow
: &c
->socket_bind_deny
;
1944 r
= sd_bus_message_enter_container(message
, 'a', "(iiqq)");
1948 while ((r
= sd_bus_message_read(message
, "(iiqq)", &family
, &ip_protocol
, &nr_ports
, &port_min
)) > 0) {
1950 if (!IN_SET(family
, AF_UNSPEC
, AF_INET
, AF_INET6
))
1951 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects INET or INET6 family, if specified.", name
);
1953 if (!IN_SET(ip_protocol
, 0, IPPROTO_TCP
, IPPROTO_UDP
))
1954 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects TCP or UDP protocol, if specified.", name
);
1956 if (port_min
+ (uint32_t) nr_ports
> (1 << 16))
1957 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects maximum port value lesser than 65536.", name
);
1959 if (port_min
== 0 && nr_ports
!= 0)
1960 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects port range starting with positive value.", name
);
1962 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1963 _cleanup_free_ CGroupSocketBindItem
*item
= NULL
;
1965 item
= new(CGroupSocketBindItem
, 1);
1969 *item
= (CGroupSocketBindItem
) {
1970 .address_family
= family
,
1971 .ip_protocol
= ip_protocol
,
1972 .nr_ports
= nr_ports
,
1973 .port_min
= port_min
1976 LIST_PREPEND(socket_bind_items
, *list
, TAKE_PTR(item
));
1983 r
= sd_bus_message_exit_container(message
);
1987 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1988 _cleanup_free_
char *buf
= NULL
;
1989 _cleanup_fclose_
FILE *f
= NULL
;
1990 CGroupSocketBindItem
*item
;
1994 cgroup_context_remove_socket_bind(list
);
1996 if ((u
->manager
->cgroup_supported
& CGROUP_MASK_BPF_SOCKET_BIND
) == 0)
1998 "Unit %s configures source compiled BPF programs "
1999 "but the local system does not support that.\n"
2000 "Starting this unit will fail!", u
->id
);
2003 f
= open_memstream_unlocked(&buf
, &size
);
2007 fprintf(f
, "%s:", name
);
2009 LIST_FOREACH(socket_bind_items
, item
, *list
)
2010 cgroup_context_dump_socket_bind_item(item
, f
);
2014 r
= fflush_and_check(f
);
2018 unit_write_setting(u
, flags
, name
, buf
);
2023 if (streq(name
, "RestrictNetworkInterfaces")) {
2025 _cleanup_strv_free_
char **l
= NULL
;
2027 r
= sd_bus_message_enter_container(message
, 'r', "bas");
2031 r
= sd_bus_message_read(message
, "b", &is_allow_list
);
2035 r
= sd_bus_message_read_strv(message
, &l
);
2039 r
= sd_bus_message_exit_container(message
);
2043 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2044 _cleanup_free_
char *joined
= NULL
;
2047 if (strv_isempty(l
)) {
2048 c
->restrict_network_interfaces_is_allow_list
= false;
2049 c
->restrict_network_interfaces
= set_free(c
->restrict_network_interfaces
);
2051 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2055 if (set_isempty(c
->restrict_network_interfaces
))
2056 c
->restrict_network_interfaces_is_allow_list
= is_allow_list
;
2058 STRV_FOREACH(s
, l
) {
2059 if (!ifname_valid(*s
)) {
2060 log_full(LOG_WARNING
, "Invalid interface name, ignoring: %s", *s
);
2063 if (c
->restrict_network_interfaces_is_allow_list
!= (bool) is_allow_list
)
2064 free(set_remove(c
->restrict_network_interfaces
, *s
));
2066 r
= set_put_strdup(&c
->restrict_network_interfaces
, *s
);
2072 joined
= strv_join(l
, " ");
2076 unit_write_settingf(u
, flags
, name
, "%s=%s%s", name
, is_allow_list
? "" : "~", joined
);
2082 if (streq(name
, "DisableControllers") || (u
->transient
&& u
->load_state
== UNIT_STUB
))
2083 return bus_cgroup_set_transient_property(u
, c
, name
, message
, flags
, error
);